نیما جمشیدی
نیما جمشیدی
خواندن ۲ دقیقه·۴ سال پیش

تاثیر Order by در نتیجه کوئری SQL Server

پیش تر در مطلب مربوط به Table Scan اشاره مختصری کردیم به اینکه چطور دو کوئری یکسان در یک سرور بدون تغییر هیچ یک از عوامل موثر میتونه نتایج متفاوتی داشته باشه. در این مطلب سعی میکنیم عامل دیگه  که باعث تغییر نحوه مرتب سازی دیتا کوئری میشه رو بررسی کنیم. همه ما میدونیم که بکارگیری Order by تضمینی هست برای اینکه همیشه با ترتیب یکسانی result مورد نیاز رو دریافت کنیم، اما چه عاملی باعث میشه که در صورت عدم استفاده از Order by در اجرا کوئری های SQL Server ، نتایج متفاوتی بگیریم، در ادامه سعی میکنیم با استفاده از مثال این عامل رو شرح بدیم .

کوئری پایین رو روی دیتابیس Stack Overflow اجرا کنید:

وقتی کوئری پلن رو بررسی می کنیم، متوجه می شیم که برای نمایش خروجی از ایندکس کلاستر جدول استفاده شده، در نتیجه خروجی براساس ایندکس کلاستر یا همون Id مرتب و نمایش داده میشه

حالا روی ستون DisplayName یه ایندکس می سازیم و دوباره کوئری رو اجرا می کنیم :

حالا مجددا کوئری پلن رو می بینیم :

همونطور که می بینید به جای استفاده از ایندکس Cluster از ایندکس جدیدی که ساختیم، استفاده شد. چرا؟

به این خاطر که Engine اس کیو ال برای پاسخ دادن به کوئری ما، دنبال کوچکترین کپی از دیتای جدول User میگرده تا بتونه اون چیزی که ما میخوایم بهمون نشون بده

اگه وضعیت ایندکس های جدول User رو ببینیم متوجه می شیم که سایز ایندکس Cluster حدود 58 مگابایت و سایز ایندکس NonClustered حدود 9 مگابایته، در نتیجه استفاده از ایندکس NonClustered بهینه تره.

نتیجه اینکه SQL Server ممکنه از ایندکسی استفاده کنه که ما انتظار نداریم در نتیجه یک کوئری ممکنه در اجراهای مختلف، خروجی هایی با Order های متفاوتی تولید کنه.

یه مثال دیگه :

اگه به همون کوئری یه Where اضافه کنیم  و شرط Where یعنی ستون reputation رو Include ایندکس کنیم چه اتفاقی میفته؟

با مشاهده کوئری پلن میبینیم که:

ایندکسی که ساختیم براساس DisplayName مرتب شده در نتیجه برای اینکه SQL Server رکوردهایی رو پیدا کنه که دارای Reputation=1 هستند، باید ایندکس رو Scan کنه.  بعد از انجام اسکن، خروجی به صورت اتوماتیک براساس DisplayName مرتب شده.

حالا یه ایندکس بهتر میسازیم و کوئری رو دوباره اجرا می کنیم:

این ایندکس براساس Reputation مرتب شده اما هیچ مرتب سازی روی DisplayName نداره.

اینبار دیگه نیازی به Scan نیست چون ایندکس جدید براساس Reputation مرتب شده و شاهد Index Seek هستیم.

همون طور که دیدید استفاده از ایندکس های مختلف توسط SQL Server باعث میشه که نتونیم Order خروجی کوئری رو کنترل کنیم. در نتیجه تنها راهی که همیشه Order یکسان بهمون میده استفاده صریح از Order By  در کوئریه.

منبع :

www.brentozar.com

sql serverکوئریمرتب سازیorder byپایگاه داده
مدیر پایگاه داده در ایپاد
شاید از این پست‌ها خوشتان بیاید