قابلیت Merry-go-round (Advance Scanning ) به مکانیزمی در SQL Server گفته میشه که امکان بهبود کارایی در هنگام Table Scan در جداول پایگاه داده فراهم میکنه.
Without ORDER BY, You Can’t Depend On the Order of Results
فرض کنید جدولی با تعداد 500000 رکورد داریم و کاربر 1 کوئری A رو اجرا میکنه که نیاز به اسکن تمام جدول داره (Table Scan), با فاصله کمی کاربر 2 همون کوئری رو اجرا میکنه که نیاز به اسکن همون جدول داره.
در لحظه اجرا کوئری کاربر دوم، SQL Server Engine در حال خوندن Page مربوط به رکورد 100001 برای کاربر 1 هست. از اینجا به بعد تصمیم میگیره نتایج اسکن ها رو به هردو کاربر 1 و 2 ارسال کنه.
وقتی Table Scan کوئری کاربر 1 تموم بشه و رکورد 500000 هم مشاهده شه، SQL Server Engine برمیگرده سراغ page های اولیه و از Page1 شروع به اسکن کردن میکنه تا به رکورد 100000 برسه و نتایج رو برای کاربر 2 میفرسته .
همانطور که دیدیم هردو کاربر درخواست Select روی تمام جدول رو داده بودن و برای هر دو هم کوئری پلن یکسانی ایجاد شد اما چون زمان درخواست های متفاوتی داشتن ترتیب نمایش رکوردها براشون متفاوت شد. کاربر اول از رکورد 1 تا 500000 رو به ترتیب توی خروجی کوئری می بینه اما کاربر دوم رکورد 100001 تا 500000 می بینه و بعد 1 تا 100000 .
هنگامی که چندین Task در حال اجرای همزمان هستند این مکانیزم شرایطی رو به وجود میاره تا Task ها بتونن نتیجه Full table Scan رو با هم به اشتراک بذارن.
یعنی اگر کوئری پلن ایجاد شده به ازاء کوئری های درحال اجرا نیاز به اسکن Data Page های جدول داشته باشه و SQL Server Engine تشخیص بده که این Page ها قبلا برای پلن دیگری هم اسکن شدن، تصمیم میگیره تا اسکن جدید رو به اسکن قبلی وصل کنه و از اون به بعد، نتیجه خوندن Page ها رو برای هردو استفاده کنه.
در واقع هر Page رو یکبار میخونه و نتیجه رو برای هردو Execution Plan ارسال میکنه. هنگامی که اسکن پلن اول تمام شد و نتایج مورد نیازش رو استخراج کرد، SQL Server Engine با توجه به اینکه کوئری دوم دیرتر اجرا شده بود و بخشی از Page های خونده شده رو نداشت، Page های اولیه رو مجددا برای کوئری دوم میخونه.
این Loop رو تا زمانی که به تمام درخواست های اسکن Page جواب بده ادامه میده، به این مکانیزم merry-go-round گفته میشه و بیان میکنه که در صورت عدم استفاده از order by تضمینی برای یکسان بودن ترتیب نتیجه select اجرا شده وجود نداره.
اگر قرار بود به ازاء هرکوئری، Table Scan های مجزا انجام بشه به سرعت Buffer pool درگیر می شد و SQL server engine مجبور می شد به سراغ دیسک فیزیکی هم بره، درنتیجه افت Performance زیادی رخ می داد.
منبع: