اصلاح آرگومان جستجو در کوئری

اصلاح آرگومان جستجو در کوئری

نوشته شده توسط: تورج عزیزی
تاریخ انتشار: ۲۶ دی ۱۳۹۴
آخرین بروزرسانی: 30 بهمن 1403
زمان مطالعه: 3 دقیقه
۵
(۱)

آرگومان جستجو در کوئری، در این مقاله می خواهیم راجع به مشکل بخصوصی که به indexing در پایگاه داده SQL Server مربوط می شود صحبت کنیم. نمونه کوئری زیر را در نظر بگیرید، مثل این کوئری را صدها بار در SQL Server دیده اید:

 -- Results in an Index Scan
SELECT*FROM Sales.SalesOrderHeader
WHEREYEAR(OrderDate)= 2005 ANDMONTH(OrderDate)= 7
GO
با این کوئری ساده ما اطلاعات فروش را راجع به ماه خاصی از یک سال خاص را درخواست می کنیم.خیلی پیچیده نیست. اما متاسفانه این کوئری خیلی خوب عمل نمی کند. حتی با وجود یک Nonclustered Index روی ستون OrderDate. وقتی به پلن اجرا نگاه می کنید، می توانید ببینید که Query Optimizer از ایندکس Nonclustered که روی OrderDate تعریف شده استفاده کرده اما متاسفانه SQL Serverیک اسکن کامل به جای اینکه یک عمل Seek موثر از ایندکس انجام میدهد. 
در حقیقت این یک مشکل برای SQL Server محسوب نمی شود، این روشی است که دیتابیس های رابطه ای کار می کنند و فکر می کنند! به محض اینکه یک عبارت (فراخوانی توابع یا محاسبات) روی یک ستون دارای ایندکس (که Search Argument هم نامیده می شود) اعمال کنید، موتور دیتابیس باید آن ایندکس را Scan کند، به جای اینکه یک عمل Seek انجام دهد. افراد علاقه‌مند می‌توانند با مطالعه مقاله پرکاربردترین دستورات SQL Server، دانش خود را در زمینه کوئری‌نویسی گسترش دهند.

آرگومان جستجو در کوئری

برای اینکه عمل اسکن ایندکس به Seek تغییر کند، باید کوئری را طوری بنویسیم که دیگر تابع DATEPART فراخوانی نشود:
-- Results in an Index Seek
SELECT*FROM Sales.SalesOrderHeader
WHERE OrderDate >='20050701'AND OrderDate <'20050801'
GO

و همانطوری که در کوئری بازنویسی شده می بینید، این کوئری نتایج مشابهی برمی گرداند، اما ما فقط فراخوانی تابع DATEPART را حذف کرده ایم. وقتی به پلن اجرا نگاه می کنید، می بینید که SQL Server یک عمل Seek انجام می دهد- در این کوئری عمل Seekاصطلاحاً Partial Range Scanنامیده می شود: SQL Server مقدار اول را جستجو می کند و عمل اسکن را تا زمانی که به آخرین مقدار درخواستی در محدوده نرسیده ادامه می دهد. اگر مجبور هستید در متن ستون های ایندکس دار فراخوانی کنید، شما باید مطمئن شوید که این فراخوانی به تابع در سمت راست ستون شما در کوئری اجرا می شوند. اجازه دهید به این مثال نگاهی بیندازیم. اجازه دهید به کوئری زیر نگاهی بیندازیم. کوئری زیر ستون دارای ایندکس CreditCardIDرا به دیتا تایپ CHAR (4) تبدیل می کند:

-- Results in an Index Scan
SELECT*FROM Sales.SalesOrderHeader
WHERECAST(CreditCardID ASCHAR(4))='1347'
GO
وقتی نگاهی دقیق تر به پلن اجرا دارید، می توانید ببینید SQL Server ایندکس Nonclustered را به تمامی اسکن کرده است. اگر شما این تبدیل را در سمت راست ستون ایندکس دار در کوئری اجرا کنید، می توانید دوباره می توانید فراخوانی روی ستون ایندکس دار را حذف کنید و SQL Server خواهد توانست عمل Seek انجام دهد:
 -- Results in an Index Seek
SELECT*FROM Sales.SalesOrderHeader
WHERE CreditCardID =CAST('1347'ASINT)
GO

سخن پایانی

آرگومان جستجو در کوئری، همان طور که در این پست دیدید، بسیار حائز اهمیت است که هیچ تابعی مستقیم یا غیر مستقیم روی ستون های دارای ایندکس فراخوانی نکنید. در غیر اینصورت SQL Server باید ایندکس را Scan کند، به جای اینکه یک عمل Seek موثر انجام دهد. این روش‌ها می‌توانند به شما کمک کنند تا آرگومان‌های جستجوی خود را در کوئری‌های SQL بهبود بخشید و عملکرد بهتری داشته باشید. ما در نیک آموز منتظر نظرات ارزشمند شما درباره این مقاله هستیم.


مشاهده کامل‌ترین و بروزترین آموزش sql server در نیک آموز


چه رتبه ای می‌دهید؟

میانگین ۵ / ۵. از مجموع ۱

اولین نفر باش

title sign
معرفی نویسنده
تورج عزیزی
مقالات
18 مقاله توسط این نویسنده
محصولات
0 دوره توسط این نویسنده
تورج عزیزی
title sign
دیدگاه کاربران

    •     بسیار عالی و موثر توضیح دادید … با تشکر

    •     بسیار جالب بود جناب عزیزی

      پس نتیجه می گیریم به جای اینکه SQL را وادار کنیم تا اطلاعات یافته شده را به فرمت دلخواه ما CAST کند ما بیاییم فرمت اطلاعات ورودی را به فرمت ذخیره شده CAST کنیم
      بسیار عالی
    • سلام

          در مقاله به همین موضوعی که شما فرمودید اشاره شده و نتیجه گیری شما درست است

      به مثال های زیر هم توجه کنید
      ad: Select … WHERE isNull(FullName,’Ed Jones’) = ‘Ed Jones’
      Fixed: Select … WHERE ((FullName = ‘Ed Jones’) OR (FullName IS NULL))
      Bad: Select … WHERE SUBSTRING(DealerName,4) = ‘Ford’
      Fixed: Select … WHERE DealerName Like ‘Ford%’
      Bad: Select … WHERE DateDiff(mm,OrderDate,GetDate()) >= 30
      Fixed: Select … WHERE OrderDate < DateAdd(mm,-30,GetDate()) 
      ضمنا مفهوم SARGable predicate را در نظر داشته باشید
  • 1
  • 2

دانلود رایگان: آموزش SQL Server

هر روز یک ویدئو آموزشی رایگان برای شما ایمیل خواهد شد!

پاپ آپ | SQL Server

  • این قسمت برای اهداف اعتبارسنجی است و باید بدون تغییر باقی بماند.