Execution Plan কী?
Execution Plan হলো ডেটাবেজ Query Optimizer-এর তৈরি করা একটি Blueprint বা পরিকল্পনা যে কীভাবে একটি SQL Query কার্যকর করা হবে। কোন Index ব্যবহার হবে, কীভাবে টেবিল Join হবে, কতটি Row স্ক্যান হবে — এসব তথ্য Execution Plan-এ থাকে।
কেন Execution Plan গুরুত্বপূর্ণ?
- Slow Query খুঁজে বের করা: কেন Query ধীর তা বুঝতে সাহায্য করে
- Index কার্যকর কিনা যাচাই: Index ব্যবহার হচ্ছে কিনা দেখা যায়
- Query Optimization: কোথায় উন্নতি করা যাবে বোঝা যায়
- Full Table Scan শনাক্ত: অপ্রয়োজনীয় Full Scan ধরা যায়
EXPLAIN কমান্ড
MySQL-এ EXPLAIN
-- Basic EXPLAIN
EXPLAIN SELECT * FROM employees WHERE email = 'test@test.com';
-- Output:
-- +----+-------------+-----------+------+----------------+----------------+---------+-------+------+---------+
-- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
-- +----+-------------+-----------+------+----------------+----------------+---------+-------+------+---------+
-- | 1 | SIMPLE | employees | ref | idx_emp_email | idx_emp_email | 768 | const | 1 | ... |
-- +----+-------------+-----------+------+----------------+----------------+---------+-------+------+---------+
মূল কলামের অর্থ:
| কলাম | অর্থ |
|---|---|
type |
কিভাবে টেবিল এক্সেস করা হচ্ছে (const, ref, range, ALL) |
possible_keys |
কোন Index ব্যবহার হতে পারে |
key |
কোন Index আসলে ব্যবহার হচ্ছে |
rows |
কতটি Row স্ক্যান হবে (আনুমানিক) |
Extra |
অতিরিক্ত তথ্য (Using index, Using filesort) |
type কলামের মান (সেরা থেকে সবচেয়ে খারাপ):
const → Primary Key বা Unique Key দিয়ে একটি Row (সবচেয়ে দ্রুত)
eq_ref → JOIN-এ Primary Key ব্যবহার
ref → Non-unique Index ব্যবহার
range → Index-এ Range scan
index → Full Index scan
ALL → Full Table scan (সবচেয়ে ধীর — এড়িয়ে চলুন!)
PostgreSQL-এ EXPLAIN
-- Basic EXPLAIN
EXPLAIN SELECT * FROM employees WHERE salary > 50000;
-- EXPLAIN ANALYZE: আনুমানিক নয়, আসল সময় দেখায়
EXPLAIN ANALYZE SELECT * FROM employees WHERE salary > 50000;
-- Output:
-- Seq Scan on employees (cost=0.00..2847.00 rows=9745 width=65) (actual time=0.012..15.234 rows=9741 loops=1)
-- Filter: (salary > 50000)
-- Rows Removed by Filter: 255
-- Planning Time: 0.134 ms
-- Execution Time: 15.891 ms
PostgreSQL Output বোঝার গাইড:
Seq Scan → Sequential (Full) Table Scan (ধীর)
Index Scan → Index ব্যবহার করছে (দ্রুত)
Index Only Scan → Covering Index (সবচেয়ে দ্রুত)
Bitmap Heap Scan → Bitmap Index Scan (মাঝারি)
cost=0.00..2847.00 → (startup cost)..(total cost)
rows=9745 → আনুমানিক Row সংখ্যা
actual time=0.012..15.234 → আসল সময় (ANALYZE দিলে)
সাধারণ সমস্যা ও সমাধান
১. Full Table Scan (ALL)
-- সমস্যা: Index নেই
EXPLAIN SELECT * FROM orders WHERE status = 'PENDING';
-- type: ALL, rows: 1000000 (ধীর!)
-- সমাধান: Index যোগ করুন
CREATE INDEX idx_orders_status ON orders(status);
-- এখন:
-- type: ref, rows: 150 (দ্রুত!)
২. Index ব্যবহার না হওয়া
-- সমস্যা: Function ব্যবহার Index নষ্ট করে
EXPLAIN SELECT * FROM employees WHERE YEAR(hire_date) = 2023;
-- type: ALL (Index নেই!)
-- সমাধান: Range Query ব্যবহার
SELECT * FROM employees
WHERE hire_date BETWEEN '2023-01-01' AND '2023-12-31';
-- type: range (Index ব্যবহার হচ্ছে!)
৩. Filesort সমস্যা
-- সমস্যা: ORDER BY-তে Index নেই
EXPLAIN SELECT * FROM products ORDER BY price DESC LIMIT 20;
-- Extra: Using filesort (ধীর!)
-- সমাধান: price-এ Index যোগ করুন
CREATE INDEX idx_products_price ON products(price DESC);
-- Extra: Using index (দ্রুত!)
Spring Boot-এ Slow Query Log
# application.properties-এ Slow Query লগ করুন
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# Slow Query threshold: 100ms এর বেশি লাগলে log করো
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql=TRACE
// Hibernate Statistics দিয়ে Query Performance দেখুন
@Configuration
public class HibernateConfig {
@Bean
public HibernatePropertiesCustomizer hibernateStatistics() {
return properties -> {
properties.put(AvailableSettings.GENERATE_STATISTICS, true);
properties.put(AvailableSettings.LOG_SLOW_QUERIES, 100); // 100ms
};
}
}
EXPLAIN ANALYZE বাস্তব উদাহরণ
-- জটিল JOIN Query-র Execution Plan
EXPLAIN ANALYZE
SELECT c.name, COUNT(o.id) as order_count, SUM(o.total) as total_spent
FROM customers c
JOIN orders o ON c.id = o.customer_id
WHERE o.created_at > '2024-01-01'
GROUP BY c.id, c.name
ORDER BY total_spent DESC
LIMIT 10;
-- Output বিশ্লেষণ:
-- Limit (cost=... rows=10) (actual time=234.5..234.6 rows=10)
-- Sort (cost=... rows=...) (actual time=234.5..234.5 rows=10)
-- HashAggregate (cost=...) (actual time=230.1..231.2 rows=1523)
-- Hash Join (cost=...) (actual time=12.3..225.6 rows=45231)
-- Seq Scan on customers ← Index নেই!
-- Index Scan on orders ← Index আছে (created_at index)
-- সমাধান: customers-এ Index যোগ করুন
-- CREATE INDEX idx_customers_id ON customers(id);
সংক্ষেপে
| বিষয় | বিবরণ |
|---|---|
| Execution Plan | Query কিভাবে চলবে তার পরিকল্পনা |
EXPLAIN |
MySQL/PostgreSQL-এ Plan দেখানোর কমান্ড |
EXPLAIN ANALYZE |
আসল সময় সহ Plan (PostgreSQL) |
type: ALL |
Full Table Scan — সবচেয়ে ধীর |
type: const |
Exact match — সবচেয়ে দ্রুত |
Using filesort |
ORDER BY-তে Index নেই |
Using index |
Covering Index ব্যবহার হচ্ছে |
উপসংহার
Execution Plan ডেটাবেজ Performance Tuning-এর সবচেয়ে গুরুত্বপূর্ণ টুল। EXPLAIN কমান্ড ব্যবহার করে Full Table Scan শনাক্ত করুন, Index কার্যকরতা যাচাই করুন এবং Slow Query Optimize করুন। Spring Boot-এ Hibernate Statistics এবং Slow Query Log সক্রিয় রাখলে Performance সমস্যা দ্রুত ধরা যায়।