एक चयन क्वेरी क्यों लिखता है?


34

मैंने देखा है कि SQL Server 2016 SP1 CU6 पर चलने वाले सर्वर पर कभी-कभी एक विस्तारित ईवेंट सत्र लिखने के कारण एक SELECT क्वेरी दिखाता है। उदाहरण के लिए:

यहाँ छवि विवरण दर्ज करें

निष्पादन योजना लिखने के लिए कोई स्पष्ट कारण नहीं दिखाती है, जैसे कि हैश टेबल, स्पूल या सॉर्ट जो कि TempDB तक फैल सकता है:

यहाँ छवि विवरण दर्ज करें

MAX प्रकार या स्वचालित आँकड़े अद्यतन के लिए परिवर्तनीय असाइनमेंट भी इसका कारण हो सकता है, लेकिन न तो इस मामले में लिखने का कारण था।

और क्या लिख ​​सकता है?

जवाबों:


8

अनाड़ी

मैं याद नहीं कर सकता अगर मैं इन में शामिल थे अपने मूल उत्तर में शामिल किया है , तो यहाँ एक और जोड़ी है।

Spools!

SQL सर्वर में बहुत सारे स्पूल होते हैं, जो अस्थायी डेटा संरचनाएं हैं जिन्हें अस्थायी रूप से संग्रहीत किया जाता है। दो उदाहरण टेबल और इंडेक्स स्पूल हैं।

जब वे एक क्वेरी प्लान में होते हैं, तो उन स्पूल को राइट को क्वेरी के साथ जोड़ा जाएगा।

पागल

ये DMVs, प्रोफाइलर, XE इत्यादि में लिखने के रूप में भी पंजीकृत होंगे।

सूचकांक स्पूल

पागल

टेबल स्पूल

पागल

प्रदर्शन की मात्रा स्पष्ट रूप से स्पूल किए गए डेटा के आकार के साथ ऊपर जाएगी।

Spills

जब SQL सर्वर को कुछ ऑपरेटरों के लिए पर्याप्त मेमोरी नहीं मिलती है, तो यह कुछ पेजों को डिस्क में फैला सकता है। यह मुख्य रूप से सॉर्ट और हैश के साथ होता है। आप इसे वास्तविक निष्पादन योजनाओं में देख सकते हैं, और SQL सर्वर के नए संस्करणों में, spills को dm_exec_query_stats में भी ट्रैक किया जाता है

SELECT deqs.sql_handle,
       deqs.total_spills,
       deqs.last_spills,
       deqs.min_spills,
       deqs.max_spills
FROM sys.dm_exec_query_stats AS deqs
WHERE deqs.min_spills > 0;

पागल

पागल

नज़र रखना

आप एक समान XE सत्र का उपयोग कर सकते हैं, जैसा कि मैंने ऊपर अपने स्वयं के डेमो में देखने के लिए उपयोग किया था।

CREATE EVENT SESSION spools_and_spills
    ON SERVER
    ADD EVENT sqlserver.sql_batch_completed
    ( ACTION ( sqlserver.sql_text ))
    ADD TARGET package0.event_file
    ( SET filename = N'c:\temp\spools_and_spills' )
    WITH ( MAX_MEMORY = 4096KB,
           EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
           MAX_DISPATCH_LATENCY = 1 SECONDS,
           MAX_EVENT_SIZE = 0KB,
           MEMORY_PARTITION_MODE = NONE,
           TRACK_CAUSALITY = OFF,
           STARTUP_STATE = OFF );
GO

38

कुछ मामलों में क्वेरी स्टोर चुनिंदा कथन के प्रभाव के रूप में और उसी सत्र में लिखने का कारण बन सकता है।

इसे निम्नानुसार पुन: प्रस्तुत किया जा सकता है:

USE master;
GO
CREATE DATABASE [Foo];
ALTER DATABASE [Foo] SET QUERY_STORE (OPERATION_MODE = READ_WRITE, 
  CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30), 
  DATA_FLUSH_INTERVAL_SECONDS = 900, 
  INTERVAL_LENGTH_MINUTES = 60, 
  MAX_STORAGE_SIZE_MB = 100, 
  QUERY_CAPTURE_MODE = ALL, 
  SIZE_BASED_CLEANUP_MODE = AUTO);
USE Foo;
CREATE TABLE Test (a int, b nvarchar(max));
INSERT INTO Test SELECT 1, 'string';

निगरानी के लिए एक विस्तारित ईवेंट सत्र बनाएँ:

CREATE EVENT SESSION [Foo] ON SERVER 
ADD EVENT sqlserver.rpc_completed(SET collect_data_stream=(1)
    ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_name,sqlserver.is_system,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_server_principal_name,sqlserver.sql_text)
    WHERE ([writes]>(0))),
ADD EVENT sqlserver.sql_batch_completed(SET collect_batch_text=(1)
    ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.client_pid,sqlserver.database_name,sqlserver.is_system,sqlserver.server_principal_name,sqlserver.session_id,sqlserver.session_server_principal_name,sqlserver.sql_text)
    WHERE ([writes]>(0)))
ADD TARGET package0.event_file(SET filename=N'C:\temp\FooActivity2016.xel',max_file_size=(11),max_rollover_files=(999999))
WITH (MAX_MEMORY=32768 KB,EVENT_RETENTION_MODE=ALLOW_MULTIPLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF);

