PDA

View Full Version : سوال: کند شدن اجرا دسور در زمان Join?



SYNDROME
شنبه 08 خرداد 1389, 11:09 صبح
با سلام
من 2 تا جدول را با هم Inner Join می زنم و دوباره همان جداول را Left Outer Join می زنم.
نتیجه برگشتی هر دو جدول یکی است.
ولی دستوری که با Inner Join می نویسم 2 دقیقه طول می کشد تا نتیجه را ببینم ولی دستور Left Outer Join در 2 ثانیه ای انجام می شود.
در محیط 2005 می کنم.
در ضمن فیلدهایی که آنها را با هم در شرط قرار می دهم هر دو Int است و مقادیر 20000000 داخل آنها قرار گرفته است.
می خواهم بین این دو جدول را Inner Join بزن.
چرا این اتفاق می افتد؟
ممنون می شوم بنده را راهنمایی کنید.
با تشکر

محمد سلیم آبادی
دوشنبه 10 خرداد 1389, 13:19 عصر
سلام،

ولی دستوری که با Inner Join می نویسم 2 دقیقه طول می کشد تا نتیجه را ببینم ولی دستور Left Outer Join در 2 ثانیه ای انجام می شود
چطور این زمان را سنجیدین؟


و مقادیر 20000000 داخل آنها قرار گرفته است.

منظورتون را از این جمله متوجه نشدم.

اگر امکان دارد Estimated Graphical Execution Plan را ارسال کنید تا بلکه بتوانم راهنمایی کنم.
برای انجام این کار هر دو کوئری (با JOIN و با LEFT JOIN) را در کنار همدیگر قرار داده (در یک پنجره) سپس دکمه ی Ctrl+L را فشار دهین سپس Plan را ذخیره کنید و ضمیمه ی پستتان قرار بدهین.

SYNDROME
چهارشنبه 12 خرداد 1389, 07:31 صبح
سلام
با تشکر از آقای ثباتی و msalim


منظورتون را از این جمله متوجه نشدم.

مقدار مقادیر فیلدهایی که با هم Join می شوند.

فایلها را قرار دادم.
موفق و پایدار باشید

SYNDROME
چهارشنبه 12 خرداد 1389, 10:53 صبح
با سلام
ببخشید.
فایلها را قرار دادم
ممنون می شوم بنده را راهنمایی کنید.
موفق باشید

محمد سلیم آبادی
چهارشنبه 12 خرداد 1389, 18:35 عصر
در ماده ی WHERE کوئری از عبارت زیر استفاده شده:


IsNull(Cast(T1.RNCellar As Nvarchar(10)),'%%') Like '%%'

معنای این جمله چیه؟
این عبارت بولین برای هر مقداری برابر با TRUE خواهد بود!

SYNDROME
پنج شنبه 13 خرداد 1389, 19:29 عصر
در ماده ی WHERE کوئری از عبارت زیر استفاده شده:


IsNull(Cast(T1.RNCellar As Nvarchar(10)),'%%') Like '%%'

معنای این جمله چیه؟
این عبارت بولین برای هر مقداری برابر با TRUE خواهد بود!
با سلام
این مقدار یک SP است که من برای شما قرار دادم.
این مقدار '%%' یک پارامتر است که از داخل برنامه ارسال می شود و اعلام می کند یا تمام رکوردها یا یک مقدار خاص.
موفق باشید

محمد سلیم آبادی
پنج شنبه 13 خرداد 1389, 19:38 عصر
پس به جای عبارت فوق (و عبارت های مشابه)این عبارت را بنویسید و کوئری ها را دوباره اجرا کنید و سرعتشان را با سرعت قبلی مقایسه کنید:

(T1.RNCella LIKE '%%' OR T1.RNCella IS NULL)
AND ...

SYNDROME
پنج شنبه 13 خرداد 1389, 20:10 عصر
با سلام
به خاطر اینکه مطمئن شوم خط های که به آن شکل نوشته شده بود را پاک کردم.
سرعت بهتر شد در حدود 26 ثانیه ولی باز هم وقتی به جای Inner Join دستور Left Outer Join را قرار دادم باز هم کمتر از 1 ثانیه اجرا شد.
با تشکر از راهنمایی شما
منتظر راهنمایی های بعدی شما هستم

محمد سلیم آبادی
پنج شنبه 13 خرداد 1389, 20:20 عصر
ببینید، من نگفتم عبارات بولیین در ماده ی WHERE را حذف کنید گفتم با منطقی که نوشتم تعویض کنید. چون توابع CONVERT باعث میشه ایندکس استفاده نشه.
از طرفی مطمئن هستین که نتیجه ی هر دو کوئری (با join و left join) یکسان هست؟ روی داده های مختلف امتحان کردین؟
من فکر می کنم شما می خواستین بگین یا مقدار شبیه به پارامتر ورودی پروسیجر باشه یا اینکه NULL باشه، درسته؟

