Transact-SQL Optimization Tips

در اینجا ۱۴ نکته خواندنی که می توانید در پرس و جو های خود بکار ببرید تا مطمئن شوید که کدهای T-SQL شما در بهینه ترین حالت ممکن هستند،موجود است:

1. سعی کنید نتایج querieهای خود را با دستوراتWHERE محدودتر کنید .

این کار باعث بهبود کارآیی می شود.چرا کهSQL Server تنها ردیفهای مورد نیاز را به client بر می گرداند نه همه ردیفهای موجود در جدول(ها). این کار باعث کاهش ترافیک شبکه و بهبود کامل کارآیی query می شود .


2. سعی کنید نتایج حاصل از querieها را با  برگرداندن ستونهای خاص (بجای تمام ستونهای جدول)از جدول محدود کنید.

این امر به خوبی در نتیجه بهینه سازی قابل مشاهده است, چون SQL Server تنها ستونهایی خاص را به جای همه ستونها به client  برمی گرداند. این کار باعث کاهش ترافیک شبکه و بهبود کامل کارآیی query می شود .


3. از viewها و stored procedureها بجای querieهای سنگین استفاده کنید.

این کار باعث کاهش ترافیک شبکه شما می شود؛ چرا که client تنها نام  stored procedure یا view را در عوض متن سنگین query به server ارسال می کند (احتمالا با چند پارامتر) . اینکار همچنین مدیریت permission ها را ساده تر می کند. چرا که دسترسی کاربران به ستونهای جداولی که امکان رویتشان برای آنها فراهم نیست محدود می شود.


4. هرجا که امکانپذیر است، از بکار بردن cursorهای SQL Server خودداری کنید.

cursorهایSQL Server  در تنزل کارآیی نتیجه در مقایسه با دستورات select بسیار موثرند. تلاش کنید که از subqueryهای همبسته و یا  جداولی که ایجاد می کنید ، جهت عملیات ردیف به ردیف استفاده کنید.


5. اگر می خواهید که تعداد نهایی ردیفهای جدول را برگردانید ، می توانیدبجای SELECT COUNT(*) statement از راه دیگری استفاده کنید.

بدلیل اینکه SELECT COUNT(*) statement جهت برگرداندن تعداد ردیفهای کل جدول، باعث بررسی کامل جدول می شود،  هنگام اعمال بر روی جدوال بزرگ ، زمان بشدت طولانی را خواهد گرفت. راه دیگری هم برای این کار موجود است. شما می توانید از جدول سیستمی sysindexes  استفاده کنید. در این جدول ستونی بنام ROWS وجود دارد.

این ستون  شامل تعداد ردیفهای هر جدول موجود در DB شما می باشد.. در نتیجه شما می توانید از دستور  select زیر بجای  SELECT COUNT(*)statement بهره برید:

SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2

برای اطلاعات بیشتر در این مورد میتوانید از این مقاله دیدن کنید: Alternative way to get the table's row count. 


6. سعی کنید از constraintها بجای triggerها ، در جایی که مقدور است ، استفاده کنید.

Constraintها بسیار کارآ تر از triggerها هستند و  می توانند در افزایش کارآیی کمک کنند.


7. از متغییرهای tableی بجای temporary tableها استفاده کنید.

متغییرهای از نوع Table نسبت به temporary tableها احتیاج کمتری به lockکردن و logg کردن به منابع دارند، این انواع تنها در نسخه Sql Server 2000 موجودند.


8. هرجا که امکانپذیر است، از بکار بردن دستورات HAVING خودداری کنید.

دستور HAVING جهت محدود کردن نتیجه حاصل از دستور GROUP BY می شود. هنگامی که شما از  GROUP BY همراه با دستور HAVING , استفاده می کنید،دستور  GROUP BY ردیفها را به مجموعه های گروهبندی شده تقسیم می کند و داده های آنها را با هم جمع می بندد و سپس  دستور HAVING گروه های نامطلوب را حذف می کند. در بسیاری موارد شما می توانید دستورات select خود را با استفاده از where و group by و بدون استفاده از دستور    HAVING بنویسید که باعث افزایش کارآیی query شما می شود.


