أفضل طريقة لاختبار إذا كان صف موجود في جدول MySQL

StackOverflow https://stackoverflow.com/questions/1676551

  •  16-09-2019
  •  | 
  •  

سؤال

أحاول معرفة ما إذا كان صف موجود في طاولة. باستخدام MySQL، هل من الأفضل القيام باستعلام مثل هذا:

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

والتحقق لمعرفة ما إذا كان المجموع غير صفر أو هل من الأفضل القيام باستعلام مثل هذا:

SELECT * FROM table1 WHERE ... LIMIT 1

والتحقق لمعرفة ما إذا تم إرجاع أي صفوف؟

في كلا الاستعلامات، يستخدم جملة المكان الفهرس.

هل كانت مفيدة؟

المحلول

يمكنك أيضا محاولة EXISTS:

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

و وثائق, ، تستطيع SELECT اى شى.

تقليديا، يبدأ SPAQUERY في SELECT *، ولكن قد يبدأ في تحديد 5 أو حدد Column1 أو أي شيء على الإطلاق. يتجاهل MySQL القائمة المختارة في مثل هذه الاستعمار الاستقبال، لذلك لا فرق.

نصائح أخرى

لقد قدمت بعض الأبحاث حول هذا الموضوع مؤخرا. الطريقة لتنفيذها يجب أن تكون مختلفة إذا كان الحقل حقل نصي، حقل غير فريد.

لقد قمت ببعض الاختبارات مع حقل نص. النظر في حقيقة أن لدينا جدول مع إدخالات 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.028197050095S.
  • 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.04489898681640606s.

ولكن الآن، مع حقل 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.00023889541625977S.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1) : 0.00020313262939453s. (أسرع)

مثال قصير عن إجابة @ 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)

في بحثي، يمكنني العثور على النتيجة في الحصول على السرعة التالية.

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) 

أشعر أنه يستحق الإشارة، على الرغم من أنه تم لمسه في التعليقات، إلا أنه في هذا الموقف:

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 التفاف إذا كنت بحاجة إلى إرجاع صريح عند عدم تطابق الصفوف.

أقترح عليك عدم استخدامها Count لأن العد دائما يجعل الأحمال الإضافية لاستخدام DB SELECT 1 ويعود 1 إذا كان السجل الخاص بك هناك خلاف ذلك، فسيتم إرجاع NULL ويمكنك التعامل معها.

في بعض الأحيان يكون مفيدا للغاية للحصول على المفتاح الأساسي لزيادة السيارات (id) من الصف إذا كان موجودا و 0 إذا لم يفعل ذلك.

إليك كيف يمكن القيام بذلك في استعلام واحد:

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

سأذهب مع COUNT(1). وبعد انها أسرع من COUNT(*) لان COUNT(*) اختبارات لمعرفة ما إذا كان عمود واحد على الأقل في هذا الصف هو! = NULL. لا تحتاج ذلك، خاصة لأن لديك بالفعل حالة في مكانها ( WHERE بند). COUNT(1) بدلا من ذلك اختبارات صلاحية 1, ، والتي هي دائما صالحة وتستغرق وقتا أقل بكثير لاختبارها.

أ عدد الاستعلام أسرع، على الرغم من أنه ربما ليس بشكل ملحوظ، ولكن فيما يتعلق بالنتيجة المرجوة، يجب أن يكون كلاهما كافيا.

بالنسبة للجداول غير InnoDB، يمكنك أيضا استخدام جداول مخطط المعلومات:

http://dev.mysql.com/doc/refman/5.1/en/Tables-Table.html.

أو يمكنك إدراج جزء SQL الخام إلى الشروط لذلك لدي"الشروط" => صفيف (عضو ". لم يكن في (حدد عضوية. member_id من العضويات كعضوية))

COUNT(*) يتم تحسينها في MySQL، لذلك من المحتمل أن يكون الاستعلام السابق بشكل أسرع، بشكل عام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top