Радикально более медленный подзапрос без autokey в MySQL 5.7 против 5.6 - есть ли способ форсировать индекс? - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть таблица datehelper с каждым YYYY-MM-DD в качестве ДАТЫ между 2000 и 2100 годами. Для этого я присоединяюсь к подзапросу для всех unit транзакций. unit. end - это DATETIME, поэтому мой подзапрос упрощает его до DATE и использует его для присоединения к таблице datehelper.

В 5.6 этот запрос занимает пару секунд для выполнения огромного количества транзакций и выводит таблицу с автоматическим ключом на основе ДАТЫ (unit. end) в подзапросе и использует ее для довольно быстрого объединения всего остального.

В 5.7 это занимает более 600 секунд и я не могу заставить его получить таблицу или следовать гораздо лучшему плану выполнения, который использовал 5.6. Есть ли флаг, который мне нужно установить, или какой-то способ отдать предпочтение старому плану выполнения?

Вот запрос:

EXPLAIN SELECT datehelper.id AS date, MONTH(datehelper.id)-1 AS month, DATE_FORMAT(datehelper.id,'%d')-1 AS day, 
                        IFNULL(SUM(a.total),0) AS total, IFNULL(SUM(a.tax),0) AS tax, IFNULL(SUM(a.notax),0) AS notax 
                    FROM datehelper 
                    LEFT JOIN 
                        (SELECT 
                            DATE(unit.end) AS endDate, 
                            getFinalPrice(unit.id) AS total, tax, getFinalPrice(unit.id)-tax AS notax 
                            FROM unit 
                                INNER JOIN products ON products.id=unit.productID 
                                INNER JOIN prodtypes FORCE INDEX(primary) ON prodtypes.id=products.prodtypeID 
                            WHERE franchiseID='1' AND void=0 AND checkout=1 
                                AND end BETWEEN '2020-01-01' AND DATE_ADD('2020-01-01', INTERVAL 1 YEAR) 
                                AND products.prodtypeID NOT IN (1,10) 
                        ) AS a ON a.endDate=datehelper.id 
                    WHERE datehelper.id BETWEEN '2020-01-01' AND '2020-12-31' 
                    GROUP BY datehelper.id ORDER BY datehelper.id;

5,6 (намного быстрее):

  • id select_type табличный тип возможных_кнопок ключ key_len ref строки Дополнительно
  • 1 ПЕРВИЧНЫЙ диапазон datehelper ПЕРВИЧНЫЙ ПЕРВИЧНЫЙ 3 NULL 365 Использование где; Использование индекса
  • 1 ПЕРВИЧНЫЙ исх 4 datehelper.id 10 NULL
  • 2 Индекс производных типов PRIMARY PRIMARY 4 NULL 10 Использование где; Использование индекса
  • 2 ПРОИЗВОДНЫХ продуктов ref ПЕРВИЧНЫЙ, prodtypeID prodtypeID 4 prodtypes.id
  • 9 Использование индекса
  • 2 ПРОИЗВОДНОЙ единицы ref productID, end, void, franchiseID productID 9 продуктов. id 2622 Использование результата where

5.7 (намного медленнее, автоключ не найден):

  • id select_type таблица разделов typeable_keys ключ key_len ref строки, отфильтрованные Extra
  • 1 ПРОСТОЙ datehelper Диапазон NULL ПЕРВИЧНЫЙ ПЕРВИЧНЫЙ 3 NULL 366 100.00 Использование где; Использование индекса
  • 1 ПРОСТАЯ единица NULL ref productID, end, void, franchiseID franchiseID 4 const 181727 100.00 Использование where
  • 1 SIMPLE product NULL eq_ref PRIMARY, prodtypeID PRIMARY 8 barkops3.unit.productID 1 100.00 Использование where
  • 1 ПРОСТЫХ типов продукции NULL eq_ref PRIMARY PRIMARY 4 barkops3.products.prodtypeID 1 100.00 Использование индекса

1 Ответ

0 голосов
/ 12 апреля 2020

Я нашел проблему. Это был флаг 'optim_merge' optimizer_switch, который является новым для 5.7.

https://dev.mysql.com/doc/refman/5.7/en/derived-table-optimization.html

Этот флаг переопределяет материализацию производных таблиц, если оптимизатор считает, что внешний WHERE может быть опущены в подзапрос. В этом случае такая оптимизация была значительно дороже, чем объединение материализованной таблицы в auto_key.

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