अगला निम्नलिखित चलाएँ:

WHILE @@TRANCOUNT > 0 COMMIT
SET IMPLICIT_TRANSACTIONS ON;
SET NOCOUNT ON;
GO
DECLARE @b nvarchar(max);
SELECT @b = b FROM dbo.Test WHERE a = 1;
WAITFOR DELAY '00:00:01.000';
GO 86400

एक प्रत्यारोपित लेनदेन इसे पुन: पेश करने के लिए आवश्यक हो सकता है या नहीं भी हो सकता है।

डिफ़ॉल्ट रूप से, अगले घंटे के शीर्ष पर क्वेरी स्टोर की सांख्यिकी संग्रह नौकरी डेटा लिख ​​देगी। यह (कभी-कभी) घंटे के दौरान निष्पादित पहली उपयोगकर्ता क्वेरी के भाग के रूप में प्रकट होता है। विस्तारित ईवेंट सत्र निम्न के जैसा कुछ दिखाएगा:

यहाँ छवि विवरण दर्ज करें

लेन-देन लॉग में हुए लेखन को दिखाता है:

USE Foo;
SELECT [Transaction ID], [Begin Time], SPID, Operation, 
  [Description], [Page ID], [Slot ID], [Parent Transaction ID] 
FROM sys.fn_dblog(null,null) 
/* Adjust based on contents of your transaction log */
WHERE [Transaction ID] IN ('0000:0000042c', '0000:0000042d', '0000:0000042e')
OR [Parent Transaction ID] IN ('0000:0000042c', '0000:0000042d', '0000:0000042e')
ORDER BY [Current LSN];

यहाँ छवि विवरण दर्ज करें

पृष्ठ के निरीक्षण से DBCC PAGEपता चलता है कि लिखना है sys.plan_persist_runtime_stats_interval

USE Foo;
DBCC TRACEON(3604); 
DBCC PAGE(5,1,344,1); SELECT
OBJECT_NAME(229575856);

ध्यान दें कि लॉग प्रविष्टियाँ तीन नेस्टेड लेनदेन दिखाती हैं लेकिन केवल दो प्रतिबद्ध रिकॉर्ड हैं। उत्पादन में इसी तरह की स्थिति में, यह एक निश्चित रूप से दोषपूर्ण क्लाइंट लाइब्रेरी का कारण बना, जिसने अप्रत्याशित लेनदेन का उपयोग अप्रत्याशित रूप से एक लेखन लेनदेन शुरू करने के लिए किया, जिससे लेन-देन लॉग को समाशोधन से रोक दिया गया। लाइब्रेरी को केवल अपडेट, इंसर्ट या डिलीट स्टेटमेंट चलाने के बाद कमिट जारी करने के लिए लिखा गया था, इसलिए इसने कभी भी एक कमिट जारी नहीं किया और एक लिखित लेनदेन खुला रह गया।


25

ऐसा होने पर एक और समय हो सकता है और यह एक स्वचालित आँकड़े अद्यतन के साथ है।

यहाँ XE सत्र हम देख रहे हैं:

CREATE EVENT SESSION batches_and_stats
    ON SERVER
    ADD EVENT sqlserver.auto_stats
    ( ACTION ( sqlserver.sql_text )),
    ADD EVENT sqlserver.sql_batch_completed
    ( ACTION ( sqlserver.sql_text ))
    ADD TARGET package0.event_file
    ( SET filename = N'c:\temp\batches_and_stats' )
    WITH ( MAX_MEMORY = 4096KB,
           EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
           MAX_DISPATCH_LATENCY = 30 SECONDS,
           MAX_EVENT_SIZE = 0KB,
           MEMORY_PARTITION_MODE = NONE,
           TRACK_CAUSALITY = OFF,
           STARTUP_STATE = OFF );
GO

फिर हम इसका उपयोग जानकारी एकत्र करने के लिए करेंगे:

USE tempdb

DROP TABLE IF EXISTS dbo.SkewedUp

CREATE TABLE dbo.SkewedUp (Id INT NOT NULL, INDEX cx_su CLUSTERED (Id))

INSERT dbo.SkewedUp WITH ( TABLOCK ) ( Id )
SELECT CASE WHEN x.r % 15 = 0 THEN 1
            WHEN x.r % 5 = 0 THEN 1000
            WHEN x.r % 3 = 0 THEN 10000
            ELSE 100000
       END AS Id
FROM   (   SELECT     TOP 1000000 ROW_NUMBER() OVER ( ORDER BY @@DBTS ) AS r
           FROM       sys.messages AS m
           CROSS JOIN sys.messages AS m2 ) AS x;


ALTER EVENT SESSION [batches_and_stats] ON SERVER STATE = START

SELECT su.Id, COUNT(*) AS records
FROM dbo.SkewedUp AS su
WHERE su.Id > 0
GROUP BY su.Id

ALTER EVENT SESSION [batches_and_stats] ON SERVER STATE = STOP

एक्सई सत्र से कुछ दिलचस्प परिणाम:

पागल

ऑटो आँकड़े अद्यतन किसी भी लिखने को प्रदर्शित नहीं करता है, लेकिन आँकड़े अद्यतन के तुरंत बाद क्वेरी एक लिखना दिखाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.