خانه/ وبلاگ/ پیدا کردن Query های کند
بهینه‌سازی عملکرد

نحوه پیدا کردن Queryهای کند در SQL Server

عملکرد ۵ شهریور ۱۴۰۴ ۱۱ دقیقه مطالعه

اگر SQL Server به‌طور کلی کند شده و مشکل به یک یا چند Query خاص برمی‌گردد، باید بدانی دقیقاً کدام کوئری‌ها مقصر هستند. SQL Server چند ابزار قدرتمند برای این کار دارد — از نگاه سریع و لحظه‌ای تا آمار تاریخی دقیق.

روش ۱ — پیدا کردن Query های در حال اجرا (لحظه‌ای)

اگر همین الان سیستم کند است و می‌خواهی ببینی چه چیزی در حال اجراست، این کوئری کمک می‌کند:

sql
SELECT r.session_id, r.status, r.command,
  r.cpu_time, r.total_elapsed_time, r.wait_type,
  SUBSTRING(t.text, (r.statement_start_offset/2)+1,
    ((CASE r.statement_end_offset
      WHEN -1 THEN DATALENGTH(t.text)
      ELSE r.statement_end_offset END - r.statement_start_offset)/2)+1) AS running_query
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.session_id <> @@SPID
ORDER BY r.total_elapsed_time DESC;

در SSMS می‌توانی این را با Activity Monitor → Active Expensive Queries هم به‌صورت گرافیکی ببینی.

روش ۲ — پیدا کردن کندترین Query ها به‌صورت تاریخی

برای دیدن آماری از Query هایی که در طول زمان بیشترین منابع را مصرف کرده‌اند (نه فقط همین لحظه)، از sys.dm_exec_query_stats استفاده کن:

sql
SELECT TOP 20
  qs.execution_count,
  qs.total_elapsed_time / qs.execution_count AS avg_elapsed_time_micro,
  qs.total_logical_reads / qs.execution_count AS avg_logical_reads,
  SUBSTRING(qt.text, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
      WHEN -1 THEN DATALENGTH(qt.text)
      ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)+1) AS query_text
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
ORDER BY avg_elapsed_time_micro DESC;
این آمار از زمان آخرین ری‌استارت سرویس SQL Server (یا پاک‌شدن Plan Cache) جمع‌آوری می‌شود. اگر سرور به‌تازگی ری‌استارت شده، ممکن است داده‌ی کافی برای تحلیل نداشته باشی.

روش ۳ — استفاده از Query Store (روش پیشنهادی در نسخه‌های جدید)

از SQL Server 2016 به بعد، Query Store بهترین ابزار برای این کار است چون تاریخچه‌ی کامل عملکرد هر Query را حتی بعد از ری‌استارت سرور نگه می‌دارد. ابتدا آن را فعال کن:

sql
ALTER DATABASE ShopDB SET QUERY_STORE = ON;

بعد از فعال‌سازی، در SSMS مسیر Object Explorer → ShopDB → Query Store → Top Resource Consuming Queries یک نمودار گرافیکی از کندترین Query ها نشان می‌دهد — بدون نیاز به نوشتن کوئری.

روش ۴ — بررسی Execution Plan یک Query خاص

وقتی Query مشکل‌دار را پیدا کردی، برای فهمیدن چرا کند است، Execution Plan آن را بررسی کن (در SSMS دکمه‌ی Include Actual Execution Plan یا Ctrl+M). دنبال این نشانه‌ها بگرد:

  • Table Scan یا Index Scan به‌جای Index Seek — معمولاً یعنی ایندکس مناسب وجود ندارد.
  • عملگرهای پرهزینه مثل Sort یا Hash Match با درصد بالا.
  • اختلاف زیاد بین Estimated و Actual Rows — نشانه‌ی آمار (Statistics) قدیمی.

برای یادگیری کامل خواندن Execution Plan، درس Execution Plans را ببین.

راه‌حل‌های رایج بعد از پیدا کردن Query کند

مشکلراه‌حل
Table Scan روی جدول بزرگساخت Nonclustered Index مناسب
آمار قدیمیUPDATE STATISTICS یا فعال‌کردن Auto Update Statistics
SELECT * روی جدول‌های عریضفقط ستون‌های لازم را انتخاب کن
JOIN بدون ایندکس روی کلیدایندکس روی ستون‌های JOIN بساز

جمع‌بندی

  • برای مشکلات لحظه‌ای، از sys.dm_exec_requests یا Activity Monitor استفاده کن.
  • برای تحلیل تاریخی، sys.dm_exec_query_stats یا Query Store گزینه‌ی بهتری است.
  • بعد از پیدا کردن Query کند، Execution Plan آن را برای علت دقیق بررسی کن.

می‌خوای بهینه‌سازی پرس‌وجو را کامل یاد بگیری؟

فصل ایندکس‌گذاری و بهینه‌سازی دوره‌ی SQLFarsi را ببین.

ادامه‌ی یادگیری