9. هرجا که امکانپذیر است، از بکار بردن دستورات DISTINCT خودداری کنید.

چرا که استفاده از دستور DISTINCT در پایین آوردن میزان کارآیی در برخی موارد تاثیر دارد., تنها زمانی که واقعا به آن نیاز است استفاده کنید.


10.دستور SET NOCOUNT ON  را در ابتدای stored procedureهای خود قرار دهید تا پس از اجرای procedure شما پیغامی مبنی بر تعداد ردیفهای حاصل از اجرای دستور T-SQLرا برنگرداند، که این امر می تواند مانع افزایش ترافیک شبکه بجهت عدم دریافت این پیغام توسط سرویس گیرنده های شما شود.


11.از دستور Select  با استفاده از کلمه کلیدی Top و یا دستور SET ROWCOUNT در هنگامی که نیاز به دریافت n رکورد اولیه را دارید، استفاده کنید.این امر می تواند کارایی پرس و جو های شما را بهبود بخشد، چرا که مجموعه جواب کوچکتری برگردانده می شود که بر ترافیک شبکه بین سرویس دهنده و سرویس گیرنده هم تاثیرگذار خواهد بود.


۱۲.از اشاره گر FAST number_rows مربوط به جدول جهت برگرداندن سریع  مقدار number_rows  استفاده کنید.در این حالت شما قادرید با نتیجه بدست آمده کار کنید، در حالیکه هنوز پرس و جو و یا procedure مشغول کار کردن بر روی نتیجه کامل خود هستند.


13. سعی کنید که از جملات UNION ALL بجای UNION در هر جا که امکان پذیر است استفاده کنید.

جمله UNION ALL بسیار سریعتر از UNION, است، چون جمله UNION ALL بدنبال ردیفهای تکراری نمی گردد در حالیکه جمله UNION بدنبال ردیفهای تکراری می گردد که آیا موجودند یا خیر.


14. از optimizer hintsدرqueriy های خود استفاده نکنید.

چون بهینه ساز query در sql server بسیار باهوش است ،ابدا از optimizer hints در بهینه سازی کدهای خود استفاده نکنید، چه بسا باعث بدتر شدن آن شوید!!

اصل مقاله:http:/www.databasejournal.com/features/mssql/article.php/1437391

نویسنده مقاله:Alexander Chigrik

linked server ها(۳)

قسمت اول ،قسمت دوم ، قسمت چهارم

مبحث کارآیی

سبک تبادل اطلاعات با remote sever شامل overhead بزرگی است که تنها شامل log in به remote server نمی شود، بلکه دریافت اطلاعات از remote server هم در آن می گنجد. بر طبق یک آنالیزی که انجام شده، بطور تخمینی اجرای یک Query تحت remote server تقریبا بیش از ۲۰ برابر اجرای ان بصورت Local منابع را اشغال کرده است.هنگامی که جدول نویسندگان را بر روی هر دو سرور با داده های زائد قرار دادم و showplan را اجرا کردم، حدودا ۳ برابر بیشتر زمان صرف شد.

اگر شما داده های بیش از نیازتان از remote server  درخواست کنید، سرعت اجرای query و حتی کارآیی کل شبکه را کاهش خواهید داد و ممکن است مدیر شبکه وارد شده و بر سرتان فریاد بکشد!

کاهش ترافیک

با دستور where ما این امکان را خواهیم داشت که بجای کل جدول ، داده هایی را که دقیقا مورد نظر است از remote server بازیابی کرده و به شکل محسوسی کارآیی را بالا ببریم.

select r.au_fname as remote_fname,r.au_lname as remote_lname,   l.*

