Есть ли смысл использовать MySQL "LIMIT 1" при запросе на индексированное/уникальное поле?
Например, я запрашиваю поле, которое я знаю, будет уникальным и индексируется, например, первичный ключ. Поэтому я знаю, что этот запрос будет возвращать только 1 строку (даже без LIMIT 1)
SELECT * FROM tablename WHERE tablename.id=123 LIMIT 1
или обновить только 1 строку
UPDATE tablename SET somefield='somevalue' WHERE tablename.id=123 LIMIT 1
Добавил бы LIMIT 1
улучшить время выполнения запроса, если поле проиндексировано?
Ответы
Ответ 1
Есть ли смысл использовать MySQL "LIMIT 1" при запросе на поле первичного ключа/уникального?
Не рекомендуется использовать LIMIT 1
при запросе с критериями фильтрации, которые противоречат либо первичному ключу, либо уникальному ограничению. Первичный ключ или уникальное ограничение означает, что в таблице есть только одна строка/запись с этим значением, только одна строка/запись когда-либо будет возвращена. Это противоречиво иметь LIMIT 1
в первичном ключе/уникальном поле - кто-то, поддерживающий код позже, может ошибочно принять значение и угадать ваш код.
Но конечным индикатором является план объяснения:
explain SELECT t.name FROM USERS t WHERE t.userid = 4
... возвращает:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
-----------------------------------------------------------------------------------------------------
1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 |
... и:
explain SELECT t.name FROM USERS t WHERE t.userid = 4 LIMIT 1
... возвращает:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra
-----------------------------------------------------------------------------------------------------
1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 |
Заключение
Никакой разницы, нет необходимости. В этом случае он оптимизирован (только для поиска по первичному ключу).
Как насчет проиндексированного поля?
Индексированное поле не гарантирует уникальности фильтруемого значения, может быть более одного случая. Поэтому LIMIT 1
имеет смысл, если вы хотите вернуть одну строку.
Ответ 2
Если в этом поле есть уникальный индекс, я не вижу, как это улучшает время выполнения вообще - оно растягивается даже по стандартам микрооптимизации.
Однако я вижу, что это потенциально маскирует другие проблемы. Скажем, вы добавляете LIMIT 1 к этим запросам, а затем каким-то образом поле, на которое вы запрашиваете, теряет свой уникальный индекс, а db получает несколько строк с одинаковым значением. Этот код будет продолжаться счастливо - я думаю, вы, возможно, захотите быстро сменить, вместо этого, чтобы узнать (и исправить) большую проблему.
В моем собственном коде интерфейса db у меня есть метод queryOneRow(), который запускает некоторый SQL и выдает исключение, если он возвращает больше одной строки. Для меня наиболее разумно обращаться с этим явно на уровне приложения, а не защищаться в SQL.
Ответ 3
В большинстве случаев, когда я запрашиваю уникальные поля, я все еще использую LIMIT 1
. Я в основном делаю это, потому что хочу, чтобы независимо от того, что кто-либо делает с базой данных/таблицами, мой запрос никогда не вернется или не обработает более одной строки.
Обычно это также должно охватывать случай динамически искаженного запроса, чтобы испортить всю базу данных (и нет - я не говорю о вводе SQL).
Ответ 4
Так как запрос будет возвращать в любой момент только одну запись; то добавление LIMIT 1
не увеличит ваше время выполнения.
Я не уверен, какой алгоритм MySQL использует для выполнения запросов LIMIT 1
. Как бы то ни было, он может использовать выражения сравнения или итераторы для возврата только одной записи - в этом случае добавление LIMIT 1
может фактически задержать время выполнения несколькими инструкциями.