MySQL — ЛЕВОЕ СОЕДИНЕНИЕ с LIKE % выполняется чрезвычайно медленно

#mysql #magento #left-join

#mysql #magento #левое соединение

Вопрос:

У меня есть запрос, который выполняется чрезвычайно медленно (около 50 секунд):

 SELECT SQL_NO_CACHE `main_table`.`entity_id`, `url_rewrite`.`request_path` 
FROM `catalog_product_entity` AS `main_table`
INNER JOIN `catalog_product_website` AS `w` 
      ON main_table.entity_id = w.product_id
LEFT JOIN `core_url_rewrite` AS `url_rewrite` 
      ON url_rewrite.product_id = main_table.entity_id 
      AND url_rewrite.is_system = 1  
      AND url_rewrite.category_id IS NULL 
      AND url_rewrite.store_id = 1 
      AND url_rewrite.id_path LIKE 'product/%'
  

Запрос исходит из Magento, только SQL_NO_CACHE был добавлен мной, чтобы сделать измерение более точным.

Такое длительное время выполнения, конечно, неприемлемо. Поэтому я сбросил базу данных и восстановил ее в своей среде разработки, чтобы исследовать проблему. Однако в моей базе данных разработки запрос выполняется очень быстро — он выполняется менее чем за 0,1 секунды.

Вопрос 1: Что может быть причиной такого длительного времени выполнения в моей производственной среде? Я не заметил, чтобы какие-либо другие запросы были настолько медленными в моей рабочей базе данных.

Для дальнейшего изучения я немного изменил запрос:

 SELECT SQL_NO_CACHE `main_table`.`entity_id`, `url_rewrite`.`request_path` 
FROM `catalog_product_entity` AS `main_table`
INNER JOIN `catalog_product_website` AS `w` 
      ON main_table.entity_id = w.product_id
LEFT JOIN `core_url_rewrite` AS `url_rewrite` 
      ON url_rewrite.product_id = main_table.entity_id 
      AND url_rewrite.is_system = 1 
      AND url_rewrite.category_id IS NULL 
      AND url_rewrite.store_id = 1 
WHERE url_rewrite.id_path LIKE 'product/%'
  

(Обратите внимание на LIKE выражение, перемещенное в WHERE предложение)

Этот запрос возвращает те же результаты, но намного быстрее — он выполняется менее чем за 1 секунду в моей рабочей базе данных.

Вопрос 2: Почему существует такая разница во времени выполнения между двумя запросами? Есть ли какая-либо проблема с LIKE выражением, помещенным в LEFT JOIN предложение?

Результаты из EXPLAIN EXTENDED :

Производственная база данных:

 id    select_type    table        type      possible_keys                                                      key                                                key_len    ref            rows    filtered    Extra
 1     SIMPLE        w            index      PRIMARY                                                           IDX_CATALOG_PRODUCT_WEBSITE_WEBSITE_ID               2        NULL           642     100.00      Using index
 1     SIMPLE        main_table   eq_ref     PRIMARY                                                           PRIMARY                                              4        w.product_id     1     100.00      Using index
 1     SIMPLE        url_rewrite  ref        IDX_CORE_URL_REWRITE_ID_PATH,                                     FK_CORE_URL_REWRITE_CTGR_ID_CAT_CTGR_ENTT_ENTT_ID    5        const           10     100.02     
                                             FK_CORE_URL_REWRITE_PRODUCT_ID_CATALOG_CATEGORY_ENTITY_ENTITY_ID,
                                             FK_CORE_URL_REWRITE_CTGR_ID_CAT_CTGR_ENTT_ENTT_ID,
                                             UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID
  

