Лучший способ проверить, существует ли строка в таблице 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
, которая всегда действительна и требует гораздо меньше времени для тестирования.
Ответ 11
Для таблиц non-InnoDB вы также можете использовать таблицы информационных схем:
http://dev.mysql.com/doc/refman/5.1/en/tables-table.html
Ответ 12
Или вы можете вставить исходную sql-часть в условия
так что я
'conditions' = > array ('Member.id NOT IN (SELECT Membership.member_id FROM членство AS членство)')
Ответ 13
COUNT(*)
оптимизированы в MySQL, поэтому первый запрос, вероятно, будет быстрее, вообще говоря.