آموزش sys.dm_exec_sql_text در SQL Server با ۱۰ مثال عملی و نکات Performance

آموزش جامع sys.dm_exec_sql_text در SQL Server

توسط admin | گروه SQL Server | 1405/04/30

نظرات 0

آموزش جامع sys.dm_exec_sql_text در Microsoft SQL Server

این مقاله یک راهنمای عملی از سطح مقدماتی تا حرفه‌ای است و روی استفاده واقعی در عیب‌یابی، تحلیل Performance و مانیتورینگ SQL Server تمرکز دارد. هدف فقط معرفی Syntax نیست؛ بلکه یاد می‌گیریم چگونه داده خروجی را تفسیر کنیم، آن را با DMVهای دیگر ترکیب کنیم و از نتیجه‌گیری شتاب‌زده جلوگیری کنیم.

بازگشت به راهنمای مادر: راهنمای جامع توابع Execution Plan در SQL Server

در محیط Production قبل از اجرای Queryهای عیب‌یابی، سطح دسترسی، حجم Plan Cache، تعداد Sessionها و هزینه احتمالی جمع‌آوری داده را بررسی کنید. Diagnostic Query نامناسب می‌تواند در زمان Incident فشار اضافه ایجاد کند.

تعریف و کاربرد اصلی

sys.dm_exec_sql_text برای بازیابی متن Batch یا Query از روی sql_handle یا plan_handle طراحی شده است. این ابزار بخشی از مجموعه Dynamic Management Objects موتور Database Engine است و معمولاً زمانی استفاده می‌شود که DBA یا Developer می‌خواهد از علائم کلی مانند CPU بالا، کندی، Blocking یا Recompile به شواهد دقیق‌تری برسد.

در عمل هیچ DMV یا DMF به‌تنهایی پاسخ کامل نمی‌دهد. بهترین تحلیل زمانی شکل می‌گیرد که اطلاعات این آبجکت با sys.dm_exec_requests، sys.dm_exec_query_stats، sys.dm_exec_cached_plans، Query Store، Wait Statistics و متن SQL کنار هم قرار گیرد. این نگاه ترکیبی از اشتباه رایج «دیدن یک Plan و صدور حکم قطعی» جلوگیری می‌کند.

کاربرد شاخص این ابزار: بازیابی متن Batch یا Query از روی sql_handle یا plan_handle. بنابراین قبل از اجرا مشخص کنید سؤال فنی شما چیست و دقیقاً دنبال کدام Session، Plan یا Query هستید.

Syntax، ورودی و خروجی

نحو پایه

SELECT *
FROM sys.dm_exec_sql_text(@sql_handle_or_plan_handle);

پارامتر یا Context موردنیاز

ورودی می‌تواند sql_handle یا plan_handle از نوع varbinary(64) باشد. این Handleها معمولاً از DMVهای اجرایی مانند sys.dm_exec_requests و sys.dm_exec_query_stats گرفته می‌شوند.

نوع خروجی

ستون‌های dbid، objectid، number، encrypted و text را برمی‌گرداند. text از نوع nvarchar(max) است و متن SQL را نگه می‌دارد.

ستون یا مفهومکاربرد
dbidشناسه دیتابیس، با محدودیت برای Ad hoc
objectidشناسه آبجکت در ماژول‌ها
encryptedآیا متن رمزگذاری شده است
textمتن Batch یا Query

مقادیر Handle مانند plan_handle و sql_handle شناسه‌های باینری موقت هستند. آنها را به‌عنوان شناسه دائمی کسب‌وکار ذخیره نکنید. Recompile، Eviction، Restart سرویس یا تغییرات Cache می‌تواند اعتبار عملی آنها را تغییر دهد.

پیش‌نیازهای امنیتی و نکات نسخه

جایگزین مدرن fn_get_sql است و در سناریوهای مانیتورینگ، تحلیل Queryهای پرمصرف و بررسی درخواست‌های فعال بسیار پرکاربرد است.

