Нужна помощь по производительности запросов - PullRequest
0 голосов
/ 23 ноября 2018

Сегодня я сталкиваюсь со странным вопросом, который у меня есть ниже запроса.Когда я запускаю этот запрос, это занимает много времени.Например, если я поставлю только "где w2.cdate между" 2018-01-01 00:00:00 "и" 2018-10-31 23:59:59 "" или только "s2.status = 'NEW'", то этодает немедленный результат, но если я соберу оба условия вместе, это займет время.Мои столбцы «cdate» и «status» проиндексированы.Что может быть причиной этого, как я могу найти это.

select w2.id from status s2
  inner join order w2 on s2.warenkorb__id=w2.id 
    where  w2.cdate between '2018-01-01 00:00:00' and '2018-10-31 23:59:59' and  s2.status='NEW'

Результат Эплена со всеми условиями Explain Result with all condition

Объясните результат с условием даты enter image description here

Ответы [ 3 ]

0 голосов
/ 23 ноября 2018

Ваша модель данных позволяет использовать несколько статусов для заказа.Таким образом, чтобы получить прямой запрос, я бы выбрал идентификатор из таблицы заказов и посмотрел статус в предложении WHERE:

select id
from `order`
where cdate >= date '2018-01-01'
  and cdate <  date '2018-11-01'
  and id in (select warenkorb__id from status where status = 'NEW');

(В других СУБД вместо этого можно использовать INTERSECT, но MySQLэтого нет.)

Теперь рассмотрим два подхода:

  1. СУБД сначала выбирает статусы для получения заказов.
  2. СУБД выбираетсначала заказывает и ищет их статусы.

Для случая 1 вы хотите:

create index idx1 on status (status, warenkorb__id);

и индекс заказа (id), который у вас уже должен быть.Или даже укажите индекс покрытия:

create index idx2 on `order` (id, cdate);

Для случая 2 вы хотите:

create index idx3 on `order` (cdate, id);
create index idx4 on status (warenkorb__id, status);

Создайте эти четыре индекса, посмотрите на план выполнения и отбросьте индексы, которые использует СУБДне использует.

0 голосов
/ 24 ноября 2018

Они должны работать хорошо, независимо от того, с какой таблицы оптимизатор решит начать:

w2:  INDEX(cdate, id)
s2:  INDEX(status, warenkorb__id)

Указанный порядок столбцов важен.(Я не думаю, что дополнительная пара индексов Торстена помогает.)

Вопросы о схеме:

  • Является ли id PRIMARY KEY из w2?(Пожалуйста, укажите SHOW CREATE TABLE, так что этот и другие вопросы не нужны.)
  • Находятся ли две таблицы в соотношении 1: 1?Это обычно не очень хороший дизайн.Кажется, что status может быть в w2.
0 голосов
/ 23 ноября 2018

Как видно из разницы в результатах оператора EXPLAIN, случай, использующий все условия, не может Using Index.

. Вы можете добавить следующие два составных индекса и проверить:

  1. (warenkorb__id, status) в таблице status.
  2. (id, cdate) в таблице order.

ALTER TABLE запросов будет следующим:

ALTER TABLE status ADD INDEX(warenkorb__id, status);

ALTER TABLE order ADD INDEX(id, cdate);
...