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

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

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

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

SELECT * FROM table1 WHERE ... LIMIT 1

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

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

Ответ 1

Вы также можете попробовать EXISTS:

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

и в документации вы можете SELECT что угодно.

Традиционно подзапрос EXISTS начинается с SELECT *, но он может начать с SELECT 5 или SELECT column1 или чего-либо еще. MySQL игнорирует список SELECT в таком подзапросе, поэтому это не имеет значения.

Ответ 2

Недавно я провел несколько исследований по этому вопросу. Способ реализовать его должен быть другим, если поле является полем 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.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.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.00023889541625977s.
  • SELECT EXISTS(SELECT 1 FROM test2 WHERE id ='321321' LIMIT 1): 0.00020313262939453s. (БЫСТРЕЕ)

Ответ 3

Краткий пример ответа @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)

Ответ 4

В моих исследованиях я могу найти результат, достигающий следующей скорости.

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) 

Ответ 5

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

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 если вам требуется явный возврат, если ни одна строка не совпадает.

Ответ 6

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

Ответ 7

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

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

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

Ответ 8

Производительность также зависит от ваших табличных индексов. Иногда лучше использовать старые способы с правильным индексом таблицы:

SELECT COUNT(field) FROM table WHERE field = 'something' LIMIT 1  

Введите индекс "my_index" в поле "<" >

Объяснение будет выглядеть следующим образом:

id select_type table  type   possible_keys key       key_len  ref   rows Extra
1  SIMPLE      table  ref    my_index      my_index  4        const 1  Using index

Ответ 9

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

Ответ 10

Я бы пошел с COUNT(1). Это быстрее, чем COUNT(*), потому что COUNT(*) проверяет, есть ли хотя бы один столбец в этой строке!= NULL. Вам это не нужно, особенно потому, что у вас уже есть условие (предложение WHERE). COUNT(1) вместо этого проверяет достоверность 1, которая всегда действительна и требует гораздо меньше времени для тестирования.

Ответ 12

Или вы можете вставить исходную sql-часть в условия так что я 'conditions' = > array ('Member.id NOT IN (SELECT Membership.member_id FROM членство AS членство)')

Ответ 13

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