![]() |
|
Задавайте вопросы, мы ответим
Вы не зашли.

Недавно столкнулся с прочно забытым правилом, согласно которому MySQL применяет оператор = к строкам CHAR/VARCHAR без учета пробелов на конце:
mysql> SELECT 'a' = 'a '; +--------------+ | 'a' = 'a ' | +--------------+ | 1 | +--------------+
С учетом пробелов сравнивает LIKE:
mysql> SELECT 'a' LIKE 'a '; +-----------------+ | 'a' LIKE 'a ' | +-----------------+ | 0 | +-----------------+
Но LIKE хуже пользуется индексом на колонке url (уникальный ключ на всю длину):
mysql> EXPLAIN SELECT * FROM pages WHERE url = '/'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pages
type: const
possible_keys: url
key: url
key_len: 258
ref: const
rows: 1
Extra:
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM pages WHERE url LIKE '/'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: pages
type: range
possible_keys: url
key: url
key_len: 258
ref: NULL
rows: 1
Extra: Using where
1 row in set (0.00 sec)Как сравнивать строки с учетом пробелов, при этом наиболее эффективно используя индекс?
Неактивен

А в чем проблема с индексом при использовании LIKE?
Не забудь, что для CHAR и VARCHAR концевые пробелы вообще не сохраняются в базе.
Неактивен

А в чем проблема с индексом при использовании LIKE?
ref у explain поприятней выглядит. Для = - const, для LIKE - using where.
Такое впечатление, что для LIKE он не хочет использовать индекс.
Не забудь, что для CHAR и VARCHAR концевые пробелы вообще не сохраняются в базе.
Забыл ![]()
Но в данном случае проблема обратная: пробелы есть в сравниваемой с базой строке. И сравнение должно заканчиваться неудачей, если строки отличаются из-за концевых пробелов.
На практике ситуация такая: серверу приходит адрес / с пробелами на конце. Оператор = скажет, что это то же самое, что /, механизм сайта как ни в чем не бывало отдаст по адресу / главную страницу. В результате у поисковика в индексе появляется дубликат главной страницы, и сеошники падают в обморок
(случай из жизни).
Неактивен

LazY написал:
Такое впечатление, что для LIKE он не хочет использовать индекс.
Это не доказательство. Должно быть по скорости так же.
Оператор = думает, что вдруг там был тоже пробел, но съелся при записи в базу.
Неактивен

Это не доказательство. Должно быть по скорости так же.
По скорости и так 0.00, и так 0.00 - таблица 100 записей ![]()
Неактивен

Просто анализ путей запроса - важная часть механизма сайта, срабатывает при каждом запросе. Хотелось сделать ее максимально быстрой.
Если LIKE нормально - то и ладно.
Неактивен

Сделай миллион записей и проверь. Вижу только то, что = делает проверку на точное совпадение, а LIKE на range. Хотя очевидно, что range достаточно узкий, это интересный вопрос почему range.
Кстати, у тебя может быть еще одна проблема. В данном случае с большими и маленькими буквами:
Неактивен

это интересный вопрос почему range
Видимо, потому что не точное равенство. LIKE по правой части оптимизатор наверняка рассматривает как range, а частный случай, когда LIKE без процентов, он отдельно не учитывает.
Кстати, для = BINARY тоже показывает range.
Насчет использования индекса. Дело тут, похоже, в наборе колонок для SELECT.
Если вместо SELECT * сделать SELECT COUNT(*), то и =, и LIKE, и = BINARY дают Using where; Using index.
По скорости все оказались примерно одинаковыми.
Кстати, у тебя может быть еще одна проблема. В данном случае с большими и маленькими буквами:
Да. Но ее решение - это вопрос отдельный.
Неактивен