Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQL सर्वर 2016:sys.dm_exec_function_stats

SQL सर्वर 2016 CTP 2.1 में, एक नया ऑब्जेक्ट है जो CTP 2.0 के बाद दिखाई दिया:sys.dm_exec_function_stats। इसका उद्देश्य sys.dm_exec_procedure_stats, sys.dm_exec_query_stats, और sys.dm_exec_trigger_stats को समान कार्यक्षमता प्रदान करना है। इसलिए अब उपयोगकर्ता-परिभाषित कार्यों के लिए समग्र रनटाइम मेट्रिक्स को ट्रैक करना संभव है।

या है?

सीटीपी 2.1 में कम से कम, मैं केवल नियमित स्केलर कार्यों के लिए यहां कोई सार्थक मीट्रिक प्राप्त कर सकता था - इनलाइन या मल्टी-स्टेटमेंट टीवीएफ के लिए कुछ भी पंजीकृत नहीं था। मैं इनलाइन कार्यों के बारे में आश्चर्यचकित नहीं हूं, क्योंकि वे वैसे भी निष्पादन से पहले अनिवार्य रूप से विस्तारित होते हैं। लेकिन चूंकि मल्टी-स्टेटमेंट टीवीएफ अक्सर प्रदर्शन की समस्याएं होती हैं, मैं उम्मीद कर रहा था कि वे भी दिखाई देंगे। वे अभी भी sys.dm_exec_query_stats में दिखाई देते हैं, इसलिए आप अभी भी वहां से उनके प्रदर्शन मीट्रिक प्राप्त कर सकते हैं, लेकिन जब आपके पास वास्तव में कई कथन हैं जो काम के कुछ हिस्से को निष्पादित करते हैं तो एकत्रीकरण करना मुश्किल हो सकता है - आपके लिए कुछ भी रोल अप नहीं किया गया है।

आइए एक त्वरित नज़र डालें कि यह कैसे खेलता है। मान लें कि हमारे पास 100,000 पंक्तियों वाली एक साधारण तालिका है:

SELECT TOP (100000) o1.[object_id], o1.create_date
  INTO dbo.src
  FROM sys.all_objects AS o1
  CROSS JOIN sys.all_objects AS o2
  ORDER BY o1.[object_id];
GO
CREATE CLUSTERED INDEX x ON dbo.src([object_id]);
GO
-- prime the cache
SELECT [object_id], create_date FROM dbo.src;

मैं तुलना करना चाहता था कि क्या होता है जब हम स्केलर यूडीएफ, बहु-कथन तालिका-मूल्यवान कार्यों, और इनलाइन तालिका-मूल्यवान कार्यों की जांच करते हैं, और हम कैसे देखते हैं कि प्रत्येक मामले में क्या काम किया गया था। सबसे पहले, कुछ तुच्छ कल्पना करें जो हम SELECT . में कर सकते हैं खंड, लेकिन हो सकता है कि हम किसी तारीख को एक स्ट्रिंग के रूप में स्वरूपित करना चाहते हों:

CREATE PROCEDURE dbo.p_dt_Standard
  @dt_ CHAR(10) = NULL
AS
BEGIN
  SET NOCOUNT ON;
  SELECT @dt_ = CONVERT(CHAR(10), create_date, 120)
    FROM dbo.src
    ORDER BY [object_id];
END
GO

(मैं आउटपुट को एक वेरिएबल को असाइन करता हूं, जो पूरी तालिका को स्कैन करने के लिए बाध्य करता है, लेकिन प्रदर्शन मेट्रिक्स को SSMS के आउटपुट को उपभोग और प्रस्तुत करने के प्रयासों से प्रभावित होने से रोकता है। रिमाइंडर के लिए धन्यवाद, मिकेल एरिक्सन।)

कई बार आप देखेंगे कि लोग उस रूपांतरण को एक फ़ंक्शन में डालते हैं, और यह स्केलर या टीवीएफ हो सकता है, जैसे:

CREATE FUNCTION dbo.dt_Inline(@dt_ DATETIME)
RETURNS TABLE
AS
  RETURN (SELECT dt_ = CONVERT(CHAR(10), @dt_, 120));
GO
 
CREATE FUNCTION dbo.dt_Multi(@dt_ DATETIME)
RETURNS @t TABLE(dt_ CHAR(10))
AS
BEGIN
  INSERT @t(dt_) SELECT CONVERT(CHAR(10), @dt_, 120);
  RETURN;
END
GO
 
CREATE FUNCTION dbo.dt_Scalar(@dt_ DATETIME)
RETURNS CHAR(10)
AS
BEGIN
  RETURN (SELECT CONVERT(CHAR(10), @dt_, 120));
END
GO

मैंने इन कार्यों के चारों ओर प्रक्रिया रैपर निम्नानुसार बनाए हैं:

CREATE PROCEDURE dbo.p_dt_Inline
  @dt_ CHAR(10) = NULL
AS
BEGIN
  SET NOCOUNT ON;
  SELECT @dt_ = dt.dt_
    FROM dbo.src AS o
    CROSS APPLY dbo.dt_Inline(o.create_date) AS dt
    ORDER BY o.[object_id];
