MySQL не использует мой индекс, в то время как объявляет, что это будет в операторе объяснения - PullRequest
0 голосов
/ 23 октября 2018

Недавно я столкнулся с проблемой, связанной с MySQL DBSM.
Таблица выглядит следующим образом:

 CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(60) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sex` enum('男','女') DEFAULT NULL,
`amount` float(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `name_i` (`name`),
KEY `sex` (`sex`)
) ENGINE=InnoDB AUTO_INCREMENT=5000001 DEFAULT CHARSET=utf8 

Как показано выше, я создаю единый индекс столбца для столбца col name
IЯ хочу выполнить запрос диапазона на name, а оператор объяснения -

mysql> explain select * from orders where name like '王%';
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
| id | select_type | table  | partitions | type  | possible_keys | key    | key_len | ref  | rows  | filtered | Extra                            |
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
|  1 | SIMPLE      | orders | NULL       | range | name_i        | name_i | 183     | NULL | 20630 |   100.00 | Using index condition; Using MRR |
+----+-------------+--------+------------+-------+---------------+--------+---------+------+-------+----------+----------------------------------+
1 row in set, 1 warning (0.10 sec)

, поэтому он должен использовать индекс name_i и завершить запрос в одно мгновение (однако мой одноклассник потратил 0,07 сек), однако,вот как это получилось:

| 4998119 | 王缝   |   27 | 男   | 159.21 |
| 4998232 | 王求葬 |   19 | 男   | 335.65 |
| 4998397 | 王倘予 |   49 | 女   | 103.39 |
| 4998482 | 王厚   |   77 | 男   | 960.69 |
| 4998703 | 王啄淋 |   73 | 女   | 458.85 |
| 4999106 | 王般埋 |   70 | 女   | 700.98 |
| 4999359 | 王胆具 |   31 | 女   | 362.83 |
| 4999510 | 王铁脾 |   31 | 女   | 973.09 |
| 4999880 | 王战万 |   59 | 女   | 127.28 |
| 4999928 | 王忆   |   42 | 女   |  72.47 |
+---------+--------+------+------+--------+
11160 rows in set (3.43 sec)

И, похоже, индекс вообще не используется, поскольку данные сортируются по первичному ключу id, а не по столбцу name (к тому же это слишкоммедленный, по сравнению с 0,07 с).

Кто-нибудь тоже сталкивался с проблемой?

1 Ответ

0 голосов
/ 25 октября 2018
  • Какой процент от таблицы составляет "Короли" (王)?Если оно составляет более 20%, вместо использования индекса будет выбрано сканирование таблицы.(И это на самом деле может быть быстрее.) (На основании комментариев, 0,22% таблицы составляют Kings.)
  • EXPLAIN и выполнение запроса - это разные вещи.Хотя я не помню, чтобы доказать это, возможно , что EXPLAIN может сказать одно, но запрос будет работать по-другому.
  • У вас есть 5 миллионов строк вТаблица?Был ли кеш холодным, когда вы впервые запустили его?И это должно было извлечь 11 160 строк с диска?Затем во второй раз все было в кеше, намного быстрее?
  • Была ли таблица загружена в «алфавитном» (или как там китайское слово для этого) порядке?Если это так, есть большая вероятность, что идентификаторы и имена расположены в одном и том же порядке?
  • Видимо, вы используете utf8_general_ci COLLATION? Может быть это не очень хорошо сортирует китайский.(Приведите контрольный пример; я проведу несколько тестов.)
  • Я не понимаю, почему он упомянул MRR.
  • Меня тоже сбивает с толку "1 мин 32,24 с",ORDER BY name должен был дополнительно побудить оптимизатор использовать INDEX(name).Можете ли вы включить «Оптимизатор трассировки».

Чтобы действительно увидеть, использовал ли он индекс, сделайте следующее:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';

Если большое число (а) похоже на числострок в таблице, затем он сделал сканирование таблицы.Если они больше похожи на 11160, то они использовали индекс.

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