در بسیاری از نسخه‌ها برای مشاهده اطلاعات سراسری Server به مجوزهای خانواده VIEW SERVER STATE یا در نسخه‌های جدیدتر VIEW SERVER PERFORMANCE STATE نیاز دارید. برخی DMVهای Database-scoped نیز مجوزهای Database Performance State می‌خواهند. حساب Service یا Application را صرفاً برای راحتی مانیتورینگ عضو sysadmin نکنید؛ اصل Least Privilege را رعایت کنید.

در Azure SQL Database و Managed Instance دامنه دید Sessionها و نام Permissionها می‌تواند متفاوت باشد. اسکریپت Production باید نسخه، Edition و محیط اجرا را تشخیص دهد و در صورت نبود مجوز، خطای قابل فهم برگرداند.

مثال‌های عملی

مثال 1: متن Queryهای فعال

sql_handle درخواست‌های فعال را به متن SQL تبدیل می‌کنیم.

SELECT
    r.session_id,
    r.status,
    st.text
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE r.session_id <> @@SPID;
session_idstatustext
58runningSELECT ...

نکته کاربردی: برای تشخیص سریع اینکه هر Session چه Batchی اجرا می‌کند مناسب است.

مثال 2: متن Queryهای پرCPU

متن Queryهای دارای بیشترین CPU تجمعی را نمایش می‌دهیم.

SELECT TOP (10)
    qs.total_worker_time,
    qs.execution_count,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
ORDER BY qs.total_worker_time DESC;
total_worker_timeexecution_counttext
950000120SELECT ...

نکته کاربردی: اولویت‌بندی بر اساس CPU قبل از خواندن متن، تحلیل را هدفمند می‌کند.

مثال 3: استخراج Statement از Batch

با Offsetها فقط Statement مربوط به ردیف Query Stats را جدا می‌کنیم.

SELECT TOP (10)
    SUBSTRING
    (
        st.text,
        (qs.statement_start_offset / 2) + 1,
        (
            (CASE qs.statement_end_offset
                WHEN -1 THEN DATALENGTH(st.text)
                ELSE qs.statement_end_offset
             END - qs.statement_start_offset) / 2
        ) + 1
    ) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st;
statement_text
SELECT OrderID, ...

نکته کاربردی: Offsetها بر حسب بایت هستند و تقسیم بر دو برای nvarchar اهمیت دارد.

مثال 4: تشخیص Ad hoc Queryها

Batchهایی که objectid ندارند به‌عنوان کاندید Ad hoc بررسی می‌شوند.

SELECT TOP (20)
    st.dbid,
    st.objectid,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE st.objectid IS NULL
ORDER BY qs.last_execution_time DESC;
dbidobjectidtext
NULLNULLSELECT ...

نکته کاربردی: برای Ad hoc، dbid از sql_handle همیشه قابل اتکا نیست.

مثال 5: نمایش نام Stored Procedure

برای متن‌های ماژولی نام آبجکت را از dbid و objectid می‌سازیم.

SELECT TOP (20)
    DB_NAME(st.dbid) AS database_name,
    OBJECT_NAME(st.objectid, st.dbid) AS object_name,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE st.objectid IS NOT NULL;
database_nameobject_nametext
SalesDbusp_ReportCREATE PROCEDURE ...

نکته کاربردی: در ماژول‌ها اتصال متن به نام Object عیب‌یابی را ساده‌تر می‌کند.

مثال 6: بررسی متن رمزگذاری‌شده

ستون encrypted و وضعیت text را بررسی می‌کنیم.

SELECT TOP (50)
    st.encrypted,
    st.objectid,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE st.encrypted = 1;
encryptedobjectidtext
1245575913NULL

نکته کاربردی: برای آبجکت رمزگذاری‌شده انتظار متن کامل نداشته باشید.

مثال 7: متن Queryهای Blocked

Sessionهای Blocked را همراه Batch ورودی نشان می‌دهیم.

