Есть ли смысл использовать 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 может фактически задержать время выполнения несколькими инструкциями.