оптимизация запросов mysql

97
9

Мне нужно будет оптимизировать следующий запрос, который займет до 10 минут. Выполняя объяснение, похоже, что он работает на всех 350815 строках таблицы "table_3" и 1 для всех остальных. Общие правила по размещению индексов в режиме "propper"? Должен ли я думать об использовании многомерных индексов? Где я должен использовать их сначала в JOINS, WHERE или GROUP BY, если я помню, что там должна быть иерархия. Кроме того, если у меня есть 1 строка для всех таблиц, но одна (в столбце строки таблицы объяснения), как я могу оптимизировать, то моя оптимизация состоит в том, что она заканчивается только одной строкой для всех столбцов, кроме одной. Все таблицы составляют от 100 тыс. До 1000k+ строк.

CREATE TABLE datab1.sku_performance
SELECT
table1.sku,
CONCAT(table1.sku,' ',table1.fk_container ) as sku_container,
table1.price as price,
SUM( CASE WHEN ( table1.fk_table1_status = 82
OR table1.fk_table1_status = 119
OR table1.fk_table1_status = 124
OR table1.fk_table1_status = 141
OR table1.fk_table1_status = 131) THEN 1 ELSE 0 END)
/ COUNT( DISTINCT id_catalog_school_class) as qty_returned,
SUM( CASE WHEN ( table1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166))
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT id_catalog_school_class) as qt,
container.id_container as container_id,
container.idden as container_idden,
container.delivery_badge,
catalog_school.id_catalog_school,
LEFT(catalog_school.flight_fair,2) as departing_country,
catalog_school.weight,
catalog_school.flight_type,
catalog_school.price,
table_3.id_table_3,
table_3.fk_catalog_brand,
MAX( LEFT( table_3.note,3 )) AS supplier,
GROUP_CONCAT( product_number, ' by ',FORMAT(catalog_school_class.quantity,0)
ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod,
Sum( distinct( catalog_school_class.purch_pri * catalog_school_class.quantity)) AS final_purch_pri,
catalog_groupp.idden as supplier_idden,
catalog_category_details.id_catalog_category,
catalog_category_details.cat1 as product_cat1,
catalog_category_details.cat2 as product_cat2,
COUNT( distinct catalog_school_class.id_catalog_school_class) as setinfo,
datab1.pageviewgrouped.pv as page_views,
Sum(distinct(catalog_school_class.purch_pri * catalog_school_class.quantity)) AS purch_pri,
container_has_table_3.position,
max( table1.created_at ) as last_order_date
FROM
table1
LEFT JOIN container
ON table1.fk_container = container.id_container
LEFT JOIN catalog_school
ON table1.sku = catalog_school.sku
LEFT JOIN table_3
ON catalog_school.fk_table_3 = table_3.id_table_3
LEFT JOIN container_has_table_3
ON table_3.id_table_3 = container_has_table_3.fk_table_3
LEFT JOIN datab1.pageviewgrouped
on table_3.id_table_3 = datab1.pageviewgrouped.url
LEFT JOIN datab1.catalog_category_details
ON datab1.catalog_category_details.id_catalog_category = table_3_has_catalog_minority.fk_catalog_category
LEFT JOIN catalog_groupp
ON table_3.fk_catalog_groupp = catalog_groupp.id_catalog_groupp
LEFT JOIN table_3_has_catalog_minority
ON table_3.id_table_3 = table_3_has_catalog_minority.fk_table_3
LEFT JOIN catalog_school_class
ON catalog_school.id_catalog_school = catalog_school_class.fk_catalog_school
WHERE
table_3.status_ok = 1
AND catalog_school.status = 'active'
AND table_3_has_catalog_minority.is_primary = '1'
GROUP BY
table1.sku,
table1.fk_container;

enter image description here

строк в таблице:

.table1 960096 to 1.3mn rows
.container 9275 to 13000 rows
.catalog_school 709970 to 1 mn rows
.table_3 709970 to 1 mn rows
.container_has_table_3 709970 to 1 mn rows
.pageviewgrouped 500000 rows
.catalog_school_class 709970 to 1 mn rows
.catalog_groupp 3000 rows
.table_3_has_catalog_minority 709970 to 1 mn rows
.catalog_category_details 659 rows

спросил(а) 2021-01-19T21:33:15+03:00 2 месяца, 3 недели назад
1
Решение
97

Слишком много, чтобы вставить один комментарий, поэтому я добавлю здесь и настрою позже, по мере необходимости... У вас ВСЕ ЛЮБЫЕ ПРИСОЕДИНЯТЬСЯ, но предложение WHERE - это специально отборочные поля из таблиц_3, Catalog_School и Table_3_has_catalog_minority. Это по умолчанию изменяет их на INNER JOINs.

Что касается вашего предложения where

WHERE
table_3.status_ok = 1
AND catalog_school.status = 'active'
AND table_3_has_catalog_minority.is_primary = '1'

Какая таблица/столбец будет иметь наименьшие результаты, основанные на этих критериях. ex: Table_3.Status_ok = 1 может иметь 500k записей, но table_3_has_catalog_minority.is_primary может иметь только 65k, а catalog_school.status = 'active' может иметь 430k.

Кроме того, некоторые из ваших столбцов не соответствуют таблице, из которой они идут. Можете ли вы подтвердить... например, "id_catalog_school_class" и "product_number"

SAMETIMES, изменяя порядок таблиц, с хорошими знаниями о составе данных и в MySQL, добавляя ключевое слово "STRAIGHT_JOIN", может повысить производительность. Это было то, что я имел в прошлом, работая с государственной базой данных контрактов и грантов с 20+ миллионами записей и присоединившись к таблицам поиска 15+. Он перешел от подвески сервера к завершению запроса менее чем за 2 часа. Учитывая объем данных, с которыми я имел дело, это было действительно хорошее время.

ПОСЛЕ того, как это делалось, я немного изменил для удобочитаемости, добавил псевдонимы для ссылок на таблицы и изменил порядок запроса и предложил некоторые предлагаемые индексы. Чтобы помочь в запросе, я попытался переместить таблицу Catalog_School в первую позицию и добавил STRAIGHT_JOIN. Индекс основывается на STATUS сначала, чтобы соответствовать предложению WHERE, тогда я включил SKU, поскольку он является первым элементом GROUP BY, а затем другими столбцами, которые используются для присоединения к последующим таблицам. Имея эти столбцы в индексе, он может квалифицировать объединения без необходимости обращаться к необработанным данным.

Изменив группу на Catalog_School.SKU вместо table_1.SKU, индекс index из catalog_school может использоваться для оптимизации этого. Это то же значение, что и соединение из каталога_school.sku = table_1.sku. Я также добавил ссылки на индекс для table_1 и table_3, которые являются предложениями - опять же, чтобы упреждающе квалифицировать соединения, не переходя на страницы необработанных данных таблиц.

Мне было бы интересно узнать конечную производительность (лучше или хуже) из ваших данных.

TABLE             INDEX ON...
catalog_school ( status, sku, fk_table_3, id_catalog_school )
table_1 ( sku, fk_container )
table_3 ( id_table_3, status_ok, fk_catalog_groupp )

SELECT STRAIGHT_JOIN
CS.sku,
CONCAT(CS.sku,' ',T1.fk_container ) as sku_container,
T1.price as price,
SUM( CASE WHEN ( T1.fk_table1_status IN ( 82, 119, 124, 141, 131)
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT CSC.id_catalog_school_class) as qty_returned,
SUM( CASE WHEN ( T1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166))
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT CSC.id_catalog_school_class) as qt,
CS.id_catalog_school,
LEFT(CS.flight_fair,2) as departing_country,
CS.weight,
CS.flight_type,
CS.price,
T3.id_table_3,
T3.fk_catalog_brand,
MAX( LEFT( T3.note,3 )) AS supplier,
C.id_container as container_id,
C.idden as container_idden,
C.delivery_badge,
GROUP_CONCAT( product_number, ' by ',FORMAT(CSC.quantity,0)
ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod,
Sum( distinct( CSC.purch_pri * CSC.quantity)) AS final_purch_pri,
CGP.idden as supplier_idden,
CCD.id_catalog_category,
CCD.cat1 as product_cat1,
CCD.cat2 as product_cat2,
COUNT( distinct CSC.id_catalog_school_class) as setinfo,
PVG.pv as page_views,
Sum(distinct(CSC.purch_pri * CSC.quantity)) AS purch_pri,
CHT3.position,
max( T1.created_at ) as last_order_date
FROM
catalog_school CS

JOIN table1 T1
ON CS.sku = T1.sku
LEFT JOIN container C
ON T1.fk_container = C.id_container

LEFT JOIN catalog_school_class CSC
ON CS.id_catalog_school = CSC.fk_catalog_school

JOIN table_3 T3
ON CS.fk_table_3 = T3.id_table_3
JOIN table_3_has_catalog_minority T3HCM
ON T3.id_table_3 = T3HCM.fk_table_3
LEFT JOIN datab1.catalog_category_details CCD
ON T3HCM.fk_catalog_category = CCD.id_catalog_category

LEFT JOIN container_has_table_3 CHT3
ON T3.id_table_3 = CHT3.fk_table_3

LEFT JOIN datab1.pageviewgrouped PVG
on T3.id_table_3 = PVG.url

LEFT JOIN catalog_groupp CGP
ON T3.fk_catalog_groupp = CGP.id_catalog_groupp
WHERE
CS.status = 'active'
AND T3.status_ok = 1
AND T3HCM.is_primary = '1'
GROUP BY
CS.sku,
T1.fk_container;

ответил(а) 2021-01-19T21:33:15+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема