Лучший способ проверить, существует ли строка в таблице 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 графа запрос быстрее, хотя, возможно, не заметно, но что касается получения желаемого результата, обоих должно быть достаточно.
или вы можете вставить необработанную часть sql в условия так у меня 'conditions' =>array ('Member.id NOT IN (выберите членство.member_id из членства в качестве членства)')