रिकॉर्ड मौजूद है या नहीं यह निर्धारित करने का सबसे तेज़ तरीका


143

जैसा कि शीर्षक से पता चलता है ... मैं यह निर्धारित करने के लिए कम से कम ओवरहेड के साथ सबसे तेज़ तरीका निकालने की कोशिश कर रहा हूं कि क्या कोई रिकॉर्ड किसी तालिका में मौजूद है या नहीं।

नमूना प्रश्न:

SELECT COUNT(*) FROM products WHERE products.id = ?;

    vs

SELECT COUNT(products.id) FROM products WHERE products.id = ?;

    vs

SELECT products.id FROM products WHERE products.id = ?;

कहते हैं कि ?इसके साथ अदला-बदली की गई है 'TB100'... पहले और दूसरे प्रश्न दोनों ही एक ही परिणाम लौटाएंगे ( 1इस बातचीत के लिए ... कहते हैं)। अंतिम क्वेरी 'TB100'अपेक्षा के अनुसार वापस आ जाएगी , या idतालिका में मौजूद नहीं होने पर कुछ भी नहीं।

उद्देश्य यह पता लगाना idहै कि तालिका में है या नहीं। यदि नहीं, तो प्रोग्राम अगले रिकॉर्ड को सम्मिलित करेगा, यदि यह है, तो प्रोग्राम इसे छोड़ देगा या इस प्रश्न के दायरे से बाहर अन्य प्रोग्राम लॉजिक के आधार पर एक UPDATE क्वेरी का प्रदर्शन करेगा।

कौन सा तेज है और कम ओवरहेड है? (यह प्रति कार्यक्रम चलने के हजारों बार दोहराया जाएगा, और दिन में कई बार चलाया जाएगा)।

(जावा से एम $ एसक्यूएल सर्वर के खिलाफ इस क्वेरी को एम $ जेडीबीसी ड्राइवर प्रदान करता है)


1
यह डेटाबेस पर निर्भर हो सकता है। उदाहरण के लिए, Postgres पर गिनती धीमी है।
माइक क्रिस्टेन्सन

क्षमा करें, यह jdbc ड्राइवर के माध्यम से एम $ SQL से बात कर रहा है। मैं अपने ओपी को अपडेट करूंगा।
स्नेकडोक


@ नोकोला मार्कोविनोविक: आप इस मामले में इसका उपयोग कैसे करेंगे?
ज़र्कम्स

5
@zerkms संदर्भ पर निर्भर करता है। यदि संग्रहीत प्रक्रिया में यह होगा if exists(select null from products where id = @id); यदि किसी क्लाइंट द्वारा सीधे कहे जाने वाले क्वेरी में select case when exists (...) then 1 else 0 end
निकोला मार्कोविनोविक

जवाबों:


170

SELECT TOP 1 products.id FROM products WHERE products.id = ?; आपके सभी सुझावों को बेहतर बनाएगा क्योंकि यह पहले रिकॉर्ड को खोजने के बाद निष्पादन को समाप्त कर देगा।


5
क्या पीके (या किसी अन्य अद्वितीय कुंजी) के माध्यम से खोज करने पर ऑप्टिमाइज़र इसे स्वयं नहीं लेता है?
ज़र्क्स

3
उन्होंने कहा कि पीके था, लेकिन अगर ऐसा है तो आशावादी कि खाते में ले जाएगा।
Declan_K

3
@Declan_K: ऐसा लगता है कि मेरा जादू क्षेत्र इस मामले में विफल रहा है और एक स्तंभ जिसका शीर्षक idपीके नहीं है। तो आपकी सलाह पर +1।
ज़र्क

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

3
मुझे लगता है कि हमें इस पर @ nenad-zivkovic जवाब पर विचार करना चाहिए।
Giulio Caccin

192

EXISTS(या NOT EXISTS) विशेष रूप से जाँच के लिए डिज़ाइन किया गया है कि कुछ मौजूद है और इसलिए सबसे अच्छा विकल्प होना चाहिए (और है)। यह पहली पंक्ति पर रुकेगा जो मेल खाता है इसलिए इसे एक TOPखंड की आवश्यकता नहीं है और यह वास्तव में किसी भी डेटा का चयन नहीं करता है, इसलिए स्तंभों के आकार में कोई ओवरहेड नहीं है। आप SELECT *यहां सुरक्षित रूप से उपयोग कर सकते हैं - से अलग नहीं SELECT 1, SELECT NULLया SELECT AnyColumn... (आप यहां तक ​​कि एक अमान्य अभिव्यक्ति का उपयोग कर सकते हैं SELECT 1/0और यह टूट नहीं जाएगा)