IsNull(Cast(T1.RNCellar As Nvarchar(10)),'%%') Like '%%'

حتما اینکاری که گفتم را انجام بدین (به جای پارامتر یک مقدار آزمایشی قرار بدین). و بعد از آن این سری Actual Execution Plan را ارسال کنید.
برای این منظور قبل از اجرای کوئری ها Ctrl+M را فشار بدین.
براساس این Plan ای که ارسال کردین، هزینه ی کوئری با JOIN از کوئری با LEFT JOIN کمتر است! من نمی دونم چطور پس زمانی چون 26 ثانیه صرف می کنه برای اجرا. مگه چند میلیون سطر در جداولتان دارین؟
پیشنهاد می کنم از تجربه ی آقای ثباتی در این مورد استفاده کنید (یه PM بفرستین و دعوتش کنید به این تاپیک)

SYNDROME
جمعه 14 خرداد 1389, 00:25 صبح
سلام بر آقا محمد
دلیل اینکه من شرط ها را حذف کردم این بود که روی آنها توجه نکنیم.
چون مشکل دستورات از شرطها نیست.
تعداد نتیجه جستجوها در حالت Inner Join برابر 25 رکورد و در حالت Left Outer برابر 26 رکورد است.
تنها دلیل کند بودن تفاوت این دو دستور است که نمی دانم چرا اینقدر تفاوت ایجاد می کند.

موفق باشید

محمد سلیم آبادی
جمعه 14 خرداد 1389, 00:35 صبح
سلام دوست من،
واقعیتش در این مورد تجربه ای ندارم ولی اگر برداشتم از شرطها درست بود حتما از تکنیکی که بهتون معرفی کردم استفاده کنید (برای بهرمندی از شاخص های مطلوب چون نقشه ی کوئری نشون میده شاخص های مطلوب همگی از دست رفتند...)
متاسفم که نمی تونم راهنمایی کنم. آقای ثباتی قطعا در این مورد تجربه دارند.
موفق باشید.

AminSobati
جمعه 14 خرداد 1389, 11:35 صبح
سلام دوست عزیزم،
یک زحمتی باید بکشین. همونطور که در پست شماره 11 اشاره شد، باید Actual Plan رو ارسال کنید. ولی نکته مهم این هست که هر دو کوئری رو با هم اجرا کنین تا Plan هم یک فایل بشه. ضمنا قبل از اجرا، دستر set statistics io رو فعال کنید و نتیجه ای که در قسمت Messages میاره پست بفرمایید

محمد سلیم آبادی
جمعه 14 خرداد 1389, 12:13 عصر
برای اینکه یکسری شک و شبه از طرف من برطرف بشه لطفا این کوئری زیر را در بانک مورد نظر اجرا کنید و نتیجه اش را پست کنید:

SELECT
[TableName] = so.name,
[RowCount] = MAX(si.rows)
FROM
sysobjects so,
sysindexes si
WHERE
so.xtype = 'U'
AND
si.id = OBJECT_ID(so.name)
GROUP BY
so.name
HAVING
so.name IN ('Tbl_Clr_HeadDocument','Tbl_Clr_DetailDocument',' Tbl_Clr_GroupObject','Tbl_Clr_DefineGroupObject')
ORDER BY
2 DESC

SYNDROME
شنبه 15 خرداد 1389, 07:30 صبح
با سلام و تشکر فراوان
فایلها را اجرا کردم و نتایج را قرار می دهم.
فقط نتوانستم هر دو Plan را در یک فایل ذخیره کنم(هر دو را در یک صفحه اجرا کردم ولی نتوانستم با هم ذخیره کنم)
با تشکر

AminSobati
شنبه 15 خرداد 1389, 12:40 عصر
سلام دوست عزیزم،
اونچه که مشخصه تفاوت سرعت ناشی از میزان IO هست. در حالت Inner جدول Tbl_Clr_HeadDocument تعداد 30992 صفحه (Page) خوانده و جدول Tbl_Clr_DetailDocument تعداد 1302816. در حالیکه همین اعداد در حالت Outer به ترتیب 29 و 331 بوده. ولی متاسفانه بازهم Estimated Plan فرستادین! لذا هنوز نمیتونم قضاوت کنم. چرا Actual نمیفرستی پسر خوب؟!

اجالتا این ایندکس رو هم بساز و دوباره میزان IO و Plan ها رو (ACTUAL!!) بفرست:



USE [HamrahanSystem]
GO
CREATE NONCLUSTERED INDEX ix1
ON [dbo].[Tbl_Clr_DetailDocument] ([Company],[DIndexState])
INCLUDE ([RefRecNo],[RNObject],[PriValue],[ForValue])

SYNDROME
شنبه 15 خرداد 1389, 13:06 عصر
با سلام به امین آقای گل


چرا Actual نمیفرستی پسر خوب؟!

شرمنده.
نمی دونم چطور باید سازم.
طبق گفته دوستمان Ctrl+M را زدم و سپس Query را اجرا کردم ولی نمی دانم چی را باید بفرستم.(این دفعه Plan ها را بعد از عملیات ضمیمه می کنم امیدوارم کارم درست باشد)



اجالتا این ایندکس رو هم بساز و دوباره میزان IO و Plan ها رو (ACTUAL!!) بفرست:



USE [HamrahanSystem]
GO
CREATE NONCLUSTERED INDEX ix1
ON [dbo].[Tbl_Clr_DetailDocument] ([Company],[DIndexState])
INCLUDE ([RefRecNo],[RNObject],[PriValue],[ForValue])

اجرا به 16 ثانیه رسید.
با تشکر از راهنمایی های شما
باز هم منتظر راهنمایی شما هستم

AminSobati
شنبه 15 خرداد 1389, 15:05 عصر
آفرین، این شد! Actual Plan بود ایندفعه ولی IO رو از Messages فراموش کردی!

این ایندکس رو هم بساز:


USE [Milad]
GO
CREATE NONCLUSTERED INDEX ix2
ON [dbo].[Tbl_Clr_DetailDocument] ([Company],[RNObject],[DIndexState])
INCLUDE ([RefRecNo],[PriValue],[ForValue])

SYNDROME
شنبه 15 خرداد 1389, 15:44 عصر
با سلام و تشکر فراوان از آقا امین گل
خیلی خیلی ممنون
واقعاً خیلی عادی بود.
کمتر از 1 ثانیه
اگر امکان دارد در رابطه با این Plan کمی به من توضیح دهید؟(از کجا شما فهمیدید که Index را چطور و بر روی کدام فیدل قراردهید قرار دهید)
دستور set statistics io ON چه عملی را انجام می دهد؟
موفق و پایدار باشید

AminSobati
شنبه 15 خرداد 1389, 15:50 عصر
عزیزم Plan رو که نفرستادی من ببینم چه تغییری کرده!

دستور set statistics io on بعد از هر کوئری، چه Select باشه چه ویرایش، تعداد IO رو نشون میده که چند Page دسترسی انجام شده

SYNDROME
شنبه 15 خرداد 1389, 15:53 عصر
عزیزم Plan رو که نفرستادی من ببینم چه تغییری کرده!

دستور set statistics io on بعد از هر کوئری، چه Select باشه چه ویرایش، تعداد IO رو نشون میده که چند Page دسترسی انجام شده
با سلام
این هم فایل
با تشکر

SYNDROME
شنبه 15 خرداد 1389, 16:59 عصر
با سلام
انگاری حق با شماست(امان از عاشقی)
فایل را باز هم قرار دادم
خدا کنه درست باشه
با تشکر

AminSobati
شنبه 15 خرداد 1389, 17:37 عصر
داره بهتر میشه، اینها رو هم بسازین:



USE [Milad]
go

create index ix3 on Tbl_Clr_DefineGroupObject
(RecNo,Company) include (CodeGroup, NameGroup)

create index ix4 on Tbl_Clr_GroupObject(Company,RNGroup) include (RNObject)

create index ix5 on Tbl_Clr_GroupObject(RNGroup,Company) include (RNObject)

SYNDROME
شنبه 15 خرداد 1389, 17:45 عصر
داره بهتر میشه، اینها رو هم بسازین:



USE [Milad]
go

create index ix3 on Tbl_Clr_DefineGroupObject
(RecNo,Company) include (CodeGroup, NameGroup)

create index ix4 on Tbl_Clr_GroupObject(Company,RNGroup) include (RNObject)

create index ix5 on Tbl_Clr_GroupObject(RNGroup,Company) include (RNObject)


با سلام
با تشکر
من ظرفیت بهتر ازا ین رو ندارم:لبخند:
IX4 و IX5 شبیه هم بود(البته به نظر من)
ممنون می شوم یک کمی هم به من توضیح بدید
با تشکر

AminSobati
شنبه 15 خرداد 1389, 23:54 عصر
ایندکس 4 و 5 در ترتیب فیلدهاشون با هم متفاوت هستند. چون دیتای شما رو ندارم نمیتونستم بررسی کنم که احتمالا کدوم ترتیب برای Query Processor مناسب تر خواهد بود، لذا هر دو حالتش رو ساختم تا ببینیم کدومش رو استفاده میکنه.
ساخت ایندکس کاری نیست که بشه در چند سطر توضیح داد. ولی به صورت کلی، وقتی Scan داره انجام میشه در حالیکه Search وجود داره، پس ایندکس میتونه کمک کنه. ولی اگر where یا join نداشته باشین پس Scan طبیعیه. یا وقتی از الگوریتم نا مناسب در Join استفاده میشه و همچنین Sort تحمیل شده، در این موارد ایندکس میتونه کمک کنه