
یادگیری سی شارپ از مفاهیم پایه تا پروژه محور: شیگرایی، کار با SQL و LINQ، ORMها (Entity Framework)، ساخت پروژه مدیریت رستوران با گزارشات حرفهای و امکانات کامل!
مشاهده بیشتر
تو این دوره SQL Server رو از صفر تا پیشرفته یاد میگیری! از تراکنشها و طراحی دیتابیس تا Query نویسی حرفهای و پروژههای واقعی مثل مدیریت فروش و سیستم مالی. همه چی رو با مثال و تمرین یاد میگیری و یه متخصص دیتابیس میشی!
مشاهده بیشترمشخصات مقاله
اجتناب از استفاده از نابرابری در عبارت WHERE
اجتناب از استفاده از نابرابری در عبارت WHERE
در بسیاری از موارد وقتی از اپراتور <> استفاده می کنیم (یا هر اپراتور دیگری در ارتباط با NOT، به عنوان مثال NOT IN) جستجوهای ایندکس اجرا نخواهند شد و در عوض اسکن یک جدول یا ایندکس لازم می باشد.
توضیحات
برای این مثال اجازه بدهید یکی از جدول های تست خود را آپدیت کنیم تا داده را کمی تغییر دهیم. و همچنین به ستونی که در عبارت WHERE استفاده خواهد شد، در جدول یک ایندکس اضافه می کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 | UPDATE [dbo].[Child] SET IntDataColumn=60000 UPDATE [dbo].[Child] SET IntDataColumn=3423 WHERE ParentID=4788 UPDATE [dbo].[Child] SET IntDataColumn=87347 WHERE ParentID=34268 UPDATE [dbo].[Child] SET IntDataColumn=93423 WHERE ParentID=84938 UPDATE [dbo].[Child] SET IntDataColumn=5564 WHERE ParentID=74118 CREATE NONCLUSTERED INDEX idxChild_IntDataColumn ON [dbo].[Child] ([IntDataColumn],[ParentID]) INCLUDE ([ChildID]) -- cleanup statements --DROP INDEX Child.idxChild_IntDataColumn <button></button> |
اکنون جازه بدهید نگاهی به یک query ساده داشته باشیم که همه ی رکوردها را در IntDataColumn <> 60000 بازمی گرداند. در اینجا آنچه را می بینید که به نظر می رسد:
1 2 3 4 5 | SELECT P.ParentID,C.ChildID,C.IntDataColumn FROM [dbo].[Parent] P INNER JOIN [dbo].[Child] C ON P.ParentID=C.ParentID WHERE C.IntDataColumn <> 60000 <button></button> |
با نگاه کردن به طرح توضیح (explain plan) برای این query، متوجه نکته ی بسیار جالبی خواهیم شد. از آنجایی که optimizer (بهینه ساز)، روی داده در این ستون دارای استاتیک هایی می باشد، query را بازنویسی کرده تا عبارت های مجزای < and > استفاده کند. این مسئله را به طور دقیق روی Index Seek زیر تیتر Seek Predicate مشاهده می کنیم.

اکنون اجازه بدهید ببینیم اگر دو عبارت <> داشته باشیم، چه اتفاقی می افتد، مانند زیر:
1 2 3 4 5 | SELECT P.ParentID,C.ChildID,C.IntDataColumn FROM [dbo].[Parent] P INNER JOIN [dbo].[Child] C ON P.ParentID=C.ParentID WHERE C.IntDataColumn <> 60000 and C.IntDataColumn <> 5564 <button></button> |
با نگاه به explain plan برای این query، مشاهده می کنیم که optimizer در عبارت WHERE تغییراتی انجام داده است. این برنامه اکنون از مقدار جدید که درSeek Predicate اضافه کردیم و یا مقدار اصلی، مانند دیگر Predicate ها استفاده می کند. هر دو تغییر کرده اند تا از عبارت های مجزای < and > استفاده کنند.

گرچه تغییرات ایجاد شده به وسیله ی optimizer ، با جلوگیری از index scanقطعا به query کمک کرده، اگر بهترین اجرای ممکن را می خواهید، همیشه بهتر است از یک اپراتور تساوی مانند = یا IN در query خود استفاده کنید. قبل از اعمال تغییرات مشابه، نکته ای که باید به آن توجه کنید این است که باید اطمینان اصل کنید که درک خوبی از داده ی خود دارید، زمانیکه جدول داده می تواند روی نتایج query شما تاثیر بگذارد. با آنچه گفته شده و ارائه شده است می دانیم که جدول ما رکوردهای کمی دارد که شرایط WHERE را کامل می کند، اجازه بدهید آن را به یک اپراتور تساوی تغییر داده و تفاوت اجرا را مشاهده کنیم.
در اینجا query جدید را مشاهده می کنید:
1 2 3 4 5 | SELECT P.ParentID,C.ChildID,C.IntDataColumn FROM [dbo].[Parent] P INNER JOIN [dbo].[Child] C ON P.ParentID=C.ParentID WHERE C.IntDataColumn IN (3423,87347,93423) <button></button> |
با نگاه کردن به explain plan برای این query، متوجه می شویم که این برنامه نیز در حال انجام جستجوی ایندکس می باشد، اما با نگاه عمیق تر به Seek Predicate ، متوجه می شیم که در حال استفاده از اپراتور تساوی می باشد که باید بسیار سریعتر باشد:

اکنون اجازه بدهید برای این دو query نگاهی به نتایج SQL Profiler بیندازیم، در زیر مشاهده می کنیم که مثالی که از اپراتور تساوی استفاده می کند، سریعتر اجرا شده و به منابع کمتری نیاز دارد. نکته: هر دو query یک مجموعه نتیجه را گزارش می دهند.