वास्तव में sysinos_exec_session में "रीड" कॉलम क्या दर्शाता है?


10

यह एक बहुत ही मूल प्रश्न की तरह लग सकता है, और वास्तव में यह होना चाहिए। हालांकि, वैज्ञानिक पद्धति के प्रशंसक के रूप में, मुझे एक परिकल्पना बनाना पसंद है, फिर यह देखने के लिए कि क्या मैं सही हूं, इसका परीक्षण करूंगा। इस मामले में, मैं बेहतर आउटपुट को समझने की कोशिश कर रहा हूं sys.dm_exec_sessions, और विशेष रूप से, एकल कॉलम "रीड"।

SQL सर्वर पुस्तकें ऑनलाइन बल्कि शुष्क रूप से निर्दिष्ट करता है:

इस सत्र के दौरान, इस सत्र में अनुरोधों की संख्या, प्रदर्शन किए गए। अशक्त नहीं है।

कोई यह मान सकता है कि सत्र शुरू होने के बाद से इस सत्र द्वारा जारी किए गए अनुरोधों को पूरा करने के लिए डिस्क से पढ़े गए पृष्ठों की संख्या का संकेत होगा । यह वह परिकल्पना है जिसे मैंने सोचा था कि मैं परीक्षण करूँगा।

logical_readsकि एक ही तालिका में स्तंभ के रूप में परिभाषित किया गया है:

सत्र पर किए गए तार्किक रीड की संख्या। अशक्त नहीं है।

SQL सर्वर का उपयोग करने के अनुभव से, मेरा मानना ​​है कि यह कॉलम उन पृष्ठों की संख्या को दर्शाता है जिन्हें डिस्क और मेमोरी दोनों से पढ़ा गया है । दूसरे शब्दों में, सत्र द्वारा कभी पढ़े गए पृष्ठों की कुल संख्या , चाहे वे पृष्ठ कहाँ भी रहें। एक ही जानकारी देने वाले दो अलग-अलग कॉलम होने के विभेदक, या मूल्य-प्रस्ताव, ऐसा प्रतीत होता है कि कोई डिस्क से पढ़े गए पृष्ठों के अनुपात को समझ सकता है ( reads) बनाम logical_readsएक विशिष्ट सत्र के लिए बफर कैश ( ) से पढ़े गए ।

अपने परीक्षण रिग पर, मैंने एक नया डेटाबेस बनाया है, एक एकल तालिका बनाई है जिसमें कई ज्ञात डेटा पृष्ठ हैं, फिर उस तालिका को एक नए सत्र में पढ़ें। फिर मैंने देखाsys.dm_exec_sessions देखने के लिए क्या readsऔर logical_readsकॉलम सत्र के बारे में कहा। इस बिंदु पर मैं परिणामों से भ्रमित हूं। शायद यहाँ कोई मेरे लिए इस पर कुछ प्रकाश डाल सकता है।

परीक्षण रिग:

USE master;
IF EXISTS (SELECT 1
    FROM sys.databases d 
    WHERE d.name = 'TestReads')
BEGIN
    ALTER DATABASE TestReads SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE TestReads;
END
GO
CREATE DATABASE TestReads;
GO
ALTER DATABASE TestReads SET RECOVERY SIMPLE;
BACKUP DATABASE TestReads TO DISK = 'NUL:'; /* ensure we are in 
                                            simple recovery model */
GO

USE TestReads;
GO

/*
    create a table with 2 rows per page, for easy math!
*/
CREATE TABLE dbo.TestReads
(
    ID INT NOT NULL
        CONSTRAINT PK_TestReads
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , SomeData CHAR(4000) NOT NULL
);

/*
    insert 5000 pages of data
*/
INSERT INTO dbo.TestReads (SomeData)
SELECT TOP(10000) o1.name
FROM sys.objects o1
    , sys.objects o2
    , sys.objects o3
ORDER BY o1.object_id
    , o2.object_id
    , o3.object_id;


/*
    Verify we have 5,000 pages of data, with 10,000 rows.
*/
SELECT o.name
    , p.rows
    , au.total_pages
    , au.used_pages
    , au.data_pages
FROM sys.partitions p
    INNER JOIN sys.objects o ON p.object_id = o.object_id 
    INNER JOIN sys.allocation_units au 
        ON p.hobt_id = au.container_id 
        AND (au.type = 1 or au.type = 0)
WHERE p.index_id = 1
    AND o.name = 'TestReads'
    AND o.type = 'U';