END
GO
 
CREATE PROCEDURE dbo.p_dt_Multi
  @dt_ CHAR(10) = NULL
AS
BEGIN
  SET NOCOUNT ON;
  SELECT @dt_ = dt.dt_
    FROM dbo.src
    CROSS APPLY dbo.dt_Multi(create_date) AS dt
    ORDER BY [object_id];
END
GO
 
CREATE PROCEDURE dbo.p_dt_Scalar
  @dt_ CHAR(10) = NULL
AS
BEGIN
  SET NOCOUNT ON;
  SELECT @dt_ = dt = dbo.dt_Scalar(create_date)
    FROM dbo.src
    ORDER BY [object_id];
END
GO

(और नहीं, dt_ सम्मेलन जो आप देख रहे हैं वह कुछ नई बात नहीं है, मुझे लगता है कि यह एक अच्छा विचार है, यह सबसे आसान तरीका था जिससे मैं इन सभी प्रश्नों को डीएमवी में एकत्र की जा रही हर चीज से अलग कर सकता था। इसने प्रत्ययों को जोड़ना भी आसान बना दिया ताकि संग्रहीत कार्यविधि और तदर्थ संस्करण के अंदर की क्वेरी के बीच आसानी से अंतर किया जा सके।)

इसके बाद, मैंने समय को स्टोर करने के लिए एक #temp तालिका बनाई, और इस प्रक्रिया को दोहराया (दोनों संग्रहीत प्रक्रिया को दो बार निष्पादित करना, और प्रक्रिया के मुख्य भाग को एक अलग तदर्थ क्वेरी के रूप में दो बार निष्पादित करना, और प्रत्येक के समय को ट्रैक करना):

CREATE TABLE #t
(
  ID INT IDENTITY(1,1), 
  q VARCHAR(32), 
  s DATETIME2, 
  e DATETIME2
);
GO
 
INSERT #t(q,s) VALUES('p Standard',SYSDATETIME());
GO
 
EXEC dbo.p_dt_Standard;
GO 2
 
UPDATE #t SET e = SYSDATETIME() WHERE ID = 1;
GO
 
INSERT #t(q,s) VALUES('ad hoc Standard',SYSDATETIME());
GO
 
DECLARE @dt_st CHAR(10);
  SELECT @dt_st = CONVERT(CHAR(10), create_date, 120)
    FROM dbo.src
    ORDER BY [object_id];
GO 2
 
UPDATE #t SET e = SYSDATETIME() WHERE ID = 2;
GO
-- repeat for inline, multi and scalar versions

फिर मैंने कुछ नैदानिक ​​प्रश्न पूछे, और ये रहे परिणाम:

sys.dm_exec_function_stats

SELECT name = OBJECT_NAME(object_id), 
  execution_count,
  time_milliseconds = total_elapsed_time/1000
FROM sys.dm_exec_function_stats
WHERE database_id = DB_ID()
ORDER BY name;

परिणाम:

name        execution_count    time_milliseconds
---------   ---------------    -----------------
dt_Scalar   400000             1116

यह एक टाइपो नहीं है; केवल अदिश UDF नए DMV में कोई उपस्थिति दिखाता है।

sys.dm_exec_procedure_stats

SELECT name = OBJECT_NAME(object_id), 
  execution_count,
  time_milliseconds = total_elapsed_time/1000
FROM sys.dm_exec_procedure_stats
WHERE database_id = DB_ID()
ORDER BY name;

परिणाम:

name            execution_count    time_milliseconds
-------------   ---------------    -----------------
p_dt_Inline     2                  74
p_dt_Multi      2                  269
p_dt_Scalar     2                  1063
p_dt_Standard   2                  75

यह आश्चर्यजनक परिणाम नहीं है:स्केलर फ़ंक्शन का उपयोग करने से ऑर्डर-ऑफ-परिमाण प्रदर्शन जुर्माना होता है, जबकि मल्टी-स्टेटमेंट टीवीएफ केवल 4x खराब था। कई परीक्षणों में, इनलाइन फ़ंक्शन हमेशा तेज़ या मिलीसेकंड या बिना किसी फ़ंक्शन की तुलना में दो तेज़ था।

sys.dm_exec_query_stats

SELECT 
  query = SUBSTRING([text],s,e), 
  execution_count, 
  time_milliseconds
FROM
(
  SELECT t.[text],
    s = s.statement_start_offset/2 + 1,
    e = COALESCE(NULLIF(s.statement_end_offset,-1),8000)/2,
    s.execution_count,
    time_milliseconds = s.total_elapsed_time/1000
  FROM sys.dm_exec_query_stats AS s
  OUTER APPLY sys.dm_exec_sql_text(s.[sql_handle]) AS t
  WHERE t.[text] LIKE N'%dt[_]%' 
) AS x;

काटे गए परिणाम, मैन्युअल रूप से पुन:क्रमित:

