एक परीक्षण का सबसे अच्छा तरीका अगर एक पंक्ति MySQL तालिका में मौजूद है


337

मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या तालिका में कोई पंक्ति मौजूद है। MySQL का उपयोग करना, क्या इस तरह से क्वेरी करना बेहतर है:

SELECT COUNT(*) AS total FROM table1 WHERE ...

और यह देखने के लिए जांचें कि क्या कुल गैर-शून्य है या इस तरह से क्वेरी करना बेहतर है:

SELECT * FROM table1 WHERE ... LIMIT 1

और यह देखने के लिए जांचें कि क्या कोई पंक्तियाँ वापस आ गईं?

दोनों प्रश्नों में, WHERE क्लॉज एक इंडेक्स का उपयोग करता है।

जवाबों:


470

आप भी कोशिश कर सकते हैं EXISTS:

SELECT EXISTS(SELECT * FROM table1 WHERE ...)

और प्रलेखन के अनुसार , आप SELECTकुछ भी कर सकते हैं ।

परंपरागत रूप से, एक EXISTS सबक्लेरी SELECT * से शुरू होती है, लेकिन यह SELECT 5 या SELECT column1 या किसी भी चीज से शुरू हो सकती है। MySQL इस तरह के एक सबक्वेरी में SELECT लिस्ट को अनदेखा करता है, इसलिए इससे कोई फर्क नहीं पड़ता।


30
के साथ टेस्ट करें ...EXISTS( SELECT 1/0 FROM someothertable)। SQL सर्वर और ओरेकल के लिए - यह *, 1 या NULL का उपयोग करने के लिए कोई फर्क नहीं पड़ता है क्योंकि EXISTS केवल एक बूलियन के लिए परीक्षण करता है जो कि 1+ मानदंडों के आधार पर मिलान करता है।
ओएमजी पॉनीज़

77
दोस्तों, यह सही है, इस उत्तर, 2 पैरा, "पारंपरिक रूप से, इस प्रश्न में लिंक किए गए दस्तावेज़ में कहा गया है, एक EXISTS सबक्लेरी SELECT * से शुरू होती है, लेकिन यह SELECT 5 या SELECT column1 या किसी भी चीज़ के साथ शुरू हो सकता है। MySQL ऐसे में SELECT लिस्ट को अनदेखा करता है। एक उपशम, इसलिए इससे कोई फर्क नहीं पड़ता। "
एमपीन

12
@ क्रिसहॉम्पसन: जब स्टेटमेंट निष्पादित किया जाता है तो क्या होता है? मेरा मतलब है कि परिणाम सेट में क्या है?
अश्विन

13
@ अश्विन, इसमें 0 (मौजूद नहीं) या 1 (मौजूद) है।
फ़ेडरक्वी 'SO रोकना नुकसानदेह'

10
मुझे लगता है कि आपकी क्वेरी शानदार है, मैंने परीक्षण किया, और यह क्वेरी SELECT 1 FROM table1 WHERE col = $var LIMIT 1आपकी क्वेरी से अधिक तेज़ है। तो आपकी क्वेरी का क्या फायदा है?
शफीज़ादेह

182

मैंने हाल ही में इस विषय पर कुछ शोध किए हैं। इसे लागू करने का तरीका अलग होना चाहिए यदि फ़ील्ड एक TEXT फ़ील्ड है, एक गैर अद्वितीय फ़ील्ड है।

मैंने एक पाठ क्षेत्र के साथ कुछ परीक्षण किए हैं। इस तथ्य को ध्यान में रखते हुए कि हमारे पास 1M प्रविष्टियों वाली एक तालिका है। 37 प्रविष्टियाँ 'कुछ' के बराबर हैं:

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1साथ mysql_num_rows() : 0.039061069488525s (और तेज)
  • SELECT count(*) as count FROM test WHERE text LIKE '%something% : 16.028197050095
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%') : 0.87045907974243s
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1) : 0.044898986816406s