База данных разработки:

 id    select_type    table        type      possible_keys                                                      key                                                               key_len    ref            rows    filtered    Extra
 1     SIMPLE        w            index      PRIMARY                                                           IDX_CATALOG_PRODUCT_WEBSITE_WEBSITE_ID                              2        NULL           1009     100.00     Using index
 1     SIMPLE        main_table   eq_ref     PRIMARY                                                           PRIMARY                                                             4        w.product_id      1     100.00     Using index
 1     SIMPLE        url_rewrite  ref        IDX_CORE_URL_REWRITE_ID_PATH,                                     FK_CORE_URL_REWRITE_PRODUCT_ID_CATALOG_CATEGORY_ENTITY_ENTITY_ID    5        w.product_id     31     100.00     Using where     
                                             FK_CORE_URL_REWRITE_PRODUCT_ID_CATALOG_CATEGORY_ENTITY_ENTITY_ID,
                                             FK_CORE_URL_REWRITE_CTGR_ID_CAT_CTGR_ENTT_ENTT_ID,
                                             UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID
  

Размеры таблиц (одинаковые на обоих серверах, поскольку база данных разработки является дампом производственной базы данных):

catalog_product_entity:
Данные 96 КБ,
индексы 88 КБ,
Всего 176 КБ

catalog_product_website:
Данные 64 КБ,
индексы 16 КБ,
всего 80 КБ

core_url_rewrite:
Data 5.5 MB
Indexes 15.5 MB
Total 21 MB

Количество записей в таблицах (одинаковое в обеих базах данных):
catalog_product_entity 1009
catalog_product_website 1009
core_url_rewrite 34878

Производительность в текущее время:
производственная база данных 50 секунд
база данных разработки 0,1 секунды

Желаемое время:
производственная база данных 1 секунда
база данных разработки 0,1 секунда

Индексы

catalog_product_entity:
ПЕРВИЧНЫЙ (entity_id, тип: BTREE, уникальный: Да) IDX_CATALOG_PRODUCT_ENTITY_ENTITY_TYPE_ID (entity_type_id, тип: BTREE, уникальный: Нет)

catalog_product_website:
ПЕРВИЧНЫЙ (product_id, тип: BTREE, уникальный: Да) IDX_CATALOG_PRODUCT_WEBSITE_WEBSITE_ID (website_id, тип: BTREE, уникальный: Нет)

core_url_rewrite:
ОСНОВНОЙ (url_rewrite_id, тип: BTREE, уникальный: Да)
UNQ_CORE_URL_REWRITE_REQUEST_PATH_STORE_ID ((request_path, store_id), Тип: BTREE, Уникальный: Да)
UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID ((id_path, is_system, store_id), Тип: BTREE, Уникальный: Да)
IDX_CORE_URL_REWRITE_TARGET_PATH_STORE_ID ((target_path, store_id), Тип: BTREE, Уникальность: Нет)
IDX_CORE_URL_REWRITE_ID_PATH (id_path, Тип: BTREE, Уникальность: Нет)
IDX_CORE_URL_REWRITE_STORE_ID (store_id, тип: BTREE, Уникальный: Нет)
FK_CORE_URL_REWRITE_CTGR_ID_CAT_CTGR_ENTT_ENTT_ID (category_id, тип: BTREE, Уникальный: Нет)
FK_CORE_URL_REWRITE_PRODUCT_ID_CATALOG_CATEGORY_ENTITY_ENTITY_ID (product_id, тип: BTREE, Уникальный: Нет)

Заключительные замечания:

Рабочий сервер не испытывает большой нагрузки — все другие запросы, которые я тестировал, дают аналогичные результаты в обеих базах данных.

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

Я был бы очень благодарен за объяснение такого странного поведения MySQL.

Комментарии:

1. Вопросы производительности должны включать EXPLAIN ANALYZE и некоторую информацию о размере таблицы, индексе, производительности в текущее время, времени ожидания и т.д. Slow это относительный термин, и нам нужно реальное значение для сравнения. MySQL

2. Первый вопрос: зависит от того, сколько пользователей использует производственную базу данных. Во-вторых, вам нужно изучить EXPLAIN ANALYZE, чтобы увидеть разницу

3. Перемещение условия в LEFT JOINed таблице из ON в WHERE изменяет поведение запроса. Вы не получите ни одной строки, которая не соответствует во второй таблице, потому что url_rewrite.id_path будет NULL в этих строках.

4. Убедитесь, что у id_path есть индекс. В противном случае это LIKE выражение требует полной проверки.

5. Я отредактировал вопрос, предоставив запрошенную вами информацию.