PDA

View Full Version : بهترین Index کدام است



محمد سلیم آبادی
دوشنبه 30 فروردین 1389, 20:20 عصر
با سلام،
یک query نوشتم که می خواهم بهترین، موثر ترین و مفید ترین index ها را برایش طراحی کنم. Query در واقع کار CrossTab را انجام می دهد و با کمک Outer Joinsو T-SQL inline table-valued UDF پیاده سازی شده است.
توابعی که جدول برمی گرداند دقیقا مثل View ها توسط Optimizer بهینه می شوند. از این جهت نگرانی وجود ندارد.
ایندکس هایی که به نظرم مفید واقع می شوند اینها هستند:


CREATE CLUSTERED INDEX IX_0 ON Sales (Product_name)
CREATE NONCLUSTERED INDEX IX_1 ON Sales (Sales_year) INCLUDE (product_name, qty, product_price)
CREATE NONCLUSTERED INDEX IX_2 ON Sales (product_name) INCLUDE (qty, product_price)



از نقشه (Plan) پیداست که IX_1 برای UDF ها بسیار موثر عمل کرده است. هم Cover داده و هم در فیلتر داده ها استفاده شده.
سوال اینجاست که آیا ایندکس های بهتری هم وجود دارند که سرعت اجرای این Query را به حداکثر برسانند یا خیر؟


CREATE FUNCTION CrossTab (@sales_year INTEGER)
RETURNS TABLE
AS
RETURN
(SELECT product_name,
SUM(qty * product_price) AS year
FROM Sales
WHERE sales_year = @sales_year
GROUP BY product_name
);
GO

SELECT P1.product_name,
COALESCE(C1.[year], 0) AS year1,
COALESCE(C2.[year], 0) AS year2,
COALESCE(C3.[year], 0) AS year3,
COALESCE(C4.[year], 0) AS year4,
COALESCE(C5.[year], 0) AS year5,
COALESCE(totals, 0) AS totals
FROM Products P1
LEFT OUTER JOIN dbo.Crosstab(1990) AS C1
ON P1.product_name = C1.product_name
LEFT OUTER JOIN dbo.Crosstab(1991) AS C2
ON P1.product_name = C2.product_name
LEFT OUTER JOIN dbo.Crosstab(1992) AS C3
ON P1.product_name = C3.product_name
LEFT OUTER JOIN dbo.Crosstab(1993) AS C4
ON P1.product_name = C4.product_name
LEFT OUTER JOIN dbo.Crosstab(1994) AS C5
ON P1.product_name = C5.product_name
LEFT OUTER JOIN (SELECT product_name,
SUM(qty * product_price) AS totals
FROM Sales
GROUP BY product_name) totals
ON P1.product_name = totals.product_name;


هر دو plan تخمین زده شده و واقعی را ضمیمه کرده ام.
در مورد ساختار جداول هم می توانید به این لینک مراجعه کنید:
http://www.30sharp.com/ShowArticle.aspx?nid=13&did=207&AuthorID=11

AminSobati
سه شنبه 31 فروردین 1389, 23:47 عصر
سلام دوست عزیزم،
این ایندکس رو آزمایش کنین:



create index newix on products(product_name)

محمد سلیم آبادی
چهارشنبه 01 اردیبهشت 1389, 09:51 صبح
سلام،
تشکر از پاسختون، امتحان کردم و نتیجه بهتری حاصل شد.

من قبلا ستون product_name از جدول products ایندکس کلاستری در نظر گرفته بودم. حالا شما یک ایندکس غیر کلاستری روی تنها همین ستون ایجاد کردین. به نظر میرسد در این مورد چون تنها به index key نیاز هست بهتره یک NonClustered Index تعریف کنیم به دلیل کم بودن حجم سطح برگ (leaf level) (تمام ایندکس scan می شود)، در نتیجه estimated I/O cost نیز کاهش پیدا می کند.

آیا این فرضیات من درست هستند؟

برای این Node ID شماره 5 نمی شه فکری کرد؟ 31% هزینه داره! که باید مربوط باشه به جدول total (که مشتق شده). کلا از کجا می شود فهمید این node های برگ مربوط میشن بکدوم جدول (ویو، udf، جدول، cte یا derived table) ؟