IF EXISTS (SELECT * FROM Products WHERE id = ?)
BEGIN
--do what you need if exists
END
ELSE
BEGIN
--do what needs to be done if not
END

इसके लिए पहले SELECT स्टेटमेंट को निष्पादित करना होगा, फिर IF EXISTS स्टेटमेंट को एक्जिक्यूट करना होगा ... अतिरिक्त ओवरहेड और इसलिए अधिक प्रोसेसिंग टाइम?
स्नेकडोक

7
@SnakeDoc नंबर इस तरह से Existsकाम करता है selectकि एक पंक्ति मिलते ही यह बाहर निकल जाता है। इसके अलावा केवल रिकॉर्ड के अस्तित्व को नोट करता है, रिकॉर्ड में वास्तविक मूल्यों को नहीं, डिस्क से पंक्ति को लोड करने की आवश्यकता को सहेजना (खोज मानदंड अनुक्रमित है, निश्चित रूप से)। ओवरहेड के लिए if- आपको इस शून्यकाल के समय को वैसे भी बिताना होगा।
निकोला मार्कोविनोविक

1
@ NikolaMarkovinović दिलचस्प बिंदु। मुझे यकीन नहीं है कि क्या कोई सूचकांक इस क्षेत्र में मौजूद है, और मेरी newbish SQL को पता नहीं है कि कैसे पता लगाना है। मैं JDBC के माध्यम से जावा से इस DB के साथ काम कर रहा हूं और डेटाबेस कहीं दूर एक कोलो में स्थित है। मुझे केवल एक "डेटाबेस सारांश" प्रदान किया गया है, जो कि केवल प्रत्येक तालिका, उनके प्रकार और किसी भी FK या PK's में मौजूद फ़ील्ड का विवरण देता है। क्या यह कुछ बदलता है?
स्नेकडोक

3
@SnakeDoc विदेशी कुंजी और अनुक्रमित सहित तालिका संरचना के बारे में जानने के लिए, sp_help table_name चलाएं । सूचकांक आवश्यक हैं जब यह कई में से कुछ पंक्तियों को पुनः प्राप्त करने की बात आती है, का उपयोग करके select topया जहां से exists; यदि वे मौजूद नहीं हैं तो sql इंजन को टेबल स्कैन करना होगा। यह कम से कम वांछनीय तालिका खोज विकल्प है। यदि आप अनुक्रमणिका बनाने के लिए अधिकृत नहीं हैं, तो आपको यह पता लगाने के लिए तकनीकी कर्मचारियों से संपर्क करना होगा कि क्या वे उन्हें स्वचालित रूप से समायोजित करते हैं या वे आपसे अनुक्रमणिका सुझाने की अपेक्षा करते हैं।
निकोला मार्कोविनोविक

1
@ कोंस्टेंटिन आप कुछ ऐसा कर सकते हैंSELECT CASE WHEN EXISTS(..) THEN 1 ELSE 0 END;
नेनाद

21

कुछ नहीं हरा सकते -

SELECT TOP 1 1 FROM products WHERE id = 'some value';

यदि तालिका में कोई डेटा है, तो आपको यह जानने के लिए गिनने की आवश्यकता नहीं है। और जब आवश्यक न हो तो अन्य का उपयोग न करें।


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

जी हां आप बिल्कुल सही हैं। अलियासिंग बहुत मदद करता है, लेकिन मुझे नहीं लगता कि इससे जुड़ने का उपयोग नहीं करने पर कोई फर्क पड़ता है। इसलिए, मैंने कहा कि यदि आवश्यक न हो तो इसका उपयोग न करें। :) और आप अस्तित्व की जाँच पर यहाँ एक लंबी चर्चा पा सकते हैं । :)
AgentSQL

3
मुझे नहीं पता कि मैंने इस पद को क्यों ग्रहण किया aliasing। सही शब्द है qualifying। यहाँ एलेक्स कुज़नेत्ज़ोव द्वारा लंबी व्याख्या की गई है । एकल तालिका प्रश्नों के बारे में - यह अब एकल तालिका है । लेकिन बाद में, जब बग की खोज की जाती है और आप बाढ़ को पकड़ने की कोशिश कर रहे होते हैं, तो ग्राहक घबरा जाता है, आप त्रुटि संदेश का सामना करने के लिए सिर्फ एक और तालिका में शामिल होते हैं - आसानी से सुधारे जाने योग्य संदेश, लेकिन इस पसीने वाले क्षण में नहीं, एक छोटे से स्ट्रोक - और आप सही करते हैं एक स्तंभ को छोड़ने के लिए याद रखने में त्रुटि ...
निकोला मार्कोविनोविक

