25+ मिलियन पंक्तियों के लिए प्रश्नों का अनुकूलन करना


11

मैं एमएस एसक्यूएल का उपयोग कर रहा हूं, और मुझे विभिन्न मानदंडों पर एक ही टेबल पर कई प्रश्न चलाने होंगे। पहले तो मैंने प्रत्येक क्वेरी को मूल तालिका पर चलाया, हालांकि वे सभी कुछ फ़िल्टरिंग (यानी दिनांक, स्थिति) साझा करती हैं। इसमें बहुत समय (लगभग 2 मिनट) लगा।

डेटा पंक्तियों में डुप्लिकेट हैं, और सभी अनुक्रम NON-CLUSTERED हैं। मुझे अपने मानदंड के लिए केवल 4 कॉलमों में दिलचस्पी है और परिणाम सभी प्रश्नों के लिए केवल गिनती का उत्पादन करना चाहिए।

स्तंभों की जरूरत: TABLE, FIELD, AFTER, DATE, और वहाँ से प्रत्येक पर एक सूचकांक है DATEऔर TABLE

मुझे केवल उन क्षेत्रों के साथ एक अस्थायी तालिका बनाने के बाद, यह एक 1:40 मिनट तक नीचे चली गई, जो अभी भी बहुत खराब है।

CREATE TABLE #TEMP
(
    TABLE VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    AFTER VARCHAR(1000) NULL,
    DATE DATETIME,
    SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)

INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
    SELECT TABLE, FIELD, AFTER, DATE 
    FROM mytbl WITH (NOLOCK)
    WHERE TABLE = 'OTB' AND
    FIELD = 'STATUS'

रननिग इस -> (216598 पंक्ति)

चूंकि सभी प्रश्न दिनांक सीमा पर निर्भर नहीं हैं, इसलिए मैंने इसे क्वेरी में शामिल नहीं किया। समस्या यह है कि यह केवल डालने के लिए 1 मिनट से अधिक समय ले रहा है । उपरोक्त प्रविष्टि में 1:19 मिनट लगे

मैं कई प्रश्नों के लिए कुछ इस तरह चलाना चाहता हूं:

SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'

यह चयन की तुलना में अधिक डालने के साथ एक समस्या है, लेकिन अस्थायी में मूल तालिका की तुलना में कम पंक्तियां हैं जो कई बार तालिका से गुजरने से बेहतर हो सकती हैं।

मैं इसे कैसे अनुकूलित कर सकता हूं?

संपादित करें

मैंने सॉर्ट आईडी को हटा दिया है, मुझे लगता है कि समस्या मुख्य रूप से चयन के साथ थी और सम्मिलित नहीं थी। यह एक अनुमान था।

मैं किसी भी सूचकांक पर एक अद्वितीय नहीं बना सकता क्योंकि कोई अद्वितीय क्षेत्र या पंक्तियाँ नहीं हैं।

मैं SQL Server 2012 का उपयोग कर रहा हूं।

तालिका जानकारी : यह एक ढेर है और इसमें निम्नलिखित स्थान का उपयोग है:

name    rows        reserved    data        index_size  unused
mytbl   24869658    9204568 KB  3017952 KB  5816232 KB  370384 KB

@MikaelEriksson मैं प्रोडक्शन टेबल को संशोधित नहीं कर सकता ..
अति

यदि आप जिन प्रश्नों को ऑप्टिमाइज़ करने का प्रयास कर रहे हैं, वे फ़ॉर्म के हैं SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01', तो आप प्रत्येक (क्वेरी) को अलग से ऑप्टिमाइज़ करने का प्रयास क्यों नहीं करते? क्या आपको तालिका में अनुक्रमणिका जोड़ने की अनुमति नहीं है?
ypercube y

2
आपको यह निर्धारित करने की आवश्यकता है कि यह धीमा क्यों है। क्या इसे अवरुद्ध किया जा रहा है? यह tempdb के बढ़ने की प्रतीक्षा कर रहा है? क्या निष्पादन योजना संक्षिप्त है? कोई भी ठीक कर सकते हैं और अधिक जानकारी के बिना "मेरी क्वेरी धीमी है" ...
हारून बर्ट्रेंड

