2011-05-02 20 views
8

के लिए जांच करते समय सर्वश्रेष्ठ स्व-तकनीक तकनीक में शामिल हों, मैं उत्पादन में मौजूद एक क्वेरी को अनुकूलित करने की कोशिश कर रहा हूं जो लंबे समय से ले रहा है। लक्ष्य मिलान मूल्य मान मानदंडों के आधार पर डुप्लिकेट रिकॉर्ड ढूंढना और फिर उन्हें हटाना है। वर्तमान क्वेरी t1.col1 = t2.col1 पर आंतरिक जुड़ने के माध्यम से स्वयं को शामिल करने का उपयोग करती है, फिर मानों की जांच करने के लिए एक खंड।डुप्लीकेट

select * from table t1 
inner join table t2 on t1.col1 = t2.col1 
where t1.col2 = t2.col2 ... 

ऐसा करने का बेहतर तरीका क्या होगा? या यह इंडेक्स पर आधारित सभी समान है? शायद

select * from table t1, table t2 
where t1.col1 = t2.col1, t2.col2 = t2.col2 ... 

इस तालिका में 100 मीटर + पंक्तियां हैं।

एमएस एसक्यूएल, एसक्यूएल सर्वर 2008 एंटरप्राइज़

select distinct t2.id 
    from table1 t1 with (nolock) 
    inner join table1 t2 with (nolock) on t1.ckid=t2.ckid 
    left join table2 t3 on t1.cid = t3.cid and t1.typeid = t3.typeid 
    where 
    t2.id > @Max_id and 
    t2.timestamp > t1.timestamp and 
    t2.rid = 2 and 
    isnull(t1.col1,'') = isnull(t2.col1,'') and 
    isnull(t1.cid,-1) = isnull(t2.cid,-1) and 
    isnull(t1.rid,-1) = isnull(t2.rid,-1)and 
    isnull(t1.typeid,-1) = isnull(t2.typeid,-1) and 
    isnull(t1.cktypeid,-1) = isnull(t2.cktypeid,-1) and 
    isnull(t1.oid,'') = isnull(t2.oid,'') and 
    isnull(t1.stypeid,-1) = isnull(t2.stypeid,-1) 

    and (
      (
       t3.uniqueoid = 1 
      ) 
      or 
      (
       t3.uniqueoid is null and 
       isnull(t1.col1,'') = isnull(t2.col1,'') and 
       isnull(t1.col2,'') = isnull(t2.col2,'') and 
       isnull(t1.rdid,-1) = isnull(t2.rdid,-1) and 
       isnull(t1.stid,-1) = isnull(t2.stid,-1) and 
       isnull(t1.huaid,-1) = isnull(t2.huaid,-1) and 
       isnull(t1.lpid,-1) = isnull(t2.lpid,-1) and 
       isnull(t1.col3,-1) = isnull(t2.col3,-1) 
      ) 
    ) 
+0

एमएस एसक्यूएल? यदि हां, तो SQL सर्वर का कौन सा संस्करण? –

+0

@ ब्रूनो क्षमा करें, मैंने प्रश्न और टैग अपडेट किया है –

+0

@ मिच नहीं, यह एक ही तालिका में शामिल होने वाली एक तालिका है। यह कैसे शामिल नहीं है? –

उत्तर

13

क्यों आत्म में शामिल होने: यह एक समग्र सवाल है।

आशा है कि आप col1, col2, पर एक सूचकांक है ...

--DELETE table 
--WHERE KeyCol NOT IN (
select 
    MIN(KeyCol) AS RowToKeep, 
    col1, col2, 
from 
    table 
GROUP BY 
    col12, col2 
HAVING 
    COUNT(*) > 1 
--) 

बहरहाल, यह कुछ समय लगेगा। look at bulk delete techniques

+0

+1 - शायद सबसे तेजी से चलने वाला उत्तर – JNK

+0

पोस्ट किया गया है मैंने क्वेरी के साथ अपना प्रश्न अपडेट किया है (कॉलम/तालिका नाम बदल गए हैं)। क्या आपका सुझाव अभी भी काम करेगा? –

+0

@ टाइटन 278: करना चाहिए। ISNULL के साथ ग्रुप करने की आवश्यकता नहीं है और आपको टेबल 2/टी 3 चेक के लिए EXISTS का उपयोग करना चाहिए (DISTINCT के उपयोग से बचाता है) – gbn