/*
    issue a checkpoint to ensure dirty pages are flushed to disk
*/
CHECKPOINT 30;
DBCC DROPCLEANBUFFERS;
DBCC FREESYSTEMCACHE ('ALL');
DBCC FREEPROCCACHE;
DBCC FREESESSIONCACHE;
GO

/*
    ensure we have no data cached in memory for the TestReads database
*/
USE master;
ALTER DATABASE TestReads SET OFFLINE WITH ROLLBACK IMMEDIATE;
ALTER DATABASE TestReads SET ONLINE;

SELECT DatabaseName = d.name
    , SchemaName = s.name
    , ObjectName = o.name
    , AllocatedMB = COUNT(1) * 8192E0 / 1048576
    , PagesInMemory = COUNT(1)
FROM sys.dm_os_buffer_descriptors dobd
    INNER JOIN sys.allocation_units au 
        ON dobd.allocation_unit_id = au.allocation_unit_id
    INNER JOIN sys.partitions p 
        ON au.container_id = p.hobt_id 
             AND (au.type = 1 OR au.type = 0)
    INNER JOIN sys.objects o ON p.object_id = o.object_id
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
    INNER JOIN sys.databases d 
        ON dobd.database_id = d.database_id
WHERE d.name = 'TestReads'
    AND o.name = 'TestReads'
    AND o.type = 'U'
GROUP BY d.name
    , s.name
    , o.name;

उपरोक्त पहला चुनिंदा कथन दर्शाता है कि वास्तव में तालिका में ५,०२५ कुल पृष्ठ, ५,०२० उपयोग किए गए पृष्ठ और ५,००० डेटा पृष्ठों के साथ १०,००० पंक्तियाँ शामिल हैं; ठीक वैसे ही जैसे कोई उम्मीद करेगा:

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

दूसरा चयन कथन पुष्टि करता है कि हमारे पास TestReadsतालिका के लिए स्मृति में कुछ भी नहीं है ।

एक नए सत्र में , हम निम्नलिखित प्रश्न को करते हैं, जो कि session_id पर ध्यान देता है:

USE TestReads;

SET STATISTICS IO ON;

SELECT *
FROM dbo.TestReads;

जैसा कि एक की उम्मीद होगी, यह डिस्क से मेमोरी में पूरी तालिका को पढ़ता है, जैसा कि आउटपुट में दिखाया गया है SET STATISTICS IO ON:

(10000 row(s) affected)
Table 'TestReads'. Scan count 1, logical reads 5020, physical reads 3, 
read-ahead reads 4998, lob logical reads 0, lob physical reads 0, lob 
read-ahead reads 0.

एक तीसरे सत्र में, हम निरीक्षण करते हैं sys.dm_exec_sessions:

SELECT des.session_id
    , des.reads
    , des.logical_reads
FROM sys.dm_exec_sessions des
WHERE des.session_id = 57; /* session_id from the 2nd (previous) session */

मैं देखना चाहता उम्मीद थी sys.dm_exec_sessionsशो में कम से कम दोनों के लिए 5000 readsऔर logical_reads। काश, मैं readsशो शून्य देखता । logical_reads5,000 के उत्तर में कहीं पढ़ने की अपेक्षित संख्या दिखाता है - यह मेरे परीक्षण में 5,020 दिखाता है:

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

मुझे पता है कि SQL Server TestReadsने sys_dm_os_buffer_descriptorsDMV के गुण द्वारा पूरी तालिका को मेमोरी में पढ़ा है :

USE TestReads;
GO
SELECT DatabaseName = d.name
    , SchemaName = s.name
    , ObjectName = o.name
    , AllocatedMB = COUNT(1) * 8192E0 / 1048576
    , PagesInMemory = COUNT(1)
FROM sys.dm_os_buffer_descriptors dobd
    INNER JOIN sys.allocation_units au 
        ON dobd.allocation_unit_id = au.allocation_unit_id
    INNER JOIN sys.partitions p 
        ON au.container_id = p.hobt_id 
            AND (au.type = 1 OR au.type = 0)
    INNER JOIN sys.objects o ON p.object_id = o.object_id
    INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
    INNER JOIN sys.databases d 
        ON dobd.database_id = d.database_id
WHERE d.name = 'TestReads'
    AND o.name = 'TestReads'
    AND o.type = 'U'
GROUP BY d.name
    , s.name
    , o.name;

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

मैं क्या गलत कर रहा हूं?

मैं इस परीक्षण के लिए SQL Server 2012 11.0.5343 का उपयोग कर रहा हूं।


आगे के निष्कर्ष:

यदि मैं निम्नलिखित चलाता हूं:

SELECT des.session_id
    , des.reads
    , des.logical_reads
FROM sys.dm_exec_sessions des

मैं readsसत्र में 784 देखता हूं , जहां मैं टेस्ट रिग बना रहा हूं; हालाँकि अन्य सभी सत्र readsकॉलम में शून्य दिखाते हैं ।

मैंने अब अपने SQL सर्वर परीक्षण उदाहरण को 11.0.6020 में अपडेट किया है; हालाँकि परिणाम वही है।


sys.dm_exec_requestsआप set statistics io onपरिणाम के रूप में लगभग एक ही दे देंगे ।
परिजनों शाह

1
दिलचस्प SET STATISTICS IO ONइससे पहले कि मैं 2 सत्रों की रिपोर्ट में तालिका से पढ़ता हूं 3 भौतिक रीड्स, और 4998 रीड-फॉरवर्ड रीड्स; हालांकि sys.dm_exec_sessionsअभी भी readsकॉलम में यह प्रतिबिंबित नहीं हुआ है ।
मैक्स वर्नोन

2
2012 में मैं अक्सर पढ़ता हूँ और दोनों के लिए पढ़ता है और गैर-शून्य परिणामों के बावजूद STATISTICS IO i.stack.imgur.com/XbHae.png
मार्टिन स्मिथ

1
वास्तव में मुझे दोनों कॉलम शून्य नजर आते हैं जो मैंने 2008 से SQL2016CTP3 तक परीक्षण किए हैं
मार्टिन स्मिथ

1
@ मर्टिनस्मिथ और मैक्स: मैं कुछ readsक्षेत्रों की वेतन वृद्धि में देरी भी देख रहा हूं । मुझे संदेह है कि यह सत्र_स्पेस_युज या जो भी DMV है जो प्रति सत्र tempdb उपयोग दिखाता है जो "अनुरोध" खत्म होने तक वेतन वृद्धि नहीं करता है।
सोलोमन रटज़की ने

जवाबों:


2

मेरी समझ हमेशा यह रही है कि readsकेवल भौतिक (यानी डिस्क से) और logical_readsकेवल बफ़र पूल (यानी मेमोरी से) से है। मैंने एक छोटी सी मेज के साथ एक त्वरित परीक्षण किया जिसमें केवल 2 डेटा पृष्ठ और 3 पृष्ठ हैं, और जो मैं देख रहा हूं वह उन दो परिभाषाओं की पुष्टि करता है।

एक चीज जो शायद आपको बुरे परिणाम दे रही है वह यह है कि आप मेमोरी को साफ़ नहीं कर रहे हैं। आपको डिस्क से पुनः लोड करने के लिए बाध्य करने के लिए परीक्षणों के बीच निम्नलिखित को चलाना चाहिए:

DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;

मेरा परीक्षण सेटअप सिर्फ निम्नलिखित था:

CREATE TABLE dbo.ReadTest (Col1 CHAR(7500) DEFAULT (' '));
INSERT INTO dbo.ReadTest (Col1) VALUES (DEFAULT), (DEFAULT);

मैंने फिर निम्नलिखित भाग किया:

SELECT reads, logical_reads FROM sys.dm_exec_sessions WHERE session_id = @@SPID;
SELECT * FROM dbo.ReadTest;

(हां, मैं उसी सत्र में परीक्षण कर रहा था जिसमें मैं DMV चला रहा था, लेकिन इसने readsक्षेत्र के परिणामों को तिरछा नहीं किया , और यदि कुछ और नहीं तो कम से कम सुसंगत था यदि यह logical_readsक्षेत्र में योगदान देता ।)

परीक्षण के लिए मैं DBCC कमांड और फिर दो सलेक्ट क्वेश्चन चलाऊंगा। तब मुझे मैदान readsऔर logical_readsमैदान दोनों में छलांग लगती। मैं फिर से चयनित प्रश्नों को चलाऊंगा और कभी-कभी मुझे एक अतिरिक्त कूद दिखाई देगा reads

उसके बाद, मैं दो का चयन प्रश्नों कई बार चल पाएंगे और readsएक ही रहते हैं, जबकि होगा logical_reads4 हर बार से ऊपर चला गया।

मैं तब DBCC को चलाने के साथ शुरू होता और उसी पैटर्न को देखता। मैंने यह काफी बार किया और रिपोर्ट किए गए अंक सभी टेस्ट रन के अनुरूप थे।


और जानकारी:

मैं SQL Server 2012, SP2 - 64 बिट (11.0.5343) पर भी परीक्षण कर रहा हूं।