SELECT
    r.session_id,
    r.blocking_session_id,
    r.wait_type,
    st.text
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE r.blocking_session_id > 0;
session_idblocking_session_idwait_typetext
7255LCK_M_SSELECT ...

نکته کاربردی: این الگو برای تحلیل Blocking یکی از کاربردی‌ترین ترکیب‌ها است.

مثال 8: استفاده از plan_handle به جای sql_handle

همان تابع می‌تواند plan_handle را نیز دریافت کند.

DECLARE @plan_handle varbinary(64);
SELECT TOP (1) @plan_handle = plan_handle
FROM sys.dm_exec_cached_plans
ORDER BY usecounts DESC;

SELECT dbid, objectid, text
FROM sys.dm_exec_sql_text(@plan_handle);
dbidobjectidtext
7NULLSELECT ...

نکته کاربردی: در برخی سناریوها plan_handle برای تعیین Context اطلاعات بیشتری نسبت به sql_handle می‌دهد.

مثال 9: Queryهای با Logical Read بالا

متن Queryهای پرمصرف I/O را بازیابی می‌کنیم.

SELECT TOP (10)
    qs.total_logical_reads,
    qs.execution_count,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
ORDER BY qs.total_logical_reads DESC;
total_logical_readsexecution_counttext
850000044SELECT ...

نکته کاربردی: ترکیب متن با معیار I/O برای یافتن Queryهای Scan-heavy مفید است.

مثال 10: کاهش خروجی با فیلتر زمان آخرین اجرا

فقط Queryهای اخیراً اجراشده را می‌خوانیم.

SELECT TOP (50)
    qs.last_execution_time,
    st.text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE qs.last_execution_time >= DATEADD(MINUTE, -30, SYSDATETIME())
ORDER BY qs.last_execution_time DESC;
last_execution_timetext
2026-07-21 12:10:00SELECT ...

نکته کاربردی: فیلتر زمانی از تولید گزارش حجیم و کم‌ارزش جلوگیری می‌کند.

خطاهای رایج و روش عیب‌یابی

برای Ad hoc Queryها مقدار dbid از sql_handle همیشه قابل تعیین نیست. در آبجکت‌های رمزگذاری‌شده نیز متن می‌تواند NULL باشد.

  • Handle یا Session قدیمی را بدون کنترل وضعیت فعلی استفاده نکنید.
  • خروجی NULL یا خالی را فوراً به‌عنوان خرابی SQL Server تعبیر نکنید؛ ابتدا Lifecycle داده و Permission را بررسی کنید.
  • در Queryهای CROSS APPLY روی کل Plan Cache یا همه Sessionها، ابتدا دامنه را با TOP، WHERE و معیارهای Performance محدود کنید.
  • برای مقایسه دو Snapshot، زمان جمع‌آوری و Context بار سیستم را ثبت کنید تا تغییرات طبیعی با Regression اشتباه نشود.
  • پاک‌سازی Plan Cache، Restart سرویس یا تغییر SET Option را فقط برای «دیدن نتیجه» انجام ندهید؛ این اقدامات می‌توانند اثر سراسری داشته باشند.

ملاحظات Performance و بهینه‌سازی

CROSS APPLY روی مجموعه بسیار بزرگ Query Stats ممکن است حجم متن زیادی تولید کند. ابتدا TOP، فیلتر زمانی یا معیار مصرف CPU/IO اعمال کنید.

برای ابزارهای مانیتورینگ سازمانی یک الگوی دو مرحله‌ای مناسب است: مرحله اول Query سبک برای پیدا کردن کاندیداها و مرحله دوم جمع‌آوری جزئیات فقط برای همان کاندیداها. این روش هم سربار را پایین می‌آورد و هم داده قابل استفاده‌تری تولید می‌کند.

اگر خروجی شامل XML یا متن بسیار بزرگ است، آن را در هر Poll ذخیره نکنید. می‌توان Hash، اندازه، Handle، زمان و چند متریک کلیدی را ثبت کرد و فقط در صورت عبور از آستانه یا وقوع Incident جزئیات کامل را گرفت. این رویکرد برای داشبوردهای داخلی و سامانه‌های Alerting بسیار مقیاس‌پذیرتر است.

