#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
это относительный термин, и нам нужно реальное значение для сравнения. MySQL2. Первый вопрос: зависит от того, сколько пользователей использует производственную базу данных. Во-вторых, вам нужно изучить EXPLAIN ANALYZE, чтобы увидеть разницу
3. Перемещение условия в
LEFT JOINed
таблице изON
вWHERE
изменяет поведение запроса. Вы не получите ни одной строки, которая не соответствует во второй таблице, потому чтоurl_rewrite.id_path
будетNULL
в этих строках.4. Убедитесь, что у
id_path
есть индекс. В противном случае этоLIKE
выражение требует полной проверки.5. Я отредактировал вопрос, предоставив запрошенную вами информацию.