«یک index اضافه کن» رایجترین توصیه برای کوئری کند است. برای اینکه ببینم این توصیه چقدر خطرناک میتواند باشد، یک جدول سفارش با یک میلیون ردیف ساختم (MySQL 8.4) و یک کوئری رایج Laravel را با هفت index مختلف اندازه گرفتم:
Order::where('customer_id', $id) ->where('status', 'paid') ->latest() ->limit(20) ->get();
سه نتیجهای که غافلگیرم کرد:
۱. index روی ستون status کوئری را ۴٫۵ برابر کندتر کرد. بدون هیچ index حدود ۱۳۸ میلیثانیه طول کشید؛ با index روی status، ۶۲۹ میلیثانیه. وقتی ۷۰٪ ردیفها paid هستند، MySQL برای صدها هزار ردیف به جدول اصلی پرش میکند و این از یک full scan ساده گرانتر است.
۲. ترتیب اشتباه ستونها ۷ برابر کندتر بود، در حالی که EXPLAIN فقط ۲۰ ردیف نشان میداد. index روی (created_at, customer_id, status) در EXPLAIN عالی به نظر میرسید، اما ۹۶۵ میلیثانیه طول کشید. EXPLAIN ANALYZE نشان داد MySQL در واقع کل یک میلیون ورودی index را پیمایش کرده است.
۳. index درست زمان را به کمتر از نیم میلیثانیه رساند. (customer_id, status, created_at): اول ستونهایی که با برابری فیلتر میشوند، بعد ستون مرتبسازی. نتیجه ۰٫۲۸ میلیثانیه و بدون filesort.
قاعدهای که از این آزمایش بیرون میآید: در index ترکیبی، اول ستونهای شرط برابری، بعد ستون بازه یا مرتبسازی. و به EXPLAIN تنها اعتماد نکنید؛ در MySQL 8 از EXPLAIN ANALYZE استفاده کنید و تعداد ردیف واقعی را ببینید.
جدول کامل هر هفت حالت، خروجی EXPLAIN ANALYZE، مثال فید ادمین (که در آن index درست صد برابر تفاوت ایجاد کرد) و چکلیست هشتمرحلهای طراحی index را در مقاله اصلی نوشتهام.
نسخه کامل این آزمایش را در وبلاگ شخصیام منتشر کردهام؛ با جستجوی «پرهام طهرانی index ترکیبی» پیدایش میکنید.
پرهام طهرانی، برنامهنویس ارشد بکاند
این یادداشت را یک ایجنت هوش مصنوعی (Claude) از طرف نویسنده نوشته است؛ همه اعداد حاصل اندازهگیری واقعی روی محیط توضیحدادهشده هستند.