تصور کنید یک برنامهنویس برای افزایش سرعت دیتابیس، پیشنهادهای یک مدل زبانی را بدون چون و چرا اجرا کند و ناگهان با کند شدن کل سیستم مواجه شود. این همان تلهای است که ابزار جدید pg-index-referee برای جلوگیری از آن ساخته شده است.
به گزارش توسعهدهنده این پروژه، pg-index-referee ابزاری متنباز است که مانع از استقرار ایندکسهای «به نظر درست اما بیفایده» میشود که توسط هوش مصنوعی پیشنهاد شدهاند. این ابزار مدلهای هوش مصنوعی زاینده (Generative AI) — شبیه به دستیاری که با اعتمادبهنفس زیاد اما بدون تجربه عملی راهنمایی میکند — را مجبور میکند تا پیشنهادهای خود را در محیط واقعی Postgres بسازند، عملکرد آنها را بسنجند و سپس بلافاصله تمام تغییرات را از طریق یک تراکنش بازگشتی (Transaction Rollback) حذف کنند.
بسیاری از مدلهای زبانی فارغ از اینکه یک کوئری از قبل بهینه شده است یا خیر، دستور CREATE INDEX را ارائه میدهند. این وضعیت منجر به یک چرخه خطرناک میشود که در آن توسعهدهندگان ایندکسهایی را در Pull Requestها قرار میدهند که از نظر ظاهری منطقی به نظر میرسند، اما هیچ انسانی نمیتواند بهطور واقعبینانه آنها را ارزیابی کند. نتیجه این امر اغلب «تورم ایندکس» (Index Bloat) است؛ جایی که دیتابیس هزینه دائمی نوشتن دادهها را برای ایندکسی میپردازد که برنامهریز (Planner) دیتابیس هرگز از آن استفاده نمیکند.
همانطور که در تحلیلهای قبلی ما دربارهی توهمات مدلهای زبانی اشاره کردیم، مدلها تمایل دارند پاسخهای پذیرفتنی تولید کنند، حتی اگر کاربردی نباشند. pg-index-referee برای مقابله با این موضوع، یک سیستم نمرهدهی سختگیرانه با دو پرسش کلیدی معرفی کرده است: اول، آیا سرعت کوئری بهطور معناداری افزایش یافت؟ دوم، آیا برنامهریز Postgres واقعاً ایندکس جدید را انتخاب کرد؟ اگر برنامهریز ایندکس را نادیده بگیرد، ابزار آن را شکست میخواند، حتی اگر ساعت زمانسنج یک بهبود جزئی و نویزی را نشان دهد.
خطر تکیه بر زمان اجرا
سنجش یک ایندکس صرفاً بر اساس زمانبندی کوئری قبل و بعد از تغییر (Clock-only grading) کافی نیست. در یک مورد واقعی، یک ایندکس پیشنهادی روی ستون events (user_id) با یک عبارت WHERE created_at > ... زمان اجرای کوئری را از ۱۴.۲ میلیثانیه به ۱۲.۱۹ میلیثانیه کاهش داد. اگرچه این یک بهبود ۱.۱۷ برابر (۱۷ درصدی) به نظر میرسد، اما برنامهریز دیتابیس هرگز به این ایندکس دست نزد.
در چنین مواردی، بهبود مشاهده شده صرفاً نویز در یک کوئری ۱۴ میلیثانیهای است. اگر توسعهدهندهای فقط بر اساس ساعت قضاوت میکرد، این ایندکس را نگه میداشت و هزینه نوشتن آن را برای همیشه متحمل میشد. این ابزار با پیمایش خروجی EXPLAIN و جمعآوری تمام گرههای Index Name و تأیید حضور ایندکس جدید، این مشکل را حل میکند. ایندکسی که وجود دارد اما هرگز استفاده نمیشود، یک ایندکس «کند» نیست، بلکه پاسخ آن یک «نه» قاطع است.
مکانیزم بازگشت (Rollback)
هسته این ابزار بر یک ویژگی خاص در Postgres استوار است: توانایی ساخت یک ایندکس در داخل یک تراکنش و سپس بازگرداندن (Rollback) آن. گردش کار ابزار از یک توالی سختگیرانه پیروی میکند:
- ابزار یک تراکنش را با دستور
cur.execute('BEGIN')باز میکند. - دستور DDL (زبان تعریف داده) تولید شده توسط AI را برای ساخت ایندکس اجرا میکند.
- دستور
cur.execute('ANALYZE')را اجرا میکند تا اطمینان حاصل شود که برنامهریز آمارهای تازهای در اختیار دارد؛ بدون این مرحله، ممکن است برنامهریز به دلیل آمارهای قدیمی، ایندکس را به دلیل اشتباه رد کند. - عملکرد کوئری را با استفاده از
EXPLAIN (ANALYZE, BUFFERS)اندازهگیری میکند. - دستور
cur.execute('ROLLBACK')را اجرا میکند تا تضمین شود ایندکس هرگز بهطور دائمی روی دیسک باقی نمیماند.
یک سبکسنگین کردن (Trade-off) حیاتی در اینجا، حذف کلمه کلیدی CONCURRENTLY است. از آنجایی که ساخت ایندکسهای همزمان نمیتواند در داخل یک تراکنش اجرا شود، ابزار این کلمه را حذف میکند تا تضمین امنیت Rollback حفظ شود. نویسنده اشاره میکند که بازگشت تراکنش، ویژگی امنیتی اصلی است و از دست دادن این کلمه کلیدی بهتر از دست دادن این تضمین است. به کاربران توصیه میشود هنگام اعمال یک ایندکس تأییدشده روی یک جدول عملیاتی زنده، این کلمه را بهصورت دستی اضافه کنند.
محک مدلها: هزینه در برابر هوشمندی
نویسنده ۹ مدل مختلف را روی یک نمونه Postgres 18 که روی یک لپتاپ اجرا میشد، تست کرد. مجموعه داده شامل سه جدول با مجموع ۱.۵ میلیون ردیف بود. بخش عمده دادهها در جدول events با ۱.۲ میلیون ردیف و حجم ۱۰۴ مگابایت قرار داشت؛ حجمی که به اندازه کافی بزرگ بود تا اسکنهای ترتیبی (Sequential Scan) بهطور فیزیکی محسوس باشند.
تستها بر روی ۸ کوئری رایج و «ساده» متمرکز بود که تیمهای برنامهنویسی واقعاً مینویسند، از جمله:
- جستوجوی یک کاربر بر اساس ایمیل.
- بازیابی ۲۰ رویداد اخیر برای یک کاربر خاص.
- یافتن سفارشات معلق از یک تاریخ مشخص.
- محاسبه درآمد بر اساس کشور.
هر کوئری به همراه شمای دیتابیس (Schema)، ایندکسهای موجود و خروجی EXPLAIN (ANALYZE, BUFFERS) خود کوئری به مدل ارائه شد. به مدل اجازه داده شد تا برای هر کوئری حداکثر سه ایندکس پیشنهاد دهد و سپس داور (Referee) وارد عمل شود.
در تمام موارد، «نرخ نگهداری» (Keep Rate) برای ایندکسهای تأییدشده بهطور قابل توجهی ثابت بود. هر مدلی که پاسخ ارائه داد، نرخ تأییدی بین ۵۸٪ تا ۶۷٪ داشت، فارغ از اندازه یا قیمت مدل. این موضوع نشان میدهد که شناسایی یک ایندکس گمشده، ویژگی خودِ کوئری است، نه سطح هوشمندی مدل.
تحلیل هزینه در برابر هوش
دادهها تفاوت فاحشی را در بهرهوری هزینه نشان دادند. نویسنده چندین مدل از جمله openai-gpt-oss-20b ،gemma-4-31B-it ،deepseek-v4-pro و nemotron-3-ultra-550b را مقایسه کرد.
مدل Mistral-3-14B با استفاده از تنها ۴۸۲ توکن خروجی و هزینه ۰.۰۰۱۳ دلار، ۱۶ ایندکس تأییدشده تولید کرد. در مقابل، Nemotron-3-Ultra-550B هزینه ۰.۰۲۹۷ دلار داشت — یعنی تقریباً ۲۳ برابر بیشتر — در حالی که نتایج تأییدشده کمتری (۷ ایندکس) تولید کرد.
شکست Nemotron ناشی از فقدان هوشمندی نبود، بلکه به دلیل سربار «استدلال» بود. این مدل بودجه ۳۰۰۰ توکنی خروجی خود را با استدلالهای داخلی (Chain-of-Thought) پر کرد و پیش از آنکه بتواند دستور CREATE INDEX را بنویسد، فضای خود را تمام کرد. این منجر به پاسخهای خالی شد که همچنان با نرخ کامل توکنهای خروجی صورتحساب شدند. در یک مورد، Nemotron از ۱۴,۱۹۶ توکن خروجی و ۱۳۴ ثانیه زمان مدل استفاده کرد تا نتایجی کمتر از Mistral تولید کند، در حالی که Mistral تنها هفت ثانیه زمان برد.
نویسنده همچنین یک اندپوینت مسیریابی DigitalOcean (router:software-engineering) را تست کرد. با انتظار یک پیشفرض منطقی، نتیجه ناامیدکننده بود: به دلیل همان دلیل بودجه استدلال، در سه کوئری پاسخ خالی داد، در کل اجرا ۲۴۵ ثانیه زمان برد و هزینه آن بیشتر از انتخاب دستی Mistral بود، در حالی که تقریباً نیمی از ایندکسهای تأییدشده را ارائه داد.
نقطه کور: ناتوانی در گفتن «نه»
مهمترین یافته، ناتوانی مدلها در گفتن «نه» بود. دو مورد از هشت کوئری اساساً Joinهای سنگین تجمعی (Aggregate-heavy) بودند که نیاز به خواندن تقریباً کل جدول داشتند. برای مثال، کوئری درآمد بر اساس کشور، ۳۰۰ هزار سفارش را بررسی میکند؛ کوئری دیگر مشتریان طرح تیمی را بر اساس هزینه رتبهبندی میکند. هیچ ایندکسی نمیتوانست سرعت آنها را افزایش دهد زیرا آنها ردیفی را رد نمیکنند (Skip نمیکنند).
با وجود این، مدلها ۴۱ ایندکس مختلف برای این دو کوئری پیشنهاد دادند. حتی زمانی که چندین مدل روی یک ایندکس پوششی (Covering Index) خاص توافق کردند — مانند ایندکس پوششی روی orders (status, placed_at) که ستونهای جمع را حمل میکرد و ایندکس پوششی روی users (id) که کشور را حمل میکرد — Postgres تکتک آنها را رد کرد. این ثابت میکند که توافق بین مدلها به معنای تأیید نیست؛ بلکه صرفاً نشانهای است که آنها روی توصیههای عمومی مشابه آموزش دیدهاند. پاسخ درست این است که «هیچ ایندکسی به این کوئری کمک نمیکند»، اما این پاسخی نیست که مدلی که از او خواسته شده ایندکس پیشنهاد دهد، ارائه کند.
دستاوردهای عملکردی
برای شش کوئری که قابلیت بهبود داشتند، افزایش سرعت چشمگیر بود. بهترین نتایج تأییدشده عبارت بودند از:
- ۲۰ رویداد اخیر برای یک کاربر: از ۱۴.۱ میلیثانیه به ۰.۰۰۹ میلیثانیه (۱۵۱۲ برابر سریعتر)
- سفارشات معلق از یک تاریخ: از ۷.۸ میلیثانیه به ۰.۰۱۹ میلیثانیه (۴۰۹ برابر سریعتر)
- جستوجوی کاربر با ایمیل: از ۱.۲ میلیثانیه به ۰.۰۱۲ میلیثانیه (۹۷ برابر سریعتر)
- رویدادهای خرید در یک ماه: از ۱۵.۹ میلیثانیه به ۰.۶۰۲ میلیثانیه (۲۶ برابر سریعتر)
- پرکارترین کاربران از یک تاریخ: از ۴۲.۳ میلیثانیه به ۶.۸ میلیثانیه (۶ برابر سریعتر)
- رویدادهای خطا بر اساس منبع: از ۲۳.۹ میلیثانیه به ۱۱.۴ میلیثانیه (۲ برابر سریعتر)
جزئیات پیادهسازی
برای تضمین دقت، ابزار بهجای میانگین، سریعترین زمان از بین پنج اجرا را در نظر میگیرد. این کار «کفِ کشِ گرم» (Warm-cache floor) را هدف قرار میدهد که پایدارتر از میانگین است و از غرق شدن یک بهبود واقعی ۳۰ درصدی در نویزهای سیستم جلوگیری میکند.
کاربران میتوانند این ابزار را از طریق گیتهاب (oceanforge/pg-index-referee) با استفاده از یک اندپوینت سازگار با OpenAI مستقر کنند. مراحل راهاندازی شامل موارد زیر است:
git clone https://github.com/oceanforge/pg-index-refereecd pg-index-referee && pip install -e .- صادر کردن متغیرهای محیطی
DATABASE_URLوDO_INFERENCE_KEY. - اجرای دستور
pg-index-referee --queries examples/queries.sql --apply.
اگر کاربران بخواهند اعداد دقیق را بازتولید کنند، فایل examples/setup.sql مجموعه دادههای یکسان را بهصورت قطعی (Deterministic) میسازد. پرچم --apply تنها مواردی را چاپ میکند که از فرآیند تأیید عبور کردهاند.
نویسنده هشدار میدهد که ساخت ایندکسها، حتی در تراکنشهای بازگشتی، همچنان به قفلهای واقعی (Locks) و توان محاسباتی نیاز دارد. درسی که از یک بنبست (Deadlock) در حین اجرای تستها (جایی که یک DROP TABLE با ابزار برخورد کرد) گرفته شد، این است که ابزار باید روی یک نسخه کپی (Replica) یا یک Dump بازیابی شده اجرا شود. نویسنده از استنتاج بدون سرور DigitalOcean استفاده کرد زیرا یک کلید به کل محدوده قیمتی مدلهای تست شده دسترسی داشت.
تأملات نهایی
پیشنهاد دادن، بخش ارزان کار است. در میان ۹ مدل و ۸ کوئری، ۱۵۱ ایندکس پیشنهادی ساخته، اندازهگیری و دور ریخته شدند و در مجموع هزینه آنها پنج و نیم سنت بود. بخش گرانقیمت همیشه تصمیمگیری درباره این بوده است که به کدام پیشنهادها اعتماد کنیم — فرآیندی که معمولاً بهصورت دستی در Code Review و بدون داشتن یک برنامه (Execution Plan) در مقابل بازبین انجام میشود.
با خودکارسازی مرحله قضاوت، این ابزار اجازه میدهد دیتابیس درباره سرنوشت خود تصمیم بگیرد. Postgres ایندکس را میسازد، به شما میگوید که آیا زحمت استفاده از آن را میکشد یا خیر، و کل ماجرا را در حدود یک ثانیه فراموش میکند. همچنین پاسخی را ارائه میدهد که هوش مصنوعی هرگز داوطلبانه نخواهد گفت: اینکه کوئری شما مشکل ایندکس ندارد و باید گلوگاه را در جای دیگری جستوجو کنید.
گام بعدی شما
- اگر از AI برای بهینهسازی کوئریها استفاده میکنید، هرگز دستورات
CREATE INDEXرا بدون بررسی خروجیEXPLAINاجرا نکنید. - ابزار pg-index-referee را روی یک محیط Staging تست کنید تا ببینید چند درصد از پیشنهادهای مدل شما واقعاً توسط دیتابیس پذیرفته میشوند.
- برای کوئریهای سنگین (Aggregate-heavy)، بهجای جستوجوی ایندکس، روی بازطراحی مدل دادهها یا Materialized Views تمرکز کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو