خانه SQL Server حل هزینه Lookup با استفاده از مفهوم Cover Index SQL Server افزایش سرعت SQL Server نوشته شده توسط: میلاد فیروزی تاریخ انتشار: ۱۶ دی ۱۳۹۴ آخرین بروزرسانی: ۱۰ اردیبهشت ۱۴۰۱ زمان مطالعه: 7 دقیقه ۴ (۱) مقدمه اگر تا به حال به مسائل Tuning و Performance در زمینه ی Queryها پرداخته باشید احتمالا با Execution Plan سر و کله زده اید تا ببینید کدام قسمت از Queryتان مشکل دارد و باید آن قسمت را اصلاح کنید و یا دنبال راه حل Indexی باشید. همان طور که می بینید در این Query تقریبا چیزی حدود ۵۰ درصد هزینه صرف Key Lookup شده است ، حال می خواهیم ابتدا ضمن بررسی کردن دلیل به وجود آمدن Lookup راه حل برطرف نمودن آن را نیز ارائه دهیم. Lookup چیست؟ خوب Lookup به معنای گشتن دنبال چیزی می باشد ، در Lookup اتفاقی که می افتد این است که SQL Server برای پیدا کردن یک یا چند فیلد نمی تواند از Index تعریف شده استفاده کند و باید برای یافتن آن فیلد و یا فیلدها دوباره در خود جدول بگردد.همانطور که می دانید دو نوع Index داریم ، Clustered و Non Clustered. چون مبحث امروز در مورد Indexها نیست سعی می کنم خیلی خلاصه مفهوم این دو Index را بررسی کنم. در نوع Clustered اتفاقی که می افتد این است که SQL چینش فیزیکی رکوردها را مرتب می کند و چون بحث مرتب سازی می باشد رکوردها تنها می توانند بر اساس یک فیلد مرتب شوند ، در نتیجه Clustered Index روی همان فیلد تعریف می شود ، پس از تعریف Primary Key هم یک Clustered Index تعریف می شود که رکوردها را بر اساس آن Key مرتب می کند. در نو Non Clustered روی یک یا چند فیلد می توانیم Index بگذاریم و اتفاقی که می افتد این است که این فیلد ها توسط SQL در مکانی دیگر کپی می شوند و با توجه به ساختاری به نام B-Tree مرتب می شوند. خوب Non Clustered index می تواند روی جداول Heap (جدولی که هیچ نوعی از Index روی آن تعریف نشده است) و یا جداول Clustered تعریف شود. در هر دوی آن ها ما تعداد محدودی از فیلدها را در Index داریم و اگر در شرط SELECT QUERY به فیلدهای بیشتری نیاز باشد SQL مجبور می شود برای یافتن آن فیلدها به خود جدول مراجعه کند و به دنبال آن فیلدها “بگردد” که به این کار به اصطلاح Key Lookup می گویند. اگر این گشتن روی یک Clustered Table باشد چون به دنبال کلید Indexی که خود جزو Non Clustered نیز هست می گردد به آن Key Lookup گفته می شود و حال اگر این Non Clustered روی Heap Table تعریف شده باشد SQL مجبور است تمامی جدول را برای یافتن فیلد اضافی بگردد که به این عمل هم RID Lookup گفته می شود. چگونه می توان Lookup را برطرف کرد؟ ما می توانیم به Non Clustered بگوییم که به جز آن چند فیلدی که در جایی دیگر کپی شده اند یک یا چند فیلد دیگر را نیز در کنار آن ها نگهداری کند به نحوی که این فیلدها در نحوه مرتب سازی تاثیری ندارند و فقط به عنوان فیلدهای اضافی به مابقی فیلدها چسبیده اند ، با این روش SQL وقتی شرط SELECT را چک می کند دیگر نیازی ندارد به خود جدول سر بزند و هرآنچه نیاز دارد در کنار بقیه فیلدها پیدا می کند و هزینه صرف شده جهت Lookup صرفه جویی می شود به این نوع از Indexها Covered Index گفته می شود. حال به مثال زیر دقت کنید در این مثال از دیتابیس AdventureWorks2012 استفاده می کنیم ، می خواهیم دستور زیر را اجرا کنیم ، قبل آن STATISTICS IO را فعال می کنیم تا تعداد صفحات خوانده شده را بتوانیم بررسی کنیم ، SET STATISTICS IO ON; SELECT CustomerID, OrderDate FROM [AdventureWorks2012].[Sales].[SalesOrderHeader] WHERE CustomerID = 11000; خوب حالا نتایج STATISTICS IO را ببینیم ، Table ‘SalesOrderHeader’. Scan count 1, logical reads 11, physical reads 0, read-ahead reads برای این واکشی ۱۱ صفحه خوانده شده است. حال نتیجه Execution Plan را با هم ببینیم ، مشاهده می شود که ۶۸ درصد هزینه صرف Key Lookup شده است و با اینکه Non Clustered Index تعریف کرده بودیم هنوز هزینه ی زیادی بابت Key Lookup پرداخت می شود. حال Index قبلی را Drop کرده و Index جدیدی با استفاده از مفهوم Covered Index ایجاد می کنیم ، حال دوباره نتیجه STATISTICS IO و Execution Plan را ببینیم ، Table ‘SalesOrderHeader’. Scan count 1, logical reads 2, physical reads 0, read-ahead reads DROP INDEX Sales.SalesOrderHeader.IX_SalesOrderHeader_CustomerID; CREATE NONCLUSTERED INDEX IX_SalesOrderHeader_CustomerID_OrderDate ON Sales.SalesOrderHeader(CustomerID, OrderDate); مشاهده می شود که علاوه بر حذف شدن هزینه Key Lookup تعداد صفحات خوانده شده نیز به عدد ۲ کاهش یافت. چه رتبه ای میدهید؟ میانگین ۴ / ۵. از مجموع ۱ اولین نفر باش معرفی نویسنده مقالات 8 مقاله توسط این نویسنده محصولات 0 دوره توسط این نویسنده میلاد فیروزی معرفی محصول مسعود طاهری آموزش ۳ در ۱ Performance Tuning در SQL Server 6.700.000 تومان مقالات مرتبط ۰۲ آبان SQL Server ابزار Database Engine Tuning Advisor؛ مزایا، کاربردها و روش استفاده تیم فنی نیک آموز ۱۵ مهر SQL Server معرفی Performance Monitor ابزار مانیتورینگ SQL Server تیم فنی نیک آموز ۱۱ مهر SQL Server راهنمای جامع مانیتورینگ بکاپ ها در SQL Server تیم فنی نیک آموز ۰۸ مهر SQL Server Resource Governor چیست؟ آشنایی با نحوه پیکربندی و اهمیت های آن تیم فنی نیک آموز دیدگاه کاربران لغو پاسخ دیدگاه نام و نام خانوادگی ایمیل ذخیره نام، ایمیل و وبسایت من در مرورگر برای زمانی که دوباره دیدگاهی مینویسم. موبایل برای اطلاع از پاسخ لطفاً مرا با خبر کن ثبت دیدگاه Δ علی تجویدی ۲۰ / ۱۰ / ۹۴ - ۰۹:۳۳ با سلامممنون از مقاله مفیدجمله شما که در زیر آورده شده صحیح نیست“حال اگر این Non Clustered روی Heap Table تعریف شده باشد SQL مجبور است تمامی جدول را برای یافتن فیلد اضافی بگردد که به این عمل هم RID Lookup گفته می شود. “تمامی جدول را نمی گردد و در خیلی موارد RID Lookup هزینه کمتری نسبت به Key Lookup دارد.با تشکر پاسخ به دیدگاه مهدی ربانی ذبیحی ۲۰ / ۱۰ / ۹۴ - ۰۶:۰۵ با سلام ممنون بابت مقاله خوبتون پاسخ به دیدگاه فرشید علی اکبری ۱۹ / ۱۰ / ۹۴ - ۰۱:۲۷ سلام مقاله خوبی بود و تشکر از زحمتی که بابت به اشتراک گذاری مطالب میگذارید. فقط اگه اون Nun را به Non ویرایش کنید باعث سردرگمی کاربران مبتدی نمیشه. ممنون. پاسخ به دیدگاه فرید طاهری ۱۹ / ۱۰ / ۹۴ - ۰۱:۵۳ سلام. با تشکر از دقت شمااصلاح گردید. پاسخ به دیدگاه میلاد فیروزی ۱۹ / ۱۰ / ۹۴ - ۰۱:۴۸ ممنون اشتباه از من بود پاسخ به دیدگاه مسعود طاهری ۱۹ / ۱۰ / ۹۴ - ۱۰:۳۵ میلاد عزیز متشکرم از مقاله خوبی که در سایت قرار دادید. فقط یک نکته کوچک دوستان عزیز توجه داشته باشید که قرار نیست هزینه LOOKUP همه کوئری را حذف کنید. دنبال کوئری های پر استفاده باشید روی حذف هزینه LOOKUP آن متمرکز شوید. ضمنا اگر قرار است تعداد فیلد زیادی به ایندکس INCLUDE شود شاید این کار به علت هزینه نگهداری ایندکس (به علت تغییرات و… ) به صرفه نباشد. اما در کل مقاله عالی و خوبی است در جهت آشنایی دوستان با مفهوم LOOKUP و حذف هزینه آن متشکرم میلاد جان پاسخ به دیدگاه sql programmer ۲۸ / ۱۱ / ۰۲ - ۰۷:۵۶ با سلام چطور میتونیم کوئری های پراستفاده را پیدا کنیم پاسخ به دیدگاه میلاد فیروزی ۱۹ / ۱۰ / ۹۴ - ۱۰:۳۱ ممنون استاد نکات ارزشمندی فرمودید پاسخ به دیدگاه 1 2