लेकिन अब, BIGINT PK फ़ील्ड के साथ, केवल एक प्रविष्टि '321321' के बराबर है:

  • SELECT * FROM test2 WHERE id ='321321' LIMIT 1के साथ mysql_num_rows() : 0.0089840888977051s।
  • SELECT count(*) as count FROM test2 WHERE id ='321321' : 0.00033879280090332s
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321') : 0.00023889541625977
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1): 0.00020313262939453s (और तेज)

2
अतिरिक्त उत्तर के लिए धन्यवाद। क्या आपको TEXT क्षेत्र के लिए दो सबसे तेज़ विकल्पों के बीच के समय में अंतर पता चला है जो कि काफी सुसंगत है? अंतर बड़ा नहीं लगता है, और SELECT EXISTS (Select 1 ... LIMIT 1) का उपयोग करना दोनों ही मामलों में बहुत अच्छा लगता है।
बर्नार्ड चेन

1
आप सही हैं, अंतर पाठ क्षेत्र से संबंधित अन्य परिणामों के बारे में इतना महत्वपूर्ण नहीं है। फिर भी, शायद क्वेरी का उपयोग बेहतर होगाSELECT 1 FROM test WHERE texte LIKE '%something%' LIMIT 1
लॉरेंट डब्ल्यू

मैंने mysql पर कोशिश की और आपके द्वारा उपयोग किए जाने के मामले में select 1 ... limit 1, चयन के साथ घेरना बेकार है
Adrien Horgnies

4
@LittleNooby में अंतर है। SELECT EXISTS ... सही और गलत मूल्य (1 या 0) देता है, जबकि SELECT 1 ... 1 या खाली देता है। आपकी स्थिति के आधार पर, झूठे मूल्य और खाली सेट के बीच सूक्ष्म अंतर हैं।
क्विकपिक

@LittleNooby एक उत्कृष्ट बिंदु बनाता है, जिसे अनदेखा करना आसान है। ऊपर दिए गए समय परीक्षणों में गुम है SELECT 1 FROM test WHERE ..., इसके SELECT EXISTSआसपास नहीं है। संभवत: इस तरह से तेजी से एक बाल है।
टूलमेकरसेव

27

@ ChrisThompson के उत्तर का एक छोटा उदाहरण

उदाहरण:

mysql> SELECT * FROM table_1;
+----+--------+
| id | col1   |
+----+--------+
|  1 | foo    |
|  2 | bar    |
|  3 | foobar |
+----+--------+
3 rows in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 1) |
+--------------------------------------------+
|                                          1 |
+--------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 9);
+--------------------------------------------+
| EXISTS(SELECT 1 FROM table_1 WHERE id = 9) |
+--------------------------------------------+
|                                          0 |
+--------------------------------------------+
1 row in set (0.00 sec)

एक उपनाम का उपयोग करना:

mysql> SELECT EXISTS(SELECT 1 FROM table_1 WHERE id = 1) AS mycheck;
+---------+
| mycheck |
+---------+
|       1 |
+---------+
1 row in set (0.00 sec)

18

अपने शोध में, मैं निम्नलिखित गति पर परिणाम प्राप्त कर सकता हूं।

select * from table where condition=value
(1 total, Query took 0.0052 sec)

select exists(select * from table where condition=value)
(1 total, Query took 0.0008 sec)

select count(*) from table where condition=value limit 1) 
(1 total, Query took 0.0007 sec)

select exists(select * from table where condition=value limit 1)
(1 total, Query took 0.0006 sec) 

12

मुझे लगता है कि यह इंगित करने लायक है, हालांकि इसे टिप्पणियों में छुआ गया था, इस स्थिति में:

SELECT 1 FROM my_table WHERE *indexed_condition* LIMIT 1

से बेहतर है:

SELECT * FROM my_table WHERE *indexed_condition* LIMIT 1

ऐसा इसलिए है क्योंकि पहली क्वेरी को सूचकांक द्वारा संतुष्ट किया जा सकता है, जबकि दूसरी के लिए पंक्ति देखने की आवश्यकता होती है (जब तक कि तालिका के सभी कॉलम उपयोग किए गए सूचकांक में न हों)।