Best Practices برای محیط Production

  1. مسئله را با یک معیار قابل اندازه‌گیری تعریف کنید؛ مانند CPU، Duration، Logical Reads، Blocking یا Plan Regression.
  2. ابتدا Session یا Query هدف را با یک DMV سبک شناسایی کنید.
  3. سپس sys.dm_exec_sql_text را فقط برای همان هدف اجرا کنید و خروجی را همراه Timestamp ذخیره کنید.
  4. متن SQL، Database Context، SET Options و پارامترهای مؤثر را تا حد امکان کنار شواهد نگه دارید.
  5. قبل از تغییر Index، Hint یا Configuration، فرضیه را در محیط Test با داده نزدیک به Production آزمایش کنید.
  6. اسکریپت عیب‌یابی را Version Control کنید تا تغییرات و نتایج قابل بازبینی باشند.

در پروژه‌های بزرگ بهتر است این Queryها به‌صورت Runbook استاندارد تهیه شوند. آموزش تیم عملیات و مستندسازی اینکه هر خروجی چه معنایی دارد، ارزش بیشتری از داشتن مجموعه‌ای از اسکریپت‌های پراکنده و بدون Context ایجاد می‌کند.

کاربرد واقعی در سناریوهای سازمانی

فرض کنید سامانه فروش در ساعات اوج با افزایش ناگهانی زمان پاسخ مواجه شده است. به‌جای Restart یا پاک‌سازی Cache، ابتدا Queryهای فعال و پرهزینه شناسایی می‌شوند، سپس از sys.dm_exec_sql_text برای بازیابی متن Batch یا Query از روی sql_handle یا plan_handle استفاده می‌شود. داده حاصل با Wait Type، Blocking، Query Store و شاخص‌های CPU و I/O تطبیق داده می‌شود.

در یک سناریوی دیگر ممکن است دو Application با Connection Setting متفاوت یک SQL مشابه را اجرا کنند و Planهای متفاوت بسازند. ابزارهای Execution-related به DBA کمک می‌کنند تفاوت Context، Plan و متن را مستند کند و به جای حدس، علت قابل اثبات ارائه دهد.

برای تیم‌های DevOps نیز می‌توان Snapshotهای محدود و زمان‌دار ساخت و هنگام Alert فقط داده‌های ضروری را ثبت کرد. این الگو برای Postmortem بسیار ارزشمند است؛ زیرا چند ساعت بعد از Incident ممکن است Plan از Cache خارج شده یا Session پایان یافته باشد.

سؤالات متداول

sys.dm_exec_sql_text دقیقاً چه کاری انجام می‌دهد؟

sys.dm_exec_sql_text برای بازیابی متن Batch یا Query از روی sql_handle یا plan_handle استفاده می‌شود. ارزش اصلی آن زمانی مشخص می‌شود که اطلاعات خام Plan Cache یا Session را با Context مناسب مانند متن SQL، آمار اجرا و وضعیت Request ترکیب کنید. در آموزش‌های حرفه‌ای SQL Server این تابع معمولاً بخشی از یک زنجیره عیب‌یابی است، نه یک Query مستقل.

از کجا ورودی یا Context مناسب برای sys.dm_exec_sql_text را پیدا کنیم؟

ورودی می‌تواند sql_handle یا plan_handle از نوع varbinary(64) باشد. این Handleها معمولاً از DMVهای اجرایی مانند sys.dm_exec_requests و sys.dm_exec_query_stats گرفته می‌شوند. در عمل بهتر است ورودی را از DMVهای همان لحظه یا Plan Cache به‌صورت پویا استخراج کنید تا Handleهای قدیمی، Session اشتباه یا داده‌های نامعتبر وارد تحلیل نشوند.

آیا استفاده از sys.dm_exec_sql_text برای پروژه‌های سازمانی ارزش دارد؟