query (truncated)                                                       execution_count    time_milliseconds
--------------------------------------------------------------------    ---------------    -----------------
-- p Standard:
SELECT @dt_ = CONVERT(CHAR(10), create_date, 120) ...                   2                  75
-- ad hoc Standard:
SELECT @dt_st = CONVERT(CHAR(10), create_date, 120) ...                 2                  72
 
-- p Inline:
SELECT @dt_ = dt.dt_ FROM dbo.src AS o CROSS APPLY dbo.dt_Inline...     2                  74
-- ad hoc Inline:
SELECT @dt_in = dt.dt_ FROM dbo.src AS o CROSS APPLY dbo.dt_Inline...   2                  72
 
-- all Multi:
INSERT @t(dt_) SELECT CONVERT(CHAR(10), @dt_, 120);                     184                5
-- p Multi:
SELECT @dt_ = dt.dt_ FROM dbo.src CROSS APPLY dbo.dt_Multi...           2                  270
-- ad hoc Multi:
SELECT @dt_m = dt.dt_ FROM dbo.src AS o CROSS APPLY dbo.dt_Multi...     2                  257
 
-- all scalar:
RETURN (SELECT CONVERT(CHAR(10), @dt_, 120));                           400000             581
-- p Scalar:
SELECT @dt_ = dbo.dt_Scalar(create_date)...                             2                  986
-- ad hoc Scalar:
SELECT @dt_sc = dbo.dt_Scalar(create_date)...                           2                  902
चुनें

यहां ध्यान देने वाली एक महत्वपूर्ण बात यह है कि मल्टी-स्टेटमेंट टीवीएफ में INSERT के लिए मिलीसेकंड में समय और स्केलर फ़ंक्शन में रिटर्न स्टेटमेंट का भी अलग-अलग चयनों के भीतर हिसाब लगाया जाता है, इसलिए इसका कोई मतलब नहीं है कि सभी को जोड़ दें समय।

मैन्युअल समय

और फिर अंत में, #temp तालिका से समय:

SELECT query = q, 
    time_milliseconds = DATEDIFF(millisecond, s, e) 
  FROM #t 
  ORDER BY ID;

परिणाम:

query             time_milliseconds
---------------   -----------------
p Standard        107
ad hoc Standard   78
p Inline          80
ad hoc Inline     78
p Multi           351
ad hoc Multi      263
p Scalar          992
ad hoc Scalar     907

यहां अतिरिक्त दिलचस्प परिणाम:प्रक्रिया रैपर में हमेशा कुछ ओवरहेड होता था, हालांकि यह कितना महत्वपूर्ण है वास्तव में व्यक्तिपरक हो सकता है।

सारांश

आज मेरा मुद्दा केवल नए डीएमवी को कार्रवाई में दिखाने के लिए था, और उम्मीदों को सही ढंग से सेट करना था - कार्यों के लिए कुछ प्रदर्शन मीट्रिक अभी भी भ्रामक होंगे, और कुछ अभी भी उपलब्ध नहीं होंगे (या कम से कम अपने लिए एक साथ टुकड़े करने के लिए बहुत कठिन हो सकते हैं )

मुझे लगता है कि यह नया डीएमवी क्वेरी मॉनिटरिंग के सबसे बड़े टुकड़ों में से एक को कवर करता है जो SQL सर्वर पहले गायब था, हालांकि:स्केलर फ़ंक्शन कभी-कभी अदृश्य प्रदर्शन हत्यारे होते हैं, क्योंकि उनके उपयोग की पहचान करने का एकमात्र विश्वसनीय तरीका क्वेरी टेक्स्ट को पार्स करना था, जो मूर्खता से दूर है। इस तथ्य पर ध्यान न दें कि यह आपको प्रदर्शन पर उनके प्रभाव को अलग करने की अनुमति नहीं देगा, या आपको पहले स्थान पर क्वेरी टेक्स्ट में स्केलर यूडीएफ की तलाश करने के लिए जाना होगा।

परिशिष्ट

मैंने स्क्रिप्ट संलग्न की है:DMExecFunctionStats.zip

साथ ही, CTP1 के अनुसार, यहां स्तंभों का सेट दिया गया है:

database_id object_id type type_desc
sql_handle plan_handle cached_time last_execution_time execution_count
total_worker_time last_worker_time min_worker_time max_worker_time
total_physical_reads last_physical_reads min_physical_reads max_physical_reads
total_logical_writes last_logical_writes min_logical_writes max_logical_writes
total_logical_reads last_logical_reads min_logical_reads max_logical_reads
total_elapsed_time last_elapsed_time min_elapsed_time max_elapsed_time

वर्तमान में sys.dm_exec_function_stats में कॉलम


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एकाधिक तालिकाओं में शामिल होने से NULL मान लौटाता है

  2. SQLCommand को पैरामीटर पास करने का सबसे अच्छा तरीका क्या है?

  3. कैसे ठीक करें "प्रक्रिया को 'ntext/nchar/nvarchar' प्रकार के पैरामीटर '@statement' की अपेक्षा है।" SQL सर्वर में त्रुटि

  4. SQL सर्वर पर LIKE बनाम CONTAINS

  5. SQL सर्वर में परिणाम सेट का प्रतिशत लौटाएं