AminSobati
چهارشنبه 01 اردیبهشت 1389, 14:16 عصر
ممکنه Actual Plan بعد از ساخت ایندکس جدید رو پست کنین تا بهتر بشه بررسی کرد؟

محمد سلیم آبادی
چهارشنبه 01 اردیبهشت 1389, 14:40 عصر
Actual Plan بعد از ساخت ایندکس جدید ضمیمه شد.

s.Jabbari
چهارشنبه 01 اردیبهشت 1389, 18:36 عصر
میشه بگید Actual Plan چیه؟

محمد سلیم آبادی
چهارشنبه 01 اردیبهشت 1389, 20:02 عصر
ممکنه لطفا این plan ها را بیشتر تحلیل کنید
مشکل من این است که اصلا این plan ها را درک نمی کنم
الان شما از کجا فهمیدین که کدام index بهتره از روی چه تحلیلی

ممنون


میشه نگید Actual Plan چیه؟
میشه نگیم یا بگیم؟!

ببینید وقتی در SQL Server یک Query را اجرا می کنیم توسط یک نرم افزار یا به اصطلاح مغز متفکر (Optimizer) بهترین مسیر از نظر کم بودن هزینه برای اجرای آن Query انتخاب میشه که به آن نقشه ی اجرا (Execution Plan) گفته می شود.
این نقشه یا plan دقیقه یک درخت هست که شامل یکسری node و root و کلا شاخ و برگ هست. هر کدام از این گره های درخت را بهش یک عملگر گفته می شود. برای خواندن Plan بایستی به زبان آن آشنا بود. اگر دقیق یادم باشه در حدود 79 عملگر مجزا وجود دارد.
حالا همین Execution Plan به دو نوع تخمین زده (Estimated) و واقعی (Actual) تقسیم میشود. اگر دکمه ی Ctrl +M را قبل از اجرای کوئری بزنید در کنار تب Result یک تب دیگه خواهید دید که در آن پلن مشاهده می شود.
این مباحث مربوط به بحث Query Tuning and Optimization میشوند که من هنوز تازه این مباحث رو آغاز کردم. می توانید به کتاب Inside SQL Server T-SQL: Query به عنوان مرجع رجوع کنید.

لطفا اجازه بدین سوال بنده به جواب کامل برسد سپس بیشتر در این مورد بحث و گفتگو خواهیم کرد.

AminSobati
پنج شنبه 02 اردیبهشت 1389, 22:33 عصر
دلیل استفاده از ایندکس جدید دو مورد هست:
1) یکی که خودتون اشاره کردین، چون حجم ایندکس جدید کمتر هست و تعداد Pageهای کمتری نیاز به پیمایش داره
2) با توجه به تاریخ ساخت ایندکس، Processor ترجیح میده بین چند ایندکس با شرایط یکسان، ایندکسی که جدیدتر هست رو استفاده کنه چون Distribution Statistic جدیدتری داره و اطلاعاتش به روز تره

در ارتباط با Nodeی که Cost سی و چند درصدی داره، اشکالی وارد نیست. چون عدد 100 بین Operatorها پخش میشه و شما هر قسمت رو که بهینه کنید، وزن روی Operator دیگه ای بیشتر خواهد شد. از طرفی Node شماره 5 کار اضافی انجام نمیده چون تمام رکوردها رو درخواست کردین و باید Scan کنه.

کوئری داخل توابع Inline و View رو نمیتونین در Plan تشخیص بدین چون این کوئریها با هم ادغام میشن و عملا یک کوئری تلقی میشن. اما فرضا اگر یک تابع Scalar Valued داشته باشین، در Estimated Plan براش Plan جدا ظاهر میشه

تشابه بین Estimated و Actual در این هست که هر دو یک Plan رو در پیش میگیرند ولی اولی کوئری رو اجرا نمیکنه. لذا وقتی Mouse رو روی فلش ها میبرید، فقط تعداد رکوردهای مستخرج رو به صورت تخمینی نشون میده. اما در Actual کوئری واقعا اجرا میشه و Actual Number of Rows بدست میاد. زمانی که یک کوئری خیلی زمان میبره و شما میخواین Tune کنین، نیازی نیست بعد از هر ایندکس که میسازین دوباره Run کنین و معطل بشین تا Plan رو ببینید. حالت Estimated بلادرنگ Plan رو به شما نمایش میده حتی با تاثیر ایندکس یا هر تغییر جدید