3
ठीक है, ऐसा लगता है कि मेरे लिए एक खोया हुआ कारण है ( "मुझे कुछ भी अनुकूलित करने की अनुमति नहीं है, इसलिए हमें हर बार कुछ प्रश्नों को चलाने के लिए एक अस्थायी तालिका में 200K पंक्तियों को धक्का देने की अनुमति देता है" )। लेकिन आप मेज से कॉलम TABLEऔर FIELDकॉलम निकाल सकते हैं #temp(सभी पंक्तियों के TABLE = 'OTB' AND FIELD = 'STATUS'बाद सभी विशिष्ट अस्थायी तालिका के लिए है।)
ypercube15

2
मैंने एक विस्तृत (और विनम्र) टिप्पणी जोड़कर एक संपादन और सुधार के लिए कहा। यह टिप्पणी किस लिए है आपको अपने प्रश्न को SQL सर्वर के उस संस्करण के साथ भी टैग करना चाहिए जिसका आप उपयोग कर रहे हैं (उदाहरण के लिए SQL Server 2014)। तालिका के लिए DDL भी सहायक हो सकता है ( CREATE TABLEकथन)। डाउन वोट इसलिए था क्योंकि प्रश्न स्पष्ट नहीं था।
पॉल व्हाइट 9

जवाबों:


12

सवाल मुख्य रूप से चयन कथन को अनुकूलित करने के तरीके के बारे में है:

SELECT [TABLE], [FIELD], [AFTER], [DATE]
FROM mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB' AND
[FIELD] = 'STATUS'

निरर्थक अनुमानों को हटाना और प्रकल्पित dboस्कीमा जोड़ना :

SELECT [AFTER], [DATE] 
FROM dbo.mytbl WITH (NOLOCK)
WHERE [TABLE] = 'OTB'
AND FIELD = 'STATUS';

([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])SQL सर्वर जैसे सूचकांक के बिना दो मुख्य विकल्प हैं:

  1. पूरी तरह से ढेर को स्कैन करें (3 जीबी +); या
  2. मिलान [TABLE] = 'OTB'और [FIELD] = 'STATUS'(उपयोग IDX6) पंक्तियों का पता लगाएँ , फिर प्रति[AFTER] और [DATE]स्तंभों को पुनः प्राप्त करने के लिए प्रति पंक्ति एक ढेर (RID) लुकअप करें ।

अनुकूलक एक ढेर स्कैन या सूचकांक की तलाश RID देखने के साथ की अनुमानित चयनात्मकता पर निर्भर करता है चुनता है या नहीं [TABLE] = 'OTB'और [FIELD] = 'STATUS'विधेय। यह देखने के लिए जांचें कि क्या शोध से प्राप्त पंक्तियों की अनुमानित संख्या वास्तविकता से मेल खाती है। यदि नहीं, तो अपने आंकड़े अपडेट करें। सूचकांक के उपयोग के लिए एक तालिका संकेत के साथ क्वेरी का परीक्षण करें, यदि वह स्थिति काफी चुनिंदा है । यदि ऑप्टिमाइज़र वर्तमान में सूचकांक की तलाश कर रहा है, तो ढेर को स्कैन करने के लिए INDEX(0)या FORCESCANसंकेत के साथ प्रदर्शन का परीक्षण करें ।

इसके अलावा, आप कुछ अप्रयुक्त स्थान (370MB) को हटाकर हीप के स्कैन को थोड़ा सुधार सकते हैं। SQL Server 2008 में यह हीप के पुनर्निर्माण के द्वारा किया जा सकता है। ढेर में अप्रयुक्त स्थान अक्सर एक टेबल लॉक किए बिना हटाए गए प्रदर्शनों के परिणाम के रूप में लिया जाता है (टेबल लॉक के बिना, खाली पृष्ठों को ढेर से नहीं हटाया जाता है)। लगातार विलोपन का अनुभव करने वाले तालिकाओं को अक्सर इस कारण से क्लस्टर तालिका के रूप में संग्रहीत किया जाता है।

हीप स्कैन का प्रदर्शन इस बात पर निर्भर करता है कि मेमोरी में टेबल कितनी संग्रहीत है, डिस्क से कितना पढ़ा जाना चाहिए, पेज कितने भरे हुए हैं, लगातार स्टोरेज की गति, स्कैन I / O या CPU बाध्य है ( समानांतरवाद मदद कर सकता है)।

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

CREATE INDEX index_name
ON dbo.mytbl ([DATE],[AFTER])
WHERE [TABLE] = 'OTB'
AND [FIELD] = 'STATUS';

इंडेक्स कम्प्रेशन पर भी विचार करें, यदि वह उपलब्ध हो और फायदेमंद हो। किसी प्रकार के नए सूचकांक के बिना, आप दिए गए क्वेरी के प्रदर्शन को बेहतर बनाने के लिए अपेक्षाकृत कम कर सकते हैं।