بله، مخصوصاً در سامانه‌هایی که کندی Query، Blocking، مصرف CPU یا رفتار Plan Cache باید سریع ریشه‌یابی شود. تیم DBA می‌تواند خروجی را در Runbookها و ابزارهای مانیتورینگ داخلی قرار دهد و در پروژه‌های بهینه‌سازی SQL Server از آن برای مستندسازی شواهد فنی استفاده کند.

در چه شرایطی مشاوره تخصصی برای تحلیل خروجی sys.dm_exec_sql_text مفید است؟

وقتی خروجی با Queryهای پیچیده، Parallelism، Parameter Sensitivity، Plan Cache Bloat یا Incidentهای Production گره می‌خورد، تفسیر صرف یک ستون کافی نیست. مشاوره SQL Server کمک می‌کند داده این ابزار با Wait Stats، Query Store، Indexها و الگوی بار واقعی کنار هم قرار گیرد.

تفاوت sys.dm_exec_sql_text با نگاه کردن ساده به Activity Monitor چیست؟

Activity Monitor یک نمای عمومی و رابط گرافیکی ارائه می‌کند، اما sys.dm_exec_sql_text داده فنی دقیق‌تری برای Queryهای اسکریپتی و اتوماسیون فراهم می‌کند. برای تحلیل قابل تکرار، Queryهای DMV معمولاً شفاف‌تر، قابل ذخیره‌تر و مناسب‌تر برای مقایسه هستند.

چطور یک اسکریپت آماده مبتنی بر sys.dm_exec_sql_text را در محیط واقعی اجرا کنیم؟

ابتدا Permission لازم را بررسی کنید، سپس Query را در محیط آزمایشی یا با فیلتر محدود اجرا کنید و بعد Session، Database یا Planهای هدف را انتخاب کنید. در سرویس‌های حساس بهتر است اسکریپت مانیتورینگ با TOP، شرط زمان و ثبت حداقلی خروجی ساخته شود.

رایج‌ترین خطا هنگام کار با sys.dm_exec_sql_text چیست؟

برای Ad hoc Queryها مقدار dbid از sql_handle همیشه قابل تعیین نیست. در آبجکت‌های رمزگذاری‌شده نیز متن می‌تواند NULL باشد. خطای رایج دیگر این است که یک Snapshot را به‌عنوان حقیقت دائمی در نظر بگیریم؛ Plan Cache و وضعیت Session پویا هستند و ممکن است چند ثانیه بعد تغییر کنند.

آیا sys.dm_exec_sql_text می‌تواند روی Performance اثر بگذارد؟

CROSS APPLY روی مجموعه بسیار بزرگ Query Stats ممکن است حجم متن زیادی تولید کند. ابتدا TOP، فیلتر زمانی یا معیار مصرف CPU/IO اعمال کنید. اصل مهم این است که Diagnostic Query هم باید خودش بهینه باشد؛ خواندن بی‌قید حجم زیادی XML، متن یا ردیف‌های Profiling می‌تواند در زمان Incident فشار اضافی ایجاد کند.

Best Practice استفاده از sys.dm_exec_sql_text چیست؟

بهترین روش، شروع از یک سؤال مشخص است: کدام Session، Query یا Plan مشکل دارد؟ سپس کمترین داده لازم را جمع کنید، Timestamp و Context را ثبت کنید، خروجی را با معیارهای دیگر تطبیق دهید و از پاک‌سازی Cache یا تغییر تنظیمات بدون شواهد کافی خودداری کنید.

sys.dm_exec_sql_text با کدام نسخه‌های SQL Server سازگار است؟

جایگزین مدرن fn_get_sql است و در سناریوهای مانیتورینگ، تحلیل Queryهای پرمصرف و بررسی درخواست‌های فعال بسیار پرکاربرد است. همیشه مستندات نسخه دقیق SQL Server و سطح Permission را بررسی کنید، زیرا نام Permissionها و برخی جزئیات Profiling یا دسترسی DMVها بین نسخه‌ها و سرویس‌های ابری تفاوت دارد.

