PDA

View Full Version : نکاتی در مورد بهینه سازی Transact-SQL



samispeed
دوشنبه 11 خرداد 1388, 12:56 عصر
نکاتی در مورد بهینه سازی Transact-SQL
نمی دونم تا حالا در این مورد صحبتی شده یا نه اما این ها نکات کلیدی که به درد من زیاد خورده گفتم شاید برای شما هم کاربرد داشته باشه و باعث بالا رفتن سرعت برنامه تون بشه
· با استفاده از شرط WHERE سعی کنید نتایج query هاتون رو محدود کنید :
این کار باعث افزایش کارآیی می شود چون فقط سطرهای خاصی را Sql server بر می گرداند نه تمام سطرها و باعث کاهش ترافیک شبکه می شود

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

· از View و stored procedure ها به جای query های که مخصوص کارهای پیچیده و متن طولانی داره استفاده کنید :
که باعث کاهش ترافیک شبکه می شود چون کلاینت فقط اسم view یا stored procedure (یا بعضی پارامتر ها) را به سرور می فرستد در حالیکه تو حالت دوم متن طولانی از query را می فرستد

· تا جایی که امکان دارد از cursor ها استفاده نکنید
چون وقتی که اطلاعات زیاد بشه باعث کندی سیستم و همچنین قفل شدن جدول می شود

· اگر احتیاج داشتید که تعداد کل ردیف های جدول را بدست آورید می توانید به جای عبارت
Select count (*) از راه حل دیگری استفاده کنید :
چون این عبارت یک جدول را بطور کامل scan می کند تا تعداد ردیف های جدول را بدست بیاورد برای جدول هایی با اطلاعات زیاد زمان زیادی می برد . راه دیگری که وجود دارد این است که می توانیم از جدول sysindexes
استفاده کنیم ستونی در این جدول وجود دارد که تعداد کل ردیف های هر جدولی که در پایگاه داده ما قرار دارد را نمایش می دهد شما می توانید با این دستور


SELECT rows


FROM sysindexes


WHERE id = OBJECT_ID('table_name') AND indid < 2

تعداد کل یک جدول را بدست آورید که باعث می شود سرعت جوابگیری بهینه شود

· تا جایی که امکان دارد از Constraint ها به جای Trigger ها استفاده کنید چون کارآیی بالاتری دارند

· بهتر است از شرط HAVING تا جایی که امکان دارد کمتر استفاده شود :
وقتی GROUP BY با شرط HAVING استفاده می شود شرط GROUP BY سطرها را به دسته ای از سطرهای گروه بندی شده تقسیم می کند و سپس شرط HAVING گروههای نامطلوب را حذف می کند در بیشتر موارد می توانید از WHERE و GROUP BY بدون HAVING استفاده کنید که این کار کارآیی QUERY را بهبود می بخشد .

· تا جایی که امکان دارد از شرط DISTINCT استفاده نکنید

· از عبارت SETNOCOUNTON در stored procedure ها استفاده کنید :
چون باعث می شود ترافیک شبکه کاهش پیدا کند چون کلاینت پیغام number of rows affected را دریافت نمی کند

· از SELECT بهمراه TOP یا SET ROWCOUNT زمانیکه می خواهید چند ردیف را نشان دهید استفاده کنید :
چون نتایج کوچکتری را برمی گرداند باعث کاهش ترافیک بین سرور و کلاینت می شود.

· از transactions ها استفاده کنید مخصوصا برای Query های که مدت زمان اجرای آنها طولانی است.
· از نوع داده TEXT و NTEXT فقط در مواردی که اطلاعات واقعا زیاد استفاده کنید چون این نوع داده در Query ها کند و انعطاف پذیری کمی دارد .

همیشه برنامه هاتون با داده زیاد تست کنید چون وقتی با یک حجم اطلاعاتی کم برنامه تون تست می کنید ممکنه سرعت خوبی داشته باشد اما وقتی کاربر نهایی اون را با داده های زیاد اجرا می کند سرعت برنامه تون کاهش پیدا کنه .

ASKaffash
دوشنبه 11 خرداد 1388, 13:55 عصر
سلام
چقدر خوب است که یک تاپیک برای این موضوع در نظر گرفته شود چون این نمونه برای پروژه های بزرگ بسیار مهم است اگر این تاپیک ایجاد شود مواردی برای ارائه دارم

amin_alexi
دوشنبه 11 خرداد 1388, 15:54 عصر
منم موافقم
شاید بهتر باشه در ادامه همین تاپیک که عنوان مناسبی هم داره ادامه بدیم .... تا مطالب پراکنده نشه :چشمک:
و هر کسی که نظر یا مطلبی داره بگه تا بقیه هم استفاده کنند

ASKaffash
سه شنبه 12 خرداد 1388, 11:22 صبح
سلام
من برای شروع کار که ببینیم چقدر افراد علاقه مند به این موضوع وجود دارد از یک سئوال به ظاهر ساده ولی فنی شروع میکنم:
فرض کنیم در جدولی بنام T فیلدی داریم بنام P که روی آن ایندکس وجود دارد سئوال آیا دستور ذیل روشی مناسب برای استخراج داده است در غیر اینصورت دستور چه تغییری کند که سرعت بهتری بدست آید و دلیل موضوع چیست ؟


Select * From T Where P In(10,20)

amin_alexi
سه شنبه 12 خرداد 1388, 13:59 عصر
سلام

من برای شروع کار که ببینیم چقدر افراد علاقه مند به این موضوع وجود دارد از یک سئوال به ظاهر ساده ولی فنی شروع میکنم:
فرض کنیم در جدولی بنام T فیلدی داریم بنام P که روی آن ایندکس وجود دارد سئوال آیا دستور ذیل روشی مناسب برای استخراج داده است در غیر اینصورت دستور چه تغییری کند که سرعت بهتری بدست آید و دلیل موضوع چیست ؟
کد:
Select * From T Where P In(10,20)

من Query رو به این صورت مینویسم

Select * From T Where P =10 or P=20
در حالتی که شما نوشتی با توجه به اینکه روی P ایندکس وجود داره ولی برای Search در T و در فیلد P مجبوره کل جدول رو Scan کنه .... و هر سطر رو به دو مقدار 10 و 20 چک کنه ...
ولی در حالتی که من نوشتم از Index استفاده می کنه و عمل Seek رو Index انجام میشه
امید وارم درست گفته باشم ...
سایر دوستان هم شرکت کنند بحث هم شیرینه و هم مفید!

seeco1234
چهارشنبه 13 خرداد 1388, 15:53 عصر
-....................

Hamid.Kad
پنج شنبه 14 خرداد 1388, 11:38 صبح
optimizer خیلی باهوش تر از این حرفهاست. خودش این عبارات رو به فرم بهینه تبدیل می کنه. ولی برای سادگی کارش بهتره که عبارات را تا حد امکان خودمون ساده کنیم. بهینه سازها مشکل اصلیشون توی ترتیب پیوندها است که قبلاً یه کم راجع به این مساله توضیح داده شده. مورد اولی هم که جناب Sami فرمودند یکی از کاربردهاش توی پیوندهاست(join)
برای مورد سومی هم که ذکر شد فکر میکنم که علاوه بر دلیلی که فرمودید، دلیل اصلیش اینه که sp ها کامپایل می شوند.(البته میشه تنظیم کرد که در هر بار اجرا مجدداً کامپایل بشن ولی این پیش فرضشون نیست). در مقایسه با یک کوئری طولانی که باید ارسال بشه و کامپایل بشه تا براش QEP بدست بیاد، SP ها هزینه کمتری رو به DBMS تحمیل می کنند.

ASKaffash
شنبه 16 خرداد 1388, 07:37 صبح
سلام به همه دوستانی که در بحث مشارکت میکنند
من دنبال همین موضوع بودم اگر این Query را ایجاد کنید و بعد به Cost ها در Execution Plan نگاه کنید خواهید دید که دستور مشابه Select * From T Where P =10 or P=20 در نظر گرفته شده است (همان صحبت جناب Amin_Alexi) ولی ظاهرا باید کل جدول Scan شود (چون Or بکار رفته است)
حال دستور را به شکل ذیل مینویسیم :


Select * From T Where P=10
Union All
Select * From T Where P=20

به نظر دوستان حال Execution Plan چه رویکردی را نشان میدهد؟
(دوستان هدفم این است که با پرسش و پاسخ تبادل فکری نمائیم)