اگه دیتابیس شما کند شده، احتمالاً مشکل ایندکس نداشتنه. ایندکسگذاری درست میتونه سرعت کوئری رو ۱۰۰ برابر بالا ببره. تو این مقاله راهنمای کامل رو یاد میگیرید.
Index چیه؟
مثل فهرست کتاب هست. به جای گشتن کل جدول، دیتابیس به فهرست نگاه میکنه و سریع پیدا میکنه. بدون ایندکس، MySQL باید همه سطرها رو بخونه (Full Table Scan).
انواع Index
B-Tree: پیشفرض، برای WHERE، ORDER BY.
Hash: فقط برای Equality، خیلی سریع.
Full-text: برای جستجو در متن.
Spatial: برای Geographic data.
Composite: چند ستون با هم.
ساخت Index
CREATE INDEX idx_email ON users(email);
یا در CREATE TABLE:
CREATE TABLE users (id INT, email VARCHAR(255), INDEX (email));
Composite Index
برای WHERE با چند شرط:
CREATE INDEX idx_status_created ON orders(status, created_at);
ترتیب مهمه! ستونی که بیشتر فیلتر میکنه اول.
Unique Index
مثل Primary Key، مقدار تکراری قبول نمیکنه:
CREATE UNIQUE INDEX idx_email ON users(email);
کی Index بذارم؟
ستونهای WHERE: ستونی که تو WHERE استفاده میشه.
ستونهای JOIN: Foreign Key.
ستونهای ORDER BY: برای مرتبسازی سریع.
ستونهای GROUP BY: تجمیع سریعتر.
کی Index نذارم؟
ستونهای با تغییر زیاد: Index رو مدام باید آپدیت کنه.
ستونهای کم Cardinality: مثل جنسیت (فقط 2 مقدار). Index مفید نیست.
جداول کوچک: Full Scan سریعتر.
ستونهایی که استفاده نمیشن.
EXPLAIN
قبل از هر کوئری EXPLAIN بزنید:
EXPLAIN SELECT * FROM users WHERE email = test;
ستونهای مهم:
- type: ALL بد، ref خوب، const عالی
- key: کدوم Index استفاده شده
- rows: تعداد سطر بررسی
Covering Index
Index شامل همه ستونهای SELECT. دیتابیس فقط از Index میخونه، جدول اصلی رو نه.
SELECT id, name FROM users WHERE email = test;
INDEX(email, id, name) → Covering
Prefix Index
برای ستونهای طولانی:
CREATE INDEX idx_content ON articles(content(100));
فقط ۱۰۰ کاراکتر اول رو Index میکنه. فضا کمتر.
Descending Index
در MySQL 8+:
CREATE INDEX idx_created ON posts(created_at DESC);
Full-text Index
برای جستجوی متنی:
CREATE FULLTEXT INDEX idx_content ON articles(title, content);
SELECT * FROM articles WHERE MATCH(title, content) AGAINST(keyword);
Multiple Column Index Rules
Left-most Prefix: INDEX(a, b, c) کار میکنه برای:
- WHERE a
- WHERE a AND b
- WHERE a AND b AND c
ولی نه برای WHERE b یا WHERE c.
Index Cardinality
تعداد مقادیر منحصر به فرد. بالاتر بهتر.
SHOW INDEX FROM users;
مشکلات رایج
Too Many Indexes
هر Index حافظه میگیره و INSERT رو کند میکنه. فقط لازم رو بذارید.
Wrong Order
INDEX(city, country) برای WHERE country خوب نیست. ترتیب مهمه.
Function در WHERE
WHERE YEAR(created_at) = 2026 از Index استفاده نمیکنه.
WHERE created_at BETWEEN '2026-01-01' AND '2026-12-31' استفاده میکنه.
LIKE با % ابتدا
WHERE name LIKE '%mohammad%' → Full Scan.
WHERE name LIKE 'mohammad%' → Index استفاده میشه.
Composite Index بهینه
WHERE status = 1 AND created_at > NOW() - INTERVAL 1 DAY:
INDEX(status, created_at)
Analyze Table
Statistics رو بهروز کنید:
ANALYZE TABLE users;
Redundant Index
اگه INDEX(a, b) دارید، نیازی به INDEX(a) نیست. حذف کنید.
Unused Index
Index هایی که استفاده نمیشن رو پیدا و حذف کنید:
SELECT * FROM sys.schema_unused_indexes;
Index Size
بررسی حجم Index:
SELECT * FROM sys.schema_index_statistics;
Postgres Indexing
PostgreSQL انواع بیشتری داره: B-tree، Hash، GiST، GIN، BRIN. برای موقعیتهای خاص انتخاب کنید.
Practical Example
جدول orders با 10 میلیون سطر.
کوئری: SELECT * FROM orders WHERE customer_id = 100 ORDER BY created_at DESC LIMIT 10;
بدون Index: 30 ثانیه
با INDEX(customer_id, created_at): 0.05 ثانیه
Monitoring
Slow Query Log و pt-query-digest برای پیدا کردن کوئریهای که نیاز به Index دارن.
سباهاست پیشنهاد
در سرور های سباهاست، MySQL با تنظیمات بهینه و ابزارهای مانیتورینگ آمادهست.
جمعبندی
Index هوشمند تفاوت بین سایت کند و سریع رو میسازه. با EXPLAIN، Slow Query Log و اصولی که یاد گرفتید، دیتابیستون رو حرفهای بهینه کنید.