MySQL Пояснение к запросу: Выбор индекса, когда в запросе есть «WHERE», а также «ORDER BY» - PullRequest
4 голосов
/ 09 мая 2020

Есть кое-что, чего я не могу понять, когда пытаюсь оптимизировать свой запрос с помощью индекса.

Таблица выглядит так:

create table order_table (
  id int not null primary key,
  customer_id varchar(50) not null,
  sale int not null,
  key customer_sale_idx (customer_id, sale)
);

при запуске explain select * from order_table where customer_id=2 order by sale limit 1;

Он показывает

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: order_table
   partitions: NULL
         type: index
possible_keys: customer_sale_idx
          key: customer_sale_idx
      key_len: 206
          ref: NULL
         rows: 5
     filtered: 20.00
        Extra: Using where; Using index; Using filesort

А затем я добавляю еще один индекс alter table order_table add key sale_customer_idx (sale, customer_id);

теперь запрос explain select * from order_table where customer_id=2 order by sale limit 1; показывает

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: order_table
   partitions: NULL
         type: index
possible_keys: customer_sale_idx
          key: sale_customer_idx
      key_len: 206
          ref: NULL
         rows: 1
     filtered: 20.00
        Extra: Using where; Using index

Q1: Я полагаю mysql сначала следует проверить customer_id, получить те записи, которые соответствуют where, а затем выполнить sort по sale. Он использует индекс customer_sale_idx, как я ожидал, но я не понимаю, почему он использует Using filesort вместо использования индекса обложки (customer_id, sale) для сортировки.

Q2: MySQL использует новый индекс sale_customer_idx (sale, customer_id) после того, как я его добавил. Но я не понимаю, как этот индекс помогает избавиться от Using filesort.

Q3: последний explain говорит, что есть только один possible_keys, который равен customer_sale_idx, но затем он использует sale_customer_idx. Как?

Кстати, я знаю странно, что customer_id это varchar. Но давайте сосредоточимся на объяснении этого явления.

Ответы [ 2 ]

1 голос
/ 09 мая 2020

MySQL должен преобразовать первый столбец вашего индекса (customer_id, sale) в целое число. Таким образом, второй столбец нельзя использовать для сортировки.

... where customer_id=2 ...

будет истинным для customer_id s со значениями varchar '2', '02', '002', '2 and a half men' и многими другими. Он не может перейти к '2', прочитать первую строку и предположить, что это строка с наименьшим значением sale, поскольку также может быть '02' с меньшим значением sale. Только это позволит MySQL не сортировать.

Вместо этого он должен go просмотреть всю таблицу, преобразовать каждую строку, проверить, = 2 ли она после преобразования, взять те, которые есть, и отсортировать все, что осталось. Вот почему у вас есть сортировка файлов. MySQL не знает, что у вас нет ничего другого, что могло бы привести к 2.

Фактически, он мог бы сделать то же самое с первичным ключом. Поскольку ваш индекс покрывает, они эквивалентны.

Вы можете проверить это, если проведете сравнение с varchar, для которого не требуется приведение типов, поэтому найденные им записи индекса правильно упорядочены по второму столбцу sale:

... where customer_id='2' ...

Теперь он может делать именно то, что ожидалось: перейти на '2', взять первую строку, остановиться. Сортировка не требуется. MySQL знает: это строка с наименьшим значением для sale.

Ваш индекс (sale, customer_id) работает следующим образом: он считывает все значения, упорядоченные по продаже, пока не достигнет значения ( autocasted), равное 2. Теперь MySQL может быть уверен, что это именно тот, который вам нужен (поскольку вы уже проверили все более низкие значения sale, ни одно из них не соответствует вашему условию customer_id. Таким образом, упорядочивание не требуется.

1 голос
/ 09 мая 2020

Похоже, что в этой таблице очень мало строк. С очень маленькими таблицами сканирование таблиц и операции сортировки могут быть дешевле, чем сканирование индекса. Когда в нем будет несколько тысяч строк, план выполнения станет более предсказуемым.

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