2010-02-06 7 views
8

मैंने निम्नलिखित कोड लिखा है, यह ठीक काम करता है, लेकिन तालिका में दस लाख रिकॉर्ड होने पर इसे पूरा करने में 3 सेकंड लगते हैं। निम्नलिखित कोड को अनुकूलित करने का कोई तरीका है।टी-एसक्यूएल: अनुकूलित पेजिंग कैसे करें?

DBCC DROPCLEANBUFFERS; 
DBCC FREEPROCCACHE; 

DECLARE @Page_Size int; 
DECLARE @Page_Number int; 
DECLARE @Lower_Bound int; 
DECLARE @Upper_Bound int; 

SET @Page_Size = 30; 
SET @Page_Number = 30000; 
SET @Lower_Bound = (@Page_Number - 1) * @Page_Size; 
--SET @Upper_Bound = @Page_Number * @Page_Size; 


WITH Customers AS--(Row_Numbr, Record_Id, First_Name, 
     Middle_Name, Last_Name, Email, Telephone) AS 
(

    SELECT ROW_NUMBER() 
     OVER 
     (ORDER BY Account.Customer.Record_Id) AS Row_Numbr, * 
    FROM Account.Customer 
) 

SELECT top(@Page_Size) * 
FROM Customers 
WHERE Row_Numbr > @Lower_Bound-- 
    AND Row_Numbr <= @Upper_Bound -- This is suppose to be faster 
--SELECT * FROM Customers 
--WHERE Row_Numbr > @Lower_Bound 
-- AND Row_Numbr <= @Upper_Bound 
+0

निष्पादन योजना क्या कहती है? – super9

+0

आपके पास कौन सी अनुक्रमणिका है? क्या आप बिल्ड टेबल स्क्रिप्ट पोस्ट कर सकते हैं? –

+0

संबंधित: http://stackoverflow.com/questions/1897436/row-number-over-not-fast-enough-with-large-result-set-any-good-solution –

उत्तर

14

पहला, क्यों DBCC DROPCLEANBUFFERS;? यह बफर पूल का एक कठिन ठंडा रीसेट है। जब तक आप अपने हार्ड ड्राइव IO प्रदर्शन को मापना और ट्यून करना नहीं चाहते हैं, तब तक कोई भी ठंडा कैश के प्रदर्शन की परवाह नहीं करता है। यह आपका सिस्टम कैसे काम करेगा। बफर पूल में कैशिंग पेज डेटाबेस में सबसे महत्वपूर्ण प्रदर्शन पहलू है, और आप इसे बाहर ले जाते हैं। यह इंजन के बिना फेरारी में दिखने की तरह है और पूछ रहा है कि इतनी धीमी क्यों है। प्रदर्शन माप के लिए आपको विपरीत के साथ करना चाहिए: कैश को गर्म करने के लिए 4-5 बार क्वेरी करें, फिर मापें।

दूसरा, आपकी तालिका संरचना क्या है? तालिका Account.Customer तालिका क्लस्टर इंडेक्स ऑर्डर Record_id द्वारा है? यदि नहीं, तो आप कभी भी अपना प्रदर्शन प्राप्त नहीं करेंगे, चाहे आप अपना टी-एसक्यूएल कैसे व्यक्त करते हों।

और अंतिम लेकिन कम से कम नहीं, आपके पास कौन सी प्रणाली है? क्या स्मृति में पूरे डेटाबेस को कैश करने के लिए पर्याप्त RAM है? यदि नहीं, तो अधिक रैम खरीदें। क्या ऐसी अन्य प्रक्रियाएं हैं जो स्मृति के लिए प्रतिस्पर्धा करती हैं, जैसे आईआईएस/एएसपी? यदि हां, तो उन्हें अपने सर्वर पर लाएं, यदि प्रदर्शन महत्वपूर्ण है तो आपको ever ever run the database on the same host as the web server होना चाहिए।

एक विकल्प के तेजी से पेजिंग कीसेट संचालित समाधान पर विचार के लिए:

/* moving up */ 
SELECT top(@Page_Size) * 
FROM Account.Customer 
WHERE Record_Id > @lastPageRecordId 
ORDER BY Record_Id; 

/* moving down */ 
SELECT top(@Page_Size) * 
FROM Account.Customer 
WHERE Record_Id < @firstPageRecordId 
ORDER BY Record_Id DESC; 

एक कीसेट संचालित समाधान अंतिम स्थिति के लिए सीधे की तलाश और फिर हो सकती है अगले/पिछले पृष्ठ को स्कैन करता है, संकुल सूचकांक कुंजी स्थिति का उपयोग कर। पेजिंग लॉजिक (राज्य) को पृष्ठ संख्या को याद रखने के बजाय वहां से जारी रखने के लिए प्रदर्शित होने वाले पृष्ठ पर अंतिम और पहली कुंजी याद रखना चाहिए।

