2009-01-18 24 views
5

दिए गए पंक्तियों की एक बड़ी संख्या का चयन करने के लिए मुझे एक बड़ी संख्या में पंक्तियों का चयन करने की आवश्यकता है जो स्वत: पहचान पहचान कॉलम पर कुंजी है। मेरे पास प्रत्येक पंक्ति के लिए प्राथमिक कुंजी मान हैं जिन्हें मैं चुनने का प्रयास कर रहा हूं, लेकिन यह बहुत बड़ा हो सकता है।प्राथमिक कुंजी

अक्सर, लेकिन हमेशा नहीं, जो पंक्तियों का चयन किया जा रहा है वे संगत होते हैं, इसलिए मैंने एक तंत्र को लागू किया जो चयन को सभी प्रविष्टियों के लिए श्रेणी खंडों के एक सेट में परिवर्तित करता है ([प्राथमिककि] 151 के बीच और 217), और एक फॉलबैक विधि जो एक इन क्लॉज के साथ सभी अलग प्रविष्टियों का चयन करती है।

अंत में मैं इस

SELECT * FROM Table WHERE ([PrimaryKey] BETWEEN 151 AND 217) OR ([PrimaryKey] BETWEEN 314 AND 378) OR ... 
OR [PrimaryKey] IN (1,3,7,14,147...) 

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

पहली बात यह है कि दिमाग में आने वाली बात यह है कि जब मैं अलग-अलग मूल्यों के विपरीत 2 (10 शायद?) से कुछ अलग करता हूं, तो मैं थ्रेसहोल्ड बदल सकता हूं, लेकिन मैं सोच रहा था कि कोई बेहतर समाधान है या नहीं वहाँ से बाहर।

उत्तर

7

उन मानों के साथ एक टेम्पप तालिका बनाएं जिन्हें आप चुनना चाहते हैं और अपनी मुख्य तालिका से temp तालिका में शामिल हों। इस तरह आपके पास व्यावहारिक रूप से कोई सीमा नहीं है।

+0

यहां भी एक तालिका चर का उपयोग कर सकता है –

1

उपयोगकर्ता ocdecio सही तरीके से प्रस्तावित करता है, तो आप एक टेम्परी टेबल में शामिल हो सकते हैं जिसमें सभी आईडी शामिल होंगी। तुम भी अलग यूनिअन भागों में अन्य रैंकों को विभाजित करने की कोशिश कर सकते:

SELECT * FROM Table WHERE [PrimaryKey] BETWEEN 151 AND 217 
UNION 
SELECT * FROM Table WHERE [PrimaryKey] BETWEEN 314 AND 378 
UNION 
... 
UNION 
SELECT * FROM Table WHERE [PrimaryKey] IN (1,3,7,14,147...) 
2

मैं अपने तंत्र के इरादे समझ सकते हैं। अभ्यास में, हालांकि, अनुकूलक में एक सूचकांक और विश्वास की उपस्थिति आमतौर पर बेहतर होती है।

यदि आप WHERE क्लॉज में दर्जन स्थितियां बनाना चाहते हैं, तो क्वेरी इंजन को उनमें से प्रत्येक को तब तक जांचना होगा जब तक कि यह कोई मिलान न हो।

समान रूप से, एकाधिक प्रश्नों को बनाने और उन्हें संघबद्ध करने का मतलब तालिका पर कई बार इंडेक्स स्कैन या इंडेक्स लुकअप होगा।

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

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

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

यदि ग्राहक गतिशील क्वेरी उत्पन्न करता है, तो आप तर्क दे सकते हैं कि आप सर्वर से कुछ लोड को क्लाइंट में स्थानांतरित कर रहे हैं। हालांकि मुझे अभी भी संदेह है कि लाभ महत्वपूर्ण होंगे।

ऐसा गधा, जब तक कि मैंने बहुत ही उल्लेखनीय प्रदर्शन में वृद्धि नहीं देखी, मैं शामिल होने के लिए चिपक गया। इंजीनियरिंग के सिद्धांत होने के सिद्धांत कारण;
- कोड की विश्वसनीयता (सरल हमेशा अधिक विश्वसनीय चतुर चाल है)
- - विकसित करने के लिए
समय कोड के अनुरक्षणीयता (? बाद देखरेख चाल समझ जाएगा)

आप में शामिल हों के विभिन्न संयोजनों का परीक्षण करते हैं और यूनियन के साथ या उसके बिना, मैं आपके प्रदर्शन परिणामों को देखने में बहुत दिलचस्पी लेता हूं।

0

यह हाल ही में जिस तरह से सामना करना पड़ा, यह एक समान समस्या है। मुझे उन पंक्तियों से चयन करने की आवश्यकता थी जो प्राथमिक पंक्तियों की एक बड़ी सूची को छेड़छाड़ करते थे। प्रश्न यह था कि एसक्यूएल सर्वर को चाबियों की बड़ी सूची को एक ऐसे रूप में प्रभावी ढंग से कैसे भेजा जाए जो उपयोग करने के लिए तेज़ और प्रभावशाली है।

इस प्रकार की स्थिति के लिए वास्तव में क्या काम करता है एक्सएमएल डेटा प्रकार है। यदि आप संग्रहीत प्रक्रिया बनाते हैं जो एक्सएमएल प्रकार के एक पैरामीटर लेता है, तो आप इनपुट को एक्सएमएल खंड में पूर्व-स्वरूपित कर सकते हैं। उदाहरण के लिए, मान लीजिए कि एक्सएमएल टुकड़ा इस तरह दिखेगा करते हैं:

<a> 
    <b>1</b> 
    <b>3</b> 
    <b>7</b> 
    <b>14</b> 
    <b>147</b> 
</a> 

मैं तत्वों लघु नाम दिया था ("एक" और "बी"), क्योंकि एक लंबे समय तक नाम ग्राहक से करने के लिए प्रसारित करने के लिए और अधिक बाइट्स का मतलब होगा एसक्यूएल सर्वर। यहाँ कैसे आप एक रिकॉर्ड सेट के रूप में "बी" तत्वों की सभी सामग्री का चयन होता है:

declare @x xml 
set @x = '<a><b>1</b><b>3</b><b>7</b><b>14</b><b>147</b></a>' 
select t.item.value('.', 'int') from @x.nodes('//a/b') as t(item) 

हालांकि वाक्य रचना गुप्त है, एक्सएमएल प्रकार सिर्फ एक मेज की तरह पूछे जा सकता है। अब आपको देखना चाहिए कि यह कहां जा रहा है। हम एक मेज की तरह एक्सएमएल प्रकार क्वेरी कर सकते हैं, हम एक और टेबल के साथ कि एक दूसरे को काटना कर सकते हैं:

select * from MyTable where ID in 
    (select t.item.value('.', 'int') from @x.nodes('//a/b') as t(item)) 

या का उपयोग कर एक में शामिल होने के

;with cte as 
    (select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item)) 
select * from MyTable inner join cte on MyTable.ID = cte.ID 

आप दोनों संस्करणों को चलाने के लिए देखने के लिए जो तेजी के लिए किया जाएगा की जरूरत है आपका डेटा। मुझे लगता है कि जॉइन मेरे डेटा के साथ तेजी से काम करता है। यहाँ एक संग्रहीत प्रक्रिया है कि इनपुट के रूप में एक्सएमएल प्रकार लेता है और वापस थूक हमारे चयनित पंक्तियों है:

create procedure MyProc @x xml as 
begin 
    set nocount on 
    ;with cte as 
    (select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item)) 
    select * from MyTable inner join cte on Table.ID = cte.ID 
end 

नई संग्रहीत प्रक्रिया का एक नमूना कॉल:

exec MyProc '<a><b>1</b><b>3</b><b>7</b><b>14</b><b>147</b></a>' 

मैंने यह भी पाया है कि एक XML स्कीमा जोड़ने इनपुट खंड के लिए संग्रहीत प्रक्रिया को थोड़ा तेज़ करने में मदद मिली। मैं यहां एक्सएमएल स्कीमा के विवरण में नहीं जाऊंगा, लेकिन विचार एसक्यूएल को पहले से बताना है कि एक्सएमएल टुकड़ा कैसा दिखता है।

create xml schema collection MyInputSchema as 
    '<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <xsd:element name="a"> 
     <xsd:complexType> 
     <xsd:complexContent> 
      <xsd:restriction base="xsd:anyType"> 
      <xsd:sequence> 
       <xsd:element name="b" type="xsd:integer" maxOccurs="unbounded" /> 
      </xsd:sequence> 
      </xsd:restriction> 
     </xsd:complexContent> 
     </xsd:complexType> 
    </xsd:element> 
    </xsd:schema>' 

अब हम इनपुट के साथ इस स्कीमा हमारे संग्रहीत प्रक्रिया के लिए इस तरह संबद्ध कर सकते हैं: यहाँ कैसे हम इनपुट हमारे स्कीमा करेंगे

create procedure MyProc @x xml(MyInputSchema) as 
begin 
    set nocount on 
    ;with cte as 
    (select ID = t.item.value('.', 'int') from @x.nodes('//a/b') as t(item)) 
    select * from MyTable inner join cte on Table.ID = cte.ID 
end 
जगह में यह सब के साथ

, मैं एक भेजने में सक्षम थे मेरे क्लाइंट मशीन से SQL सर्वर तक 43,016 वर्णों का एक्सएमएल खंड और परिणामस्वरूप बहुत जल्दी परिणाम प्राप्त करें। मैंने कुल 10,000 अनुरोधों के लिए 10 धागे पर 1,000 अनुरोधों का परीक्षण किया। परिणाम प्रति सेकंड संसाधित 72 अनुरोध थे। बेशक आपकी मिलेज आपके हार्डवेयर और सॉफ्टवेयर के आधार पर अलग-अलग हो जाएगी।

नोट: यह कोड SQL 2005 पर काम करता है और 2008 पर भी काम करना चाहिए।

0

आप चुनने के लिए प्राथमिक कुंजी मानों की सूची कैसे निर्धारित करते हैं? मैं सोच रहा हूं कि हमें इस 'अपस्ट्रीम' को देखना चाहिए - क्या कुछ पूर्व प्रश्न या प्रश्न हैं जो आप कुंजी की सूची में पहुंचने के लिए दौड़ चुके हैं? यदि ऐसा है, तो शायद आप उसमें शामिल हो सकते हैं और कुंजी-लुकअप को पूरी तरह से छोड़ सकते हैं।

0

मेरा पहला विचार यह देखना होगा कि आप कुंजी की सूची में कैसे खींच रहे हैं। क्या यह कहीं और पूछताछ से है? यदि हां, तो आप

SELECT * FROM Table WHERE [PrimaryKey] in 
(
    SELECT PrimaryKey from SomeOtherTable where Condition = 'met' 
) 

की कोशिश की है या यदि आपके शर्तें समान तालिका में हैं, यह और भी आसान

SELECT * FROM Table WHERE condition = 'met' 
बेशक

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

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

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