2013-08-03 2 views
-1

## MySql Server 5.5, двигатель базы данных MyISAM, таблица fact_transaction индексируется на date_key, time_key, unit_cost_price, unit_retail_price (комбинированный ключ) и то же самое для fact_stockout_sales за исключением time_key. ##Выберите Оптимизация запросов на MySQL для больших объемов данных

Query plan

Query plan

Запрос

SELECT 
    t.Level, t.Name, t.KeyValue, 
    ROUND((SUM(t.Gross)/SUM(t.Revenue))*100, 2) AS Value, 
    ROUND((SUM(t.adjustedGross)/SUM(t.adjustedRevenue))*100, 2) AS adjustedValue, 
    t.dataType AS dataType 
FROM 
    (SELECT "item" AS Level, ds.product_name AS Name, ds.product_id AS KeyValue, 
     SUM(ft.gross_profit) AS Gross, 
     SUM(ft.selling_amount) AS Revenue, 
     SUM(ft.adjusted_gross_profit) AS adjustedGross, 
     SUM(ft.adjusted_selling_amount) AS adjustedRevenue, 
     "%" AS dataType 
    FROM fact_transaction AS ft 
    JOIN dim_sku AS ds ON ft.sku_key = ds.sku_key 
    WHERE ft.date_key BETWEEN 20080215 AND 20130107 
     AND ft.time_key BETWEEN 100 AND 235900 
     AND ft.unit_cost_price BETWEEN 0 AND 1333 
     AND ft.unit_retail_price BETWEEN 0 AND 16500 
     AND ft.store_key IN ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16") 
     AND ds.product_id IN (1312009,1312007,... Huge List say 30000) 
     AND ds.category IN ("Male","Female","Unisex") 
     AND ft.day_of_week IN ("1","2","3","4","5","6","7") 
     AND ds.collection_name IN ("Base","SS12","AW12") 
    GROUP BY ds.product_id       
    UNION 
    SELECT "item" AS Level, ds.product_name AS Name, ds.product_id AS KeyValue, 
     SUM(ft.gross_profit) AS Gross, 
     SUM(ft.selling_amount) AS Revenue, 
     SUM(ft.adjusted_gross_profit) AS adjustedGross, 
     SUM(ft.adjusted_selling_amount) AS adjustedRevenue, 
     "%" AS dataType 
    FROM fact_stockout_sales AS ft 
    JOIN dim_sku AS ds ON ft.sku_key = ds.sku_key 
    WHERE ft.date_key BETWEEN 20080215 AND 20130107 
     AND ft.unit_cost_price BETWEEN 0 AND 1333 
     AND ft.unit_retail_price BETWEEN 0 AND 16500 
     AND ft.store_key IN ("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16") 
     AND ds.product_id IN (1312009,1312007,.. Huge List say 30000) 
     AND ds.category IN ("Male","Female","Unisex") 
     AND ft.day_of_week IN ("1","2","3","4","5","6","7") 
     AND ds.collection_name IN ("Base","SS12","AW12") 
     GROUP BY ds.product_id) AS t 
GROUP BY t.KeyValue 
+0

Почему вы используете UNION для объединения двух ** тождественных ** запросов? Это должно быть медленным - один и тот же запрос выполняется дважды, тогда UNION объединяет два конца идентификационных результатов, что исключает дубликаты. – krokodilko

+0

@kordirko: Они не идентичны. Они выбирают из двух разных таблиц, а второй опускает ft.time_key из предложения WHERE. –

+0

Righ, они не то же самое. Но поскольку оба подзапроса содержат объединение в ту же таблицу 'dim_sku', вы можете попытаться преобразовать этот запрос, используя« объединение факторизации », чтобы избежать повторной проверки' dim_sk', эта ссылка описывает, как это преобразование работает: http://docs.oracle. com/cd/E16655_01/server.121/e15858/tgsql_transform.htm # BABHGGEG – krokodilko

ответ

0
  1. Измерьте время запуска.

  2. Измерьте время выполнения каждого запроса, входящего в состав оператора UNION.

  3. Индекс каждой колонки, используемой в предложении WHERE.

  4. Поместите наиболее избирательные столбцы сначала в предложение WHERE и проверьте влияние многоколоночных индексов.

  5. Обрезать бесполезные тесты. (Конечно, ft.day_of_week можно удалить из предложений WHERE.)

  6. Пересмотреть типы данных. Являются ли дни недели и хранят ключи действительно строки?

  7. Пересмотреть решение о выборе пятилетних данных за раз.

  8. Попробуйте переместить идентификационные номера продуктов во временную таблицу и присоединиться к ней.

+0

1. Даты, время, стоимостьЦена, retailЦена наиболее преобладают colmns, поэтому она появляется сразу после этого. 2.day_of_week, store_id, тип данных product_id - целые числа. 3.Combined Indx выполняется для преобладающих столбцов (данные, время, стоимостьPrice, retailPrice) 4. Вставляемый вами запрос - это точный запрос, за исключением product_id check coz, список, который он проверит, огромен. – Itachi

+0

* Преобладающий * и * выборочный * не означает одно и то же на английском языке. Вы хотите построить составной индекс на * selective * столбцах, которые используются в предложении WHERE. Мой комментарий о точном запросе был моей ошибкой - я думал, что есть несогласованные парады. –