MySQL: SELECT (x) ГДЕ ПРОТИВ СЧЕТА ГДЕ? - PullRequest
2 голосов
/ 21 февраля 2010

Это будет один из тех вопросов, но мне нужно его задать.

У меня есть большая таблица, которая может иметь или не иметь одну уникальную строку. Поэтому мне нужен запрос MySQL, который просто скажет мне ИСТИНА или ЛОЖЬ.

Насколько я знаю, я вижу два варианта (псевдокод):

[id = первичный ключ]

ВАРИАНТ 1:

SELECT id FROM table WHERE x=1 LIMIT 1
... and then determine in PHP whether a result was returned.

ВАРИАНТ 2:

SELECT COUNT(id) FROM table WHERE x=1
... and then just use the count.

Является ли какой-либо из них предпочтительным по какой-либо причине, или, возможно, есть даже лучшее решение?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 21 февраля 2010

Если критерий выбора действительно уникален (т. Е. Дает не более одного результата), вы увидите значительное улучшение производительности благодаря наличию индекса для столбца (или столбцов), участвующих в этом критерии.

create index my_unique_index on table(x)

Если вы хотите применить уникальность, это даже не вариант, вы должны иметь

create unique index my_unique_index on table(x)

Имея этот индекс, запрос по уникальному критерию будет работать очень хорошо, независимо от незначительных настроек SQL, таких как count (*), count (id), count (x), limit 1 и так далее. Для наглядности я бы написал

select count(*) from table where x = ?

Я бы избегал LIMIT 1 по двум другим причинам:

  • Это нестандартный SQL. Я не религиозен в этом, используйте специфичные для MySQL вещи там, где это необходимо (то есть для подкачки данных), но здесь это не обязательно.
  • Если по какой-то причине у вас есть более одной строки данных, это, вероятно, серьезная ошибка в вашем приложении. С LIMIT 1 вы никогда не увидите проблемы. Это похоже на подсчет динозавров в Парке Юрского периода с предположением, что их число может только уменьшиться.
1 голос
/ 21 февраля 2010

Интуитивно понятно, что первое может быть быстрее, поскольку может прервать сканирование таблицы (или индекса), когда найдет первое значение.Но вы должны получить x, а не id, поскольку, если движок использует индекс по x, ему не нужно переходить в блок, где на самом деле находится строка.

Другой вариант может быть:

select exists(select 1 from mytable where x = ?) from dual

, который уже возвращает логическое значение.

1 голос
/ 21 февраля 2010

Лично я обычно делаю первый, выбирая идентификатор из строки и ограничиваясь 1 строкой. Мне нравится это лучше с точки зрения кодирования. Вместо того, чтобы фактически получать данные, я просто проверяю количество возвращаемых строк.

Если бы я сравнивал скорости, я бы сказал, что не делать подсчет в MySQL было бы быстрее. У меня нет никаких доказательств, но я думаю, что MySQL должен получить все строки, а затем посчитать, сколько их. Хотя ... если подумать, то это нужно сделать и в первом варианте, чтобы код знал, сколько строк тоже. Но так как у вас есть COUNT(id) против COUNT(*), я бы сказал, что может быть немного медленнее .

1 голос
/ 21 февраля 2010

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

0 голосов
/ 21 февраля 2010

Как правило, вы используете предложение group by having, чтобы определить, есть ли в таблице повторяющиеся строки. Если у вас есть таблица с идентификатором и именем. (Предполагая, что id является первичным ключом, и вы хотите знать, является ли имя уникальным или повторяется). Вы бы использовали

select name, count(*) as total from mytable group by name having total > 1;

Выше будет возвращаться количество повторяющихся имен и количество раз.

Если вы хотите, чтобы один запрос получал ваш ответ как истинный или ложный, вы можете использовать вложенный запрос, например,

select if(count(*) >= 1, True, False) from (select name, count(*) as total from mytable group by name having total > 1) a;

Вышеприведенное должно возвращать true, если в вашей таблице есть повторяющиеся строки, в противном случае - false.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...