रोकाउंट आधारित समाधान (साथ ही साथ MySQL में LIMIT) कुंजीसेट आधारित लोगों की तुलना में कम कुशल हैं क्योंकि उन्हें हमेशा कुंजी की स्थिति में सीधे खोज करने की बजाय, खुद को स्थिति में रखने के लिए रिकॉर्ड गिनना पड़ता है।

+0

लेकिन रिकॉर्ड_आईडी 1, 3, 7, 10, 11, 12, 13, 17. हो सकता है। पृष्ठ बराबर नहीं होंगे, अंतिम पृष्ठ शायद पूरी तालिका को कवर नहीं करेगा। इस मामले में, सटीक @lastPageRecordId कैसे प्राप्त करें? अभी मुझे यह मिला है कि आप Record_Id अनुक्रमणिका का उपयोग करके प्रदर्शन को बढ़ाने के लिए चाहते हैं, इसलिए आप चाहते हैं कि मैं खंड के साथ बदलूं और Row_Number के बजाय Record_Id का उपयोग करें, मुझे यकीन नहीं है कि अभी तक खंड को कैसे बदला जाए !! क्या मैं आपका पीछा कर रहा हूँ? – Costa

+1

कहें कि आप 3 के पेज प्रदर्शित करना चाहते हैं। पहली बार जब आप TOP (3) ... रिकॉर्ड आईडी द्वारा आदेश देते हैं और आपको 1,3,7 मिलते हैं। अगले पृष्ठ के लिए आप टॉप (3) के लिए पूछते हैं ..जहां रिकॉर्ड किया गया> 7 ... द्वारा आदेश ... और आपको 10,11,12 मिलते हैं। नीचे जाने के लिए आप टॉप (3) के लिए पूछें ... जहां रिकॉर्ड किया गया <10 ... द्वारा आदेश ... डीईएससी और आप फिर से 7,3,1 प्राप्त करते हैं। आगे जाने के लिए आप टॉप (3) के लिए पूछें ... रिकॉर्ड आईडी> 12 ... द्वारा आदेश ... और आपको 13,17 मिलते हैं। आप पृष्ठ पर पहले और आखिरी रिकॉर्ड आईडी का उपयोग * कुंजी * के रूप में करते हैं, रैंक के रूप में नहीं। –

+0

@ रीमस हाय, तो पेजिंग की तुलना में कीसेट समाधान तेज है? मैंने उपरोक्त यूआर कोड के आधार पर संग्रहीत संग्रहीत प्रक्रिया बनाने की कोशिश की लेकिन मुझे कोई परिणाम नहीं मिला। कोई विचार? बनाएं प्रोक PagingSample \t ((पर) PAGE_SIZE पूर्णांक, \t (कम) firstPageRecordId पूर्णांक) के रूप में \t चयन शीर्ष ((PAGE_SIZE पर)) * \t dbo.data \t कहां (कम) से शुरू (पर) पहचान <(at) firstPageRecordId \t डेटटाइम डीईएससी द्वारा ऑर्डर; अंत –

2

मैं इस संग्रहीत प्रक्रिया का उपयोग करें:

CREATE PROCEDURE sp_PagedItems 
    (
    @Page int, 
    @RecsPerPage int 
    ) 
AS 

-- We don't want to return the # of rows inserted 
-- into our temporary table, so turn NOCOUNT ON 
SET NOCOUNT ON 


--Create a temporary table 
CREATE TABLE #TempItems 
(
    ID int IDENTITY, 
    Name varchar(50), 
    Price currency 
) 


-- Insert the rows from tblItems into the temp. table 
INSERT INTO #TempItems (Name, Price) 
SELECT Name,Price FROM tblItem ORDER BY Price 

-- Find out the first and last record we want 
DECLARE @FirstRec int, @LastRec int 
SELECT @FirstRec = (@Page - 1) * @RecsPerPage 
SELECT @LastRec = (@Page * @RecsPerPage + 1) 

-- Now, return the set of paged records, plus, an indiciation of we 
-- have more records or not! 
SELECT *, 
     MoreRecords = 
    (
    SELECT COUNT(*) 
    FROM #TempItems TI 
    WHERE TI.ID >= @LastRec 
    ) 
FROM #TempItems 
WHERE ID > @FirstRec AND ID < @LastRec 


-- Turn NOCOUNT back OFF 
SET NOCOUNT OFF 
1

किसी SQL Server 2012 का उपयोग कर रहा है - एक नई सुविधा ORDER BY खंड में जोड़ा गया था एक सेट डेटा के अनुकूलन क्वेरी करने के लिए, डेटा पेजिंग के साथ आसान काम कर रही है एसक्यूएल सर्वर में पूरी निष्पादन योजना के लिए टी-एसक्यूएल में लिखने वाले किसी भी व्यक्ति के लिए। संदर्भ here

संबंधित मुद्दे