1
अब इसे अनदेखा नहीं कर सकते। धन्यवाद!! :)
AgentSQL

15
SELECT CASE WHEN EXISTS (SELECT TOP 1 *
                         FROM dbo.[YourTable] 
                         WHERE [YourColumn] = [YourValue]) 
            THEN CAST (1 AS BIT) 
            ELSE CAST (0 AS BIT) END

यह दृष्टिकोण आपके लिए एक बूलियन देता है।


1
संभवत: शीर्ष स्टेटमेंट और * स्टेटमेंट को थोड़ा और तेज कर सकता है, क्योंकि एक्ज़िस्ट एक बार रिकॉर्ड करने के बाद बाहर निकल जाएगा, इसलिए कुछ इस तरह से: सिलेक्ट केस WHEN EXISTS (सिलेक्ट 1 फ्रॉम द्बो। [YourTable] WHERE [YourColumn]] = [YourValue]) तब कास्ट (1 AS BIT) ELSE CAST (0 AS BIT) END
स्टीफन ज्वोनर

यह सुझाव इस बात का उल्लेख करने में विफल रहता है कि यह SQL सर्वर के अंदर मौजूद / मौजूद न होने वाले बयानों से अधिक तेज़ क्यों होगा। किसी भी बेंचमार्किंग के बिना मुझे विश्वास करना मुश्किल होगा कि एक केस स्टेटमेंट तत्काल सच / झूठी प्रतिक्रिया की तुलना में तेजी से परिणाम देगा।
Bonez024

8

आप भी उपयोग कर सकते हैं

 If EXISTS (SELECT 1 FROM dbo.T1 WHERE T1.Name='Scot')
    BEGIN
         --<Do something>
    END 

ELSE    
     BEGIN
       --<Do something>
     END

7

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

SELECT CASE WHEN EXISTS (SELECT 1 
                     FROM dbo.[YourTable] WITH (NOLOCK)
                     WHERE [YourColumn] = [YourValue]) 
        THEN CAST (1 AS BIT) 
        ELSE CAST (0 AS BIT) END

3
SELECT COUNT(*) FROM products WHERE products.id = ?;

यह क्रॉस रिलेशनल डेटाबेस सॉल्यूशन है जो सभी डेटाबेस में काम करता है।


7
हालाँकि, आप db को सभी रिकॉर्ड्स पर लूप करने के लिए मजबूर करते हैं, बड़ी टेबलों पर बहुत धीमी
amd

@amd केयर करने के लिए क्यों समझा?
उमनीबॉय

@ आपकी टिप्पणी से पूरी समझ में आता है। यह क्वेरी किसी भी तरह से सभी की तुलना में अधिक है।
15

1

नीचे यह निर्धारित करने का सबसे सरल और तेज़ तरीका है कि क्या कोई रिकॉर्ड डेटाबेस में मौजूद है या नहीं अच्छी बात यह है कि यह सभी संबंधपरक डीबी में काम करता है

SELECT distinct 1 products.id FROM products WHERE products.id = ?;

0
create or replace procedure ex(j in number) as
i number;
begin
select id into i from student where id=j;
if i is not null then
dbms_output.put_line('exists');
end if;
exception
   when no_data_found then
        dbms_output.put_line(i||' does not exists');

end;

2
संभवतः आपका कोड बहुत अच्छा काम करता है, लेकिन बेहतर होगा कि आप कुछ अतिरिक्त जानकारी जोड़ें, ताकि बेहतर समझ में आ सके।
इदमन

0

मैंने अतीत में इसका उपयोग किया है और यह देखने के लिए पूर्ण तालिका स्कैन की आवश्यकता नहीं है कि क्या कुछ मौजूद है। यह सुपर फास्ट है ...

UPDATE TableName SET column=value WHERE column=value
IF @@ROWCOUNT=0
BEGIN
     --Do work
END             

0

MySQL या Oracle पृष्ठभूमि से इस पर ठोकर खाने वालों के लिए - MySQL सीमित संख्या के रिकॉर्ड का चयन करने के लिए LIMIT क्लॉज का समर्थन करता है, जबकि Oracle ROWNUM का उपयोग करता है।

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