1

आप ROW_NUMBER() एक तालिका में डुप्लिकेट पंक्तियों को खोजने के लिए उपयोग कर सकते हैं।

आप जांच here

+0

ओह। टेबल के इस आकार पर बुरा होने जा रहा है। मैं एक कुल – gbn

+0

हां का उपयोग करता हूं, लेकिन यदि पंक्तियां बिल्कुल वही हैं, तो मुझे नहीं लगता कि कुल मिलाकर, कम से कम एक सरल तरीके से काम करेगा। –

+0

आप कोई पीके मानते हैं: आप पीके के बाहर डुप्लिकेट कर सकते हैं। ओपी के अपडेटेड शो में एक पीके है लेकिन अभी भी डुप्लिकेट है। यह इस तथ्य को नहीं बदलेगा कि ROW_NUMBER कुत्ते की तरह दौड़ जाएगा। – gbn

0

डुप्लिकेट पता लगाने के लिए कर सकते हैं, तो आप में शामिल होने की जरूरत नहीं है:

SELECT col1, col2 
FROM table 
GROUP BY col1, col2 
HAVING COUNT(*) > 1 

बहुत तेजी से होना चाहिए।

+0

एक 100 मिलियन पंक्ति तालिका पर? मुझे ऐसा नहीं लगता! –

+0

@ मिच गेहूं: कोई भी तकनीक 100 मीटर + पंक्तियों पर कुत्ते की तरह दौड़ जाएगी ... विशेष रूप से ROW_NUMBER आधारित फ्यूशनशन – gbn

+2

@ मिच: व्यावहारिक प्रश्न यह नहीं है, "क्या यह लिखने का कोई तरीका है जो अंडेक्स x सेकेंड में चलाएगा?" लेकिन "वांछित परिणाम देने के लिए सबसे तेज़ प्रश्न क्या है।" – Jay

1

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

और, वैसे, यह काम नहीं करेगा। आपके पास कम से कम एक फ़ील्ड होना चाहिए जो भिन्न नहीं है या प्रत्येक रिकॉर्ड स्वयं मेल खाता है।

तुम कुछ अधिक की तरह की कोशिश करना चाहते हो सकता है:

select col1, col2, col3 
from table 
group by col1, col2, col3 
having count(*)>1 
1

100 मीटर + पंक्तियों के साथ तालिका के लिए, GROUPBY फ़ंक्शंस का उपयोग करके और होल्डिंग टेबल का उपयोग करके अनुकूलित किया जाएगा। भले ही यह चार प्रश्नों में अनुवाद करता है।

कदम 1: एक होल्डिंग कुंजी बनाने:

SELECT col1, col2, col3=count(*) 
INTO holdkey 
FROM t1 
GROUP BY col1, col2 
HAVING count(*) > 1 

कदम 2: holddups में सभी डुप्लिकेट प्रविष्टियों पुश। इस चरण 4.

SELECT DISTINCT t1.* 
INTO holddups 
FROM t1, holdkey 
WHERE t1.col1 = holdkey.col1 
AND t1.col2 = holdkey.col2 

कदम 3 के लिए आवश्यक है: मूल तालिका से डुप्लिकेट पंक्तियों को हटा दें।

DELETE t1 
FROM t1, holdkey 
WHERE t1.col1 = holdkey.col1 
AND t1.col2 = holdkey.col2 

चरण 4: अद्वितीय पंक्तियां मूल तालिका में वापस रखो।उदाहरण के लिए:

INSERT t1 SELECT * FROM holddups 
0

मेरे अनुभव में, एसक्यूएल सर्वर प्रदर्शन वास्तव में OR शर्तों के साथ बुरा है। शायद यह स्वयं शामिल नहीं है लेकिन तालिका 3 के साथ जो खराब प्रदर्शन का कारण बनता है। लेकिन योजना को देखे बिना, मुझे यकीन नहीं होगा।

इस मामले में, यह दो में अपनी क्वेरी विभाजित करने के लिए मदद कर सकता है: जहां हालत t3.uniqueoid = 1 और एक table3 पर अन्य शर्तों को के लिए एक कहां हालत, और फिर साथ UNION ALL का उपयोग दूसरे के साथ संलग्न करने के लिए एक एक।

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