निम्नलिखित DBCC कमांड्स हम दोनों की कोशिश की है और कोई प्रभाव नहीं देखा है:

DBCC FREESYSTEMCACHE('ALL');
DBCC FREEPROCCACHE;
DBCC FREESESSIONCACHE;

ज्यादातर समय DBCC DROPCLEANBUFFERSकाम करता है, लेकिन मैं कभी-कभी देखता हूं कि यह अभी भी बफ़र पूल में है। अजीब।

जब मैं:

  • DBCC DROPCLEANBUFFERS: रीड्स 24 से ऊपर जाते हैं और तार्किक_ 52 से ऊपर जाते हैं।
  • SELECT [Col1] FROM dbo.ReadTest;फिर से चलाएँ : रीड्स ऊपर नहीं जाते हैं, लेकिन तार्किक_ 6 से ऊपर जाते हैं।
  • क्वेरी टेक्स्ट और रि-रन के लिए एक स्थान जोड़ें: रीड्स ऊपर नहीं जाते हैं, लेकिन तार्किक_ब्रिट्स 52 तक जाते हैं (ठीक उसी तरह जैसे DBCC DROPCLEANBUFFERS)।

ऐसा प्रतीत होता है कि 52 तार्किक योजना पीढ़ी और परिणामों के लिए खाते पढ़ते हैं, जिसका अर्थ है कि योजना पीढ़ी अतिरिक्त 46 तार्किक रीड का कारण बनी। लेकिन भौतिक रीड्स फिर से ऊपर नहीं जाते हैं और फिर भी यह वही 52 तार्किक रीड है जैसा कि तब था जब शारीरिक रीडिंग को भी करने की आवश्यकता थी, इसलिए logical_readsइसमें भौतिक शामिल नहीं है reads। मैं इस बिंदु को स्पष्ट कर रहा हूं, कि यह प्रश्न में कहा गया है या नहीं।

लेकिन, एक व्यवहार मैंने नोटिस किया जो तालिका के डेटा पृष्ठों के अस्तित्व का उपयोग करके (कम से कम थोड़ा) फेंकता है sys.dm_os_buffer_descriptors: यह किसी अन्य प्रक्रिया द्वारा पुनः लोड हो जाता है। यदि आप DROPCLEANBUFFERS और तुरंत जांच करते हैं, तो इसे चला जाना चाहिए। लेकिन कुछ मिनट प्रतीक्षा करें और यह फिर से दिखाई देता है, लेकिन इस बार सभी डेटा पृष्ठों के बिना। मेरे परीक्षण में, तालिका में 1 IAM पृष्ठ और 4 डेटा पृष्ठ हैं। मेरे द्वारा करने के बाद सभी 5 पृष्ठ बफ़र पूल में हैं SELECT। लेकिन जब इसे किसी अन्य प्रक्रिया द्वारा पुनः लोड किया जाता है, तो यह सिर्फ IAM पेज और 1 डेटा पेज होता है। मुझे लगा कि यह SSMS IntelliSense हो सकता है, लेकिन मैंने अपने क्वेरी टैब में उस ऑब्जेक्ट नाम के सभी संदर्भ हटा दिए हैं और यह अभी भी पुनः लोड हो गया है।


पर्याप्त रूप से, मैंने अपने परीक्षण रिग से DBCC DROPCLEANBUFFERS(और अन्य DBCC DROPxxxआदेशों) को हटा दिया क्योंकि उन्हें कोई फर्क नहीं पड़ा। डेटाबेस को ऑफ़लाइन सेट करना सभी बफ़र्स को छोड़ देता है, और डेटाबेस से जुड़ी बाकी सभी चीजें।
मैक्स वर्नन

जैसा कि आप पढ़ रहे हैं शारीरिक होने के बारे में मैं उसी समझ में था, और बफर पूल, बीडब्ल्यूटी से तार्किक रीड शुरू होते हैं।
अधिकतम वर्नोन

मैंने भी इसके साथ प्रयास किया: DBCC FREESYSTEMCACHE ('ALL'); DBCC FREEPROCCACHE; DBCC FREESESSIONCACHE;
मैक्स वर्नोन

1
@MaxVernon "रख उन्हें guessin" सुविधा ;-) हो सकता है
सोलोमन Rutzky

2
@MaxVernon, CHECKPOUNTडेटाबेस के संदर्भ में पहले निष्पादित करने के लिए मत भूलना DBCC DROPCLEANBUFFERS
डैन गुज़मैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.