سؤالات مصاحبه SQL Server

در مصاحبه چگونه کاربرد sys.dm_exec_sql_text را توضیح می‌دهید؟

می‌گویم این ابزار برای بازیابی متن Batch یا Query از روی sql_handle یا plan_handle است و سپس توضیح می‌دهم چگونه آن را با DMVهای مرتبط ترکیب می‌کنم تا از یک شناسه خام به شواهد قابل اقدام برسم.

اگر خروجی sys.dm_exec_sql_text خالی یا NULL باشد چه می‌کنید؟

ابتدا اعتبار Handle یا Session، وجود Query در حال اجرا، وضعیت Plan Cache، Permission و محدودیت نسخه را بررسی می‌کنم؛ سپس از یک منبع جایگزین مانند Query Store، Actual Plan یا Extended Events استفاده می‌کنم.

چطور از سربار مانیتورینگ با sys.dm_exec_sql_text جلوگیری می‌کنید؟

با فیلتر دقیق، TOP، انتخاب بازه زمانی کوتاه، جلوگیری از Polling بی‌وقفه و جمع‌آوری فقط ستون‌های ضروری. در Production هر Diagnostic Query باید با همان دقت Queryهای کسب‌وکار طراحی شود.

چه داده‌هایی را همراه خروجی sys.dm_exec_sql_text ذخیره می‌کنید؟

زمان جمع‌آوری، نام Instance و Database، session_id یا plan_handle مرتبط، متن Query، معیارهای CPU و I/O، Wait Type و توضیح Incident را ذخیره می‌کنم تا تحلیل بعداً قابل بازسازی باشد.

چرا یک Plan یا Snapshot به‌تنهایی برای نتیجه‌گیری کافی نیست؟

زیرا رفتار SQL Server به پارامترها، حجم داده، Statistics، Concurrency، Memory Grant، Waitها و لحظه اجرای Query وابسته است. شواهد باید از چند منبع مستقل کنار هم قرار گیرند.

چک‌لیست نهایی

  • نسخه SQL Server و Permission لازم را مشخص کرده‌ام.
  • Session، Query یا Plan هدف را قبل از جمع‌آوری جزئیات محدود کرده‌ام.
  • خروجی را همراه زمان، Database Context و متن SQL ثبت کرده‌ام.
  • نتیجه را با حداقل یک منبع دیگر مانند Query Store، Wait Stats یا Actual Plan تطبیق داده‌ام.
  • هیچ اقدام پرریسک مانند Clear Cache را بدون دلیل و برنامه Rollback انجام نداده‌ام.
  • اسکریپت را طوری نوشته‌ام که در صورت نبود داده یا Permission، رفتار قابل پیش‌بینی داشته باشد.

جمع‌بندی

sys.dm_exec_sql_text یک ابزار تخصصی برای بازیابی متن Batch یا Query از روی sql_handle یا plan_handle است. ارزش واقعی آن در ترکیب با Context و متریک‌های دیگر نمایان می‌شود. با فیلتر هدفمند، ثبت Timestamp، رعایت Permission و تحلیل چندمنبعی می‌توان از آن برای Troubleshooting سریع و مستند در محیط‌های جدی SQL Server استفاده کرد.

برای دیدن ارتباط این ابزار با سایر توابع، مقاله مادر توابع Execution Plan در SQL Server را مطالعه کنید.

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

حرف 500 حداکثر

اطلاعات تماس

  • آدرس:اصفهان-خیابان ام کلثوم غربی - بعد خیابان تخم چی - بیست متر بعد از پیتزا ننه شب - کوچه تعمیر گاه سمار زغالی - پلاک 354 - درب مشکی - طبقه هفتم
  • آدرس ایمیل:najafzade@gmail.com
  • وب سایت:http://www.a00b.com/
  • تلفن ثابت:(+98)9131253620
  • تلفن همراه:09131253620