LIMITक्लॉज जोड़ने से इंजन किसी भी पंक्ति को खोजने के बाद बंद हो जाता है।

पहली क्वेरी के लिए तुलनीय होना चाहिए:

SELECT EXISTS(SELECT * FROM my_table WHERE *indexed_condition*)

जो इंजन को एक ही संकेत भेजता है (1 / * यहां कोई फर्क नहीं पड़ता), लेकिन मैं अभी भी 1 लिखूंगा जब आदत को मजबूत करने के लिए EXISTS:

SELECT EXISTS(SELECT 1 FROM my_table WHERE *indexed_condition*)

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


4

आपको उपयोग न करने का सुझाव दें Countक्योंकि गणना हमेशा db उपयोग के लिए अतिरिक्त भार बनाती है SELECT 1और यह 1 वापस आती है यदि आपका रिकॉर्ड वहीं है अन्यथा यह अशक्त है और आप इसे संभाल सकते हैं।


2

एक COUNT क्वेरी तेज़ है, हालाँकि शायद ध्यान देने योग्य नहीं है, लेकिन जहाँ तक वांछित परिणाम मिल रहा है, दोनों पर्याप्त होना चाहिए।


4
हालांकि यह डीबी विशिष्ट है। COgUNT (*) को PostgreSQL में धीमा जाना जाता है। बेहतर होगा कि आप पीके कॉलम का चयन करें और देखें कि क्या यह किसी पंक्तियों को लौटाता है।
बालुसक

3
COUNT (*) InnoDB में धीमा है, हालांकि
विल

2

idयदि यह मौजूद है और 0यदि ऐसा नहीं है तो कई बार पंक्ति की ऑटो इंक्रीमेंट प्राइमरी कुंजी ( ) प्राप्त करना काफी आसान है ।

यहां बताया गया है कि यह एक ही क्वेरी में कैसे किया जा सकता है:

SELECT IFNULL(`id`, COUNT(*)) FROM WHERE ...

सिर्फ IFNULL(id, 0)यहाँ के बजाय का उपयोग क्यों नहीं COUNT(*)?
एथन होहेंस


-1

मैं साथ चलूँगा COUNT(1)। यह देखने की तुलना में तेज़ है COUNT(*)क्योंकि यह COUNT(*)देखने के लिए कि उस पंक्ति में कम से कम एक स्तंभ है! = NULL। आपको इसकी आवश्यकता नहीं है, खासकर क्योंकि आपके पास पहले से ही एक शर्त है ( WHEREखंड)। COUNT(1)इसके बजाय की वैधता का परीक्षण करता है 1, जो हमेशा मान्य होता है और परीक्षण के लिए बहुत कम समय लगता है।


8
-1 यह गलत है। COUNT (*) कॉलम मानों को नहीं देखता है - यह केवल पंक्तियों की संख्या गिनता है। मेरा उत्तर यहाँ देखें: stackoverflow.com/questions/2876909/…
मार्क बायर्स

6
COUNT () EXISTS की तुलना में बहुत धीमा है क्योंकि EXISTS पहली बार एक पंक्ति में आने पर वापस लौट सकता है
Will

-1

या आप शर्तों के लिए कच्चे sql भाग सम्मिलित कर सकते हैं, इसलिए मेरे पास 'स्थितियां' => सरणी ('सदस्‍यता नहीं है (सदस्‍यता के रूप में चयन करें।


-2

COUNT(*) MySQL में अनुकूलित हैं, इसलिए पूर्व क्वेरी आमतौर पर तेज होने की संभावना है, आम तौर पर बोल रहा हूं।


2
क्या आप उस अनुकूलन का जिक्र कर रहे हैं जो MyISAM में पूरी तालिका के लिए गणना का चयन करने के लिए है? मुझे नहीं लगता कि अगर वहाँ एक शर्त थी तो मदद की।
बर्नार्ड चेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.