Лучший способ проверить, существует ли строка в таблице MySQL

Я пытаюсь выяснить, существует ли строка в таблице. Используя MySQL, лучше ли делать такой запрос:

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

и проверьте, не является ли сумма ненулевой или лучше сделать такой запрос:

SELECT * FROM table1 WHERE ... LIMIT 1

и проверьте, были ли возвращены какие-либо строки?

в обоих запросах предложение WHERE использует индекс.

12 ответов


вы также можете попробовать использовать

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

per документация

в комментарии ниже:

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

недавно я провел некоторые исследования по этому вопросу. Способ его реализации должен быть другим, если поле является текстовым полем, не уникальным полем.

я сделал несколько тестов с текстовым полем. Учитывая тот факт, что у нас есть таблица с 1м записей. 37 записей равны "что-то":

  • SELECT * FROM test WHERE texte LIKE '%something%' LIMIT 1 с mysql_num_rows() : 0.039061069488525 С. (быстрее)
  • SELECT count(*) as count FROM test WHERE text LIKE '%something% : 16.028197050095 ы.
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%') : 0.87045907974243 ы.
  • SELECT EXISTS(SELECT 1 FROM test WHERE text LIKE '%something%' LIMIT 1): 0.044898986816406 s.

но теперь, с полем BIGINT PK, только одна запись равна "321321":

  • SELECT * FROM test2 WHERE id ='321321' LIMIT 1 С mysql_num_rows(): 0.0089840888977051 s.
  • SELECT count(*) as count FROM test2 WHERE id ='321321': 0.00033879280090332 s.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321'): 0.00023889541625977 s.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1) : 0.00020313262939453 С. (быстрее)

краткий пример ответа @Christhompson's

пример:

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) 

предлагаю вам не использовать Count потому что count всегда делает дополнительные нагрузки для использования db SELECT 1 и это возвращает 1 если ваша запись прямо там, иначе она возвращает null, и вы можете ее обработать.


иногда очень удобно получить первичный ключ автоматического приращения (id) строки, если она существует и 0 если это не так.

вот как это можно сделать в один запрос:

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

Я чувствую, что стоит отметить, хотя это было затронуто в комментариях, что в этой ситуации:

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, чтобы удалить любые сомнения:

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

может иметь смысл добавить EXISTS упаковка, если вам требуется явное возвращение, когда строки не совпадают.


Я бы пошел с COUNT(1). Это быстрее, чем COUNT(*), потому что COUNT(*) тесты, чтобы увидеть, если хотя бы один столбец в этой строке != НЕДЕЙСТВИТЕЛЬНЫЙ. Вам это не нужно, тем более, что у вас уже есть условие на месте (WHERE предложения). COUNT(1) вместо этого проверяет действительность 1, который всегда действителен и занимает намного меньше времени для тестирования.


A графа запрос быстрее, хотя, возможно, не заметно, но что касается получения желаемого результата, обоих должно быть достаточно.


для таблиц, отличных от InnoDB, вы также можете использовать таблицы информационной схемы:

http://dev.mysql.com/doc/refman/5.1/en/tables-table.html


или вы можете вставить необработанную часть sql в условия так у меня 'conditions' =>array ('Member.id NOT IN (выберите членство.member_id из членства в качестве членства)')


COUNT(*) оптимизированы в MySQL, поэтому первый запрос, скорее всего, будет быстрее, вообще говоря.