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

چرا نباید درکوئری تمام ستون ها را انتخاب کنیم؟

اگر * Select به همراه Order By انتخاب کنیم، چه اشکالی داره ؟

در مطلب دیگری به تاثیر order by در مرتب بودن خروجی دیتا اشاره کردیم، حالا سعی می کنیم بررسی کنیم که بکارگیری order by به همراه  *  select  چه تاثیری روی اجرا کوئری در SQL Server  داره  و راه درست بکارگیری اون چیه.


کوئریزیررورویدیتابیسStackOverflowاجراکنیم:
همونطورکهمیبینیددرکوئریاولفقطIdدرخروجینمایشدادهشدهودرکوئریدومتمامیستونهایجدولUser.

با بررسی کوئری پلن هر دو کوئری می بینیم که Base هر دو کوئری یه چیزه، اسکن ایندکس کلاستر، مرتب سازی و نمایش خروجی. با این تفاوت که تو کوئری دوم، با توجه به هزینه بالایی که کوئری داره، عملیات به صورت Parallel بین Core های CPU تقسیم شده. احتمالا در نگاه اول میگید که خب جفت این دو  تا کوئری دارن از ایندکس Cluster میخونن و به همه دیتا دسترسی دارن اما * Select  میتونه دیتای بیشتری رو بخونه

ساختار جدول User رو ببینید:

اگه دقت کنید، می بینید که فیلد AboutMe از نوع Nvarchar(max) هست، به این معنا که ممکنه طول ش اونقدری بزرگ شه که تو Page های 8 کیلوبایتی جا نشه، اگه طول ش کمتر از 8 کیلو بایت باشه، با مکانیزمی مشابه بقیه فیلدها، ذخیره و بازیابی میشه اما اگه طولش بیشتر شه تو Page های از نوع LOB (Large Object) ذخیره میشه و طبیعتا خوندن و بازیابی LOB هزینه ای رو به CPU متحمل میکنه پس:

وقتی Select * مینویسیم SQL مجبوره تمامی Page ها رو بخونه حتی LOB ها رو در حالیکه در Select Id فقط Page های معمولی رو میخونه ، * Select   میتونه مرتب سازی بیشتری انجام بده

احتمالا براساس چیزی که تو کوئری نوشته شده (Order by LastAccessDate)  این تصور ایجاد میشه که SQL ستون LastAccessDate رو تو یه فضای جداگانه مرتب میکنه و بعد بین اون فضا و ایندکس Cluster سوئیچ می کنه تا مابقی فیلدها رو استخراج کنه، نه اینطور نیست، چون این سوئیچ کردن هزینه زیادی براش داره در نتیجه کل دیتا رو میگیره و مرتب سازی رو انجام میده نتیجتا اینکه CPU و Memory زیادی درگیر اجرای عملیات Sort میشه. به همین خاطره که تو کوئری پلن کوئری دوم، 97 درصد هزینه مربوط به عملگر Sort هست ، * Select میتونه مدت بیشتری طول بکشه تا خروجی رو نشون بده

هر دوی این کوئری ها داره از ایندکس Cluster استفاده میکنه که دیتا هم همراهشه اما انتقال همه اطلاعات تحت شبکه زمان برتر خواهد بود تا انتقال فقط یک فیلد.

نکات:
  1. وقتی میگیم از * Select  استفاده نکنید فقط منظورمون استفاده نکردن از * نیست، اینکه ستون هایی رو در خروجی بیاریم که نیازی بهشون نداریم و مجبوریم اونا رو هم مرتب کنیم، همین معنی رو میده.
  2. اگه تو کوئری تون از Order By استفاده نکنید به این معنا نیست که کوئری پلن تون عملگر Sort نخواهد داشت مثلا ممکنه در اجرای یه کوئری از ایندکس NonClusterd استفاده بشه و اون ایندکس یک یا دوتا از فیلدهایی که باید در خروجی نمایش داده بشه رو در خودش نداره، در نتیجه با عملگر Key Lookup سراغ ایندکس Cluster میره تا بقیه فیلدهایی که میخواد استخراج کنه، حالا برای مقایسه کردن این دو تا فضا (ایندکس Cluster و NonClusterd) میاد ایندکس NonClusterd رو براساس کلید ایندکس Cluster مرتب میکنه و سپس بین او دو Join میزنه

منبع :

www.brentozar.com

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