क्षमा करें पॉल, वहाँ है IDX6 nonclustered located on PRIMARY TABLE, FIELD:। शायद यह आपके द्वारा बताई गई चीजों को बदल देगा?
एतेह

6

मुझे लगता है कि यहाँ अनुक्रमणिका बदलने का एक मामला है क्योंकि:

  • आपके पास करने के लिए एक कार्य है (ये कई प्रश्न)
  • डेटा वेयरहाउस वॉल्यूम (25+ मिलियन पंक्तियाँ) और
  • एक प्रदर्शन समस्या।

यह SQL सर्वर 2012 में शुरू किए गए गैर-क्लस्टर किए गए कॉलमस्टोर इंडेक्स के लिए एक अच्छा उपयोग मामला भी होगा, अर्थात कई स्तंभों के साथ एक बड़ी मेज पर कुछ स्तंभों को संक्षेप / एकत्र करें।

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

मैंने आपके सेटअप की नकल करने के लिए एक साधारण परीक्षण रिग स्थापित किया, और प्रदर्शन में एक अच्छा सुधार देखा:

USE tempdb
GO

SET NOCOUNT ON
GO

-- Create a large table
IF OBJECT_ID('dbo.largeTable') IS NOT NULL
DROP TABLE dbo.largeTable
GO
CREATE TABLE dbo.largeTable ( 

    [TABLE] VARCHAR(30) NULL,
    FIELD VARCHAR(30) NULL,
    [AFTER] VARCHAR(1000) NULL,
    [DATE] DATETIME,
    SORT_ID INT IDENTITY(1,1),

    pad VARCHAR(100) DEFAULT REPLICATE( '$', 100 )
)
GO

-- Populate table
;WITH cte AS (
SELECT TOP 100000 ROW_NUMBER() OVER ( ORDER BY ( SELECT 1 ) ) rn
FROM master.sys.columns c1
    CROSS JOIN master.sys.columns c2
    CROSS JOIN master.sys.columns c3
)
INSERT INTO dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
SELECT 
    x.tableName, 
    y.field,
    z.[after],
    DATEADD( day, rn % 1111, '1 Jan 2012' )
FROM cte c
    CROSS JOIN ( VALUES ( 'OTB' ), ( 'AAA' ), ( 'BBB' ), ( 'CCCC' ) ) x ( tableName )
    CROSS JOIN ( VALUES ( 'STATUS' ), ( 'TIME' ), ( 'POWER' ) ) y ( field )
    CROSS JOIN ( VALUES ( 'R' ), ( 'X' ), ( 'Z' ), ( 'A' ) ) z ( [after] )

CHECKPOINT

GO 5

EXEC sp_spaceused 'dbo.largeTable'
GO

SELECT MIN([DATE]) xmin, MAX([DATE]) xmax, FORMAT( COUNT(*), '#,#' ) records
FROM dbo.largeTable
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff1
GO

-- Add the non-clustered columnstore
CREATE NONCLUSTERED COLUMNSTORE INDEX _cs ON dbo.largeTable ( [TABLE], FIELD, [AFTER], [DATE] )
GO

-- Optionally clear cache for more comparable results; DO NOT RUN ON PRODUCTION SYSTEM!!
--DBCC DROPCLEANBUFFERS
--DBCC FREEPROCCACHE
--GO

-- Check query again
DECLARE @startDate DATETIME2 = SYSUTCDATETIME()

SELECT COUNT(*) AS COUNT
FROM dbo.largeTable
WHERE [AFTER] = 'R' 
  AND [DATE] >= '2014-01-01' 
  AND [DATE] <= '2015-01-01'

SELECT DATEDIFF( millisecond, @startDate, SYSUTCDATETIME() ) diff2
GO

मेरे परिणाम, 6 सेकंड v 0.08 सेकंड:

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

सारांश में, अपने बॉस के साथ अनुक्रमणिका को बदलने या कम से कम किसी प्रकार की रातोंरात प्रक्रिया बनाने का प्रयास करें और जहां इन रिकॉर्ड्स को केवल-पढ़ने के लिए रिपोर्टिंग टेबल / डेटाबेस पर ले जाया जाए, जहां आप अपना काम कर सकते हैं, और अनुक्रमण जोड़ सकते हैं उस कार्यभार के लिए उपयुक्त है।

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