2009-12-02 19 views
9

मेरे पास लगभग 20+ मिलियन रिकॉर्ड वाली एक तालिका है।SQL सर्वर धीमी बड़ी तालिका से चुनें

EventId UNIQUEIDENTIFIER 
SourceUserId UNIQUEIDENTIFIER 
DestinationUserId UNIQUEIDENTIFIER 
CreatedAt DATETIME 
TypeId INT 
MetaId INT 

तालिका प्राप्त कर रहा है प्रत्येक दिन 100k के बारे में + रिकॉर्ड:

संरचना की तरह है।

मैं अनुक्रमित MetaId को छोड़कर प्रत्येक स्तंभ पर, के रूप में यह 'जहां' खंड

में नहीं किया जाता है समस्या यह है जब मैं जैसे लेने के लिए चाहते हैं। वांछित SourceUserId

क्वेरी के लिए नवीनतम 100 रिकॉर्ड निष्पादित करने के लिए कभी-कभी 4 मिनट तक लगते हैं, जो स्वीकार्य नहीं है।

ईजी।

SELECT TOP 100 * FROM Events WITH (NOLOCK) 
WHERE SourceUserId = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
AND 
(
TypeId IN (2, 3, 4) 
    OR 
(TypeId = 60 AND SrcMemberId != DstMemberId) 
) 
ORDER BY CreatedAt DESC 

मैं विभाजन आदि नहीं कर सकता क्योंकि मैं SQL सर्वर और एंटरप्राइज़ का मानक संस्करण उपयोग कर रहा हूं।

मुझे यह भी लगता है कि तालिका धीमी होने के लिए काफी छोटी है।

मुझे लगता है कि समस्या ऑर्डर द्वारा ऑर्डर के रूप में है क्योंकि डीबी को डेटा के बहुत बड़े सेट के माध्यम से जाना चाहिए।

कोई विचार यह कैसे जल्दी बनाता है?

शायद संबंधपरक डेटाबेस उस तरह के डेटा के लिए एक अच्छा विचार नहीं है।

डाटा हमेशा उठाया जा रहा है का आदेश दिया CreatedAt DESC द्वारा

पढ़ने के लिए धन्यवाद।

PabloX

+0

इस पर वोट देना, क्योंकि मेरे पास लगभग एक ही समस्या है! –

उत्तर

15

आप संभावना क्वेरी के इस प्रकार के लिए एक समग्र सूचकांक बनाना चाहेंगे होगा - जब क्वेरी चलाता है धीरे-धीरे यह सबसे अधिक संभावना नीचे स्कैन करने के लिए चुन रहा है MadeAt कॉलम पर एक इंडेक्स और SourceUserId मान पर एक अवशिष्ट फ़िल्टर करें, जब वास्तव में आप जो करना चाहते हैं वह किसी दिए गए SourceUserId के लिए सीधे सभी रिकॉर्ड्स पर कूदना है - इसे प्राप्त करने के लिए, आप एक समग्र बनाना चाहते हैं इंडेक्स मुख्य रूप से SourceUserId (समानता जांच करने) पर और दूसरी बार CreateAt पर (किसी दिए गए SourceUserId मान के भीतर ऑर्डर को संरक्षित करने के लिए) पर। आप इस कॉलम की चयनकता के आधार पर टाइपआईडी को भी जोड़ने की कोशिश कर सकते हैं।

तो, 2 कि सबसे अधिक संभावना सबसे अच्छा repeatable प्रदर्शन (उन्हें बाहर की कोशिश और तुलना करें) होगा दे देंगे:

  1. पर (SourceUserId, CreatedAt) पर (SourceUserId, TypeId
  2. सूचकांक सूचकांक, CreatedAt)

हमेशा की तरह, वहाँ भी निर्धारित करने के साथ ध्यान में रखना कई अन्य विचार कैसे/क्या/जहां सूचकांक को, Remus एक अलग जवाब में चर्चा करता है एक बड़ा विचार क्वेरी बनाम लुकअप रखने को कवर किया जाता है के रूप में। इसके अतिरिक्त आपको लिखने के वॉल्यूम, possible fragmentation impact (if any), सिंगलटन लुकअप बनाम बड़े अनुक्रमिक स्कैन इत्यादि पर विचार करना होगा।

+2

+1: और SQL सर्वर शब्दावली में 'अनुक्रमणिका को कवर करना'। –

+1

हाँ, बहुत से SQL प्रश्नों के साथ, उत्तर कुछ जादू चयन चाल नहीं है लेकिन अच्छी पुरानी फैशन इंडेक्स डिज़ाइन है। –

+0

इस इंडेक्स को क्लस्टर करना और धारीदार डिस्क होने से भी मदद मिलेगी। –

0

मुझे यकीन है कि CreatedAt समुचित रूप से सूचीबद्ध है

+0

'निर्मित द्वारा निर्मित आदेश' खंड के साथ और बिना क्वेरी को बेंचमार्क करना अच्छा होगा! –

+0

पूरी तरह से CreateAt पर एक इंडेक्स इस प्रकार की क्वेरी के साथ-साथ समानता फ़िल्टर SourceUserId पर एक समग्र रूप से मदद नहीं करेगा - केवल एटीएक्स पर एक इंडेक्स केवल ऑप्टिमाइज़र को बी-ट्री के पीछे एक स्कैनल फ़िल्टर चेक करने के लिए स्कैन करने की अनुमति देगा SourceUserId जब तक यह निर्दिष्ट मूल्य के साथ 100 नहीं मिला (यदि SourceUserId बहुत चुनिंदा है, तो यह संभवतः काफी लंबा स्कैन का कारण बनता है)। यदि आप SourceUserId पर संयुक्त सूचकांक बनाते हैं तो बनाया गया, ऑप्टिमाइज़र स्कैन को छोड़ सकता है, दिए गए SourceUserId को ढूंढ सकता है और केवल पूर्व-आदेशित अंतिम 100 को खींच सकता है। – chadhoc

0

आप एक यूनिअन के साथ दो में क्वेरी विभाजित OR जैसे

SElect * FROM(
SELECT TOP 100 * FROM Events WITH (NOLOCK) 
WHERE SourceUserId = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
AND TypeId IN (2, 3, 4) 
UNION SELECT TOP 100 * FROM Events WITH (NOLOCK) 
WHERE SourceUserId = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
AND TypeId = 60 AND SrcMemberId != DstMemberId 
) 
ORDER BY CreatedAt DESC 

इसके अलावा कुछ से बचने के लिए (जो आपके सूचकांक पैदा कर सकता है इस्तेमाल किया जा करने के लिए नहीं), जाँच करें कि uniqueidentifier अनुक्रमित संकुल नहीं कर रहे हैं हो सकता है।

1

2 सितं, वर तालिकाओं में डेटा प्राप्त करने की सिफारिश करेंगे

INSERT INTO @Table1 
SELECT * FROM Events WITH (NOLOCK) 
WHERE SourceUserId = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
AND 
(
TypeId IN (2, 3, 4) 
) 
INSERT INTO @Table2 
SELECT * FROM Events WITH (NOLOCK) 
WHERE SourceUserId = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
AND 
(
(TypeId = 60 AND SrcMemberId != DstMemberId) 
) 

तो चयन का आदेश दिया और ऊपर से एक unoin लागू होते हैं। जाने से डेटा सीमित करें।

1

मैं एक यूनिअन उपयोग करने का सुझाव:

SELECT TOP 100 x.* 
    FROM (SELECT a.* 
      FROM EVENTS a 
     WHERE a.typeid IN (2, 3, 4) 
     UNION ALL 
     SELECT b.* 
      FROM EVENTS b 
     WHERE b.typeid = 60 
      AND b.srcmemberid != b.dstmemberid) x 
WHERE x.sourceuserid = '15b534b17-5a5a-415a-9fc0-7565199c3461' 
6

मैं प्रत्येक स्तंभ पर अनुक्रमित है छोड़कर

गैर कवर अनुक्रमित जाएगा MetaId संभावना 'tipping point' मारा और क्वेरी एक वापस लौट आएगा टेबल स्कैन बस प्रत्येक कॉलम पर एक इंडेक्स जोड़ना क्योंकि इसका उपयोग उस खंड में किया जाता है जहां क्लॉज अच्छा इंडेक्स डिज़ाइन समान नहीं है। उदाहरण के लिए आपकी क्वेरी लेने के लिए, एक अच्छा 100% कवर सूचकांक होगा:

INDEX ON (SourceUserId , CreatedAt) INCLUDE (TypeId, SrcMemberId, DstMemberId) 

के बाद सूचकांक भी उपयोगी है, हालांकि यह अभी भी खोज के कारण करने के लिए जा रहा:

INDEX ON (SourceUserId , CreatedAt) INCLUDE (TypeId) 

और अंत में एक सूचकांक w/ओ किसी भी शामिल स्तंभ हो सकता है मदद, लेकिन बस के रूप में होने की संभावना नजरअंदाज कर दिया जाएगा है (कॉलम के आंकड़े और प्रमुखता अनुमान पर निर्भर करता है):

INDEX ON (SourceUserId , CreatedAt) 

बू SourceUSerId पर एक अलग अनुक्रमणिका नहीं है और MadeAt पर एक मूल रूप से आपकी क्वेरी के लिए बेकार है।

Index Design Basics देखें।

+0

धन्यवाद! इससे मुझे मदद मिली :) – pablox

0

यदि हर दिन 100K रिकॉर्ड जोड़े जाते हैं, तो आपको अपनी अनुक्रमणिका विखंडन की जांच करनी चाहिए। और तदनुसार इसे पुनर्निर्माण या पुनर्गठित करें। और जानकारी: SQLauthority

+0

हाँ मैं भी यह कर रहा हूं – pablox

4

तथ्य यह है कि तालिका अनुक्रमित GUID मूल्यों पर बनाया गया है, समस्याओं कि प्रदर्शन को प्रभावित करती है की एक संभव श्रृंखला इंगित करता है:

  • उच्च सूचकांक विखंडन: के बाद से नया GUIDs उत्पन्न कर रहे हैं यादृच्छिक रूप से, सूचकांक उन्हें अनुक्रमिक क्रम में व्यवस्थित नहीं कर सकता है और नोड्स असमान रूप से फैलते हैं।
  • पृष्ठ विभाजन की उच्च संख्या: एक GUID (16 बाइट्स) का आकार इंडेक्स में कई पेज विभाजित करता है, क्योंकि एक नए मूल्य की तुलना में अधिक संभावना है कि किसी पृष्ठ में उपलब्ध शेष स्थान में फिट न हो।
  • धीमी मूल्य तुलना: दो GUID की तुलना करना अपेक्षाकृत धीमी गति से ऑपरेशन है क्योंकि सभी 33 वर्णों का मिलान होना चाहिए।
यहाँ

कैसे की जांच और हल करने के लिए इन समस्याओं पर संसाधनों की एक जोड़ी:

0

हम ले जाकर एक नाबालिग लाभ महसूस किया गया है हमारी घटना तालिका के लिए एक बड़ी पहचान कुंजी के लिए; क्लस्टर्ड प्राथमिक कुंजी के रूप में इसका उपयोग करके, हम धोखा दे सकते हैं और डेट ऑर्डरिंग के लिए इसका उपयोग कर सकते हैं।

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