from  authors l              

join  fuji_PUBS_DB.pubs.dbo.authors r

on    l.au_id = r.au_id

where (l.au_fname <> r.au_fname OR l.au_lname <> r.au_lname )

and   r.au_id in ('172-32-1176', '213-46-8915', '238-95-7766', '267-41-2394')

 توجه کنید که ردیفهایی که بصورت local موجودند را از سرور local  و تنها ردیفهایthe au_fname و au_lname  از remote server بازیابی شده اند. اگر دستور "select * from" را برای بازیابی داده ها استفاده می کردیم،SQL Server مجبور به بازیابی همه ستونها ،‌حتی آنهایی که نگاهی به آنها نمی اندازیم می شد. SQL Server 2000 به اندازه ای باهوش است که تنها ۲ردیف مورد نظر و یک ردیف au_id را بعنوان شناسه استفاده شده در دستور where را که مورد نیاز است،بازیابی کند. تنها ذره ای برنامه نویسی تر وتمیز توسط شما با MS SQL Server لازم است!

شما می توانید با استفاده از Query Analyser ، با نمایش execution plan و تمرکز روی آیکون remote query ، چک کنید که آیا query شما بهینه است یا خیر.

فراخوانی Stored Procedureها

 Stored procedureها بر روی remote server به راحتی اجرا می شوند، اما server در ابتدا نیاز دارد که برای RPC تنظیم شود.برای این کار تنها به کد زیر احتیاج است:

sp_serveroption fuji_PUBS_DB, [rpc out], true

این کد تنها یکبار می بایست اجرا شود.

برای صدا کردن stored procedure ها می توان طبق همان فرمول ۴ قسمتی فراخوانی جداول عمل کرد:

exec fuji_PUBS_DB.master.dbo.sp_who2


تغییر داده هایRemote

تغییر و بروز رسانی جداول در سرور پیوندی(linked server) هم مسئله خاصی ندارد.در اینجا مثال ساده ای بر مبنای select ی که جداول authors روی سرورهای دور از هم(remote) را با هم join کرده موجود است:

UPDATE fuji_PUBS_DB.pubs.dbo.authors

SET   au_fname = r.au_fname,     au_lname = r.au_lname

from  fuji_PUBS_DB.pubs.dbo.authors r join  authors l   on l.au_id = r.au_id

where (  l.au_fname <> r.au_fname OR  l.au_lname <> r.au_lname)

با این دستور update ، نیاز به ۲ رفت و برگشت جداگانه به سرور پیوندی(linked server) است. یک گردش که داده ها را از سرور پیوندی به سرور محلی می آورد برای جایگزینی در join. دومین گردش تغییرات واقعی روی ردیف های داده ای که  sql server نیاز به اعمال تغییرات بر روی آنها دارد را اجرا می کند.

مباحث بیشتر پیرامون کارآیی

در این مثال ردیفهایی را که به آنها مشکوک بودم کنار گذاشتم ، در صورتی که اگر آنها را وارد  می کردم، کارآیی پرس و جو می توانست بهتر شود، چرا که ردیفها در نتیجه نهایی linked server فیلتر می شد و داده های کمتری در سطح شبکه جریان می یافت و کار کمتری در join انجام می شد.

شبیه تمام تراکنش های update ، بروزرسانی(update) در linked server ها هم در یک تراکنش(transaction) صورت می گیرد.پردازش تراکنش ها هم به همین منوال نسبت به پردازش در سطح local زمان بیشتری صرف می کند که به همین جهت تراکنش های توزیع شده ای به این شکل را باید با صرف دقت بیشتر ، به شکل کارآ تری طراحی کرد.در ضمن شما می توانید چندین update در یک تراکنش توزیع شده داشته باشید

 اصل مقاله:http://www.databasejournal.com/features/mssql/article.php/10894_1438991_3

نویسنده:Neil Boyle

 

ادامه دارد...