2016-12-29 3 views
0

У меня была аналогичная проблема позапрошлая неделя с запросом, который велся навсегда для запуска. При написании этого запроса я попытался применить некоторые из вещей, извлеченных из другого запроса, но все же выполнить его очень долго.Оптимизация запросов/исправление

При выполнении двух отдельных частей запроса требуется 2 минуты для завершения, что приемлемо, хотя быстрее будет намного лучше.

Вот мой запрос:

SELECT 
    x.entityCode 'Entity Code' 
, x.nnd_volume 'Latest Brand Volume' 
, maxDate   'Last Action Date' 
, x.Brand   'Brand Description' 
, (SELECT 
      ROUND(((SELECT (MAX(A.line_value * B.pack_volume)) 
         FROM master_data.brand_master B 
         WHERE A.brand_code = B.brand_code 
          AND A.brand_code = B.brand_code) 
       /--THIS IS NOT A BUG, JUST TRYING TO CLEARLY INDICATE THE TWO SELECTS BEING DIVIDED AND CALCULATED 
        (SELECT C.case_volume 
         FROM master_data.brand_master C 
         WHERE A.brand_code = C.brand_code 
          AND A.brand_code = C.brand_code)),2) 'brand_volume' 
     FROM am_lines.brand_module A 
     WHERE A.action_date BETWEEN DATE(DATE_SUB(CURDATE(), INTERVAL 28 DAY)) 
     AND DATE(DATE_SUB(CURDATE(), INTERVAL 0 DAY)) 
     AND A.entity_code = x.entityCode 
     AND A.brand_code = x.brandCode 
     GROUP BY A.entity_code, A.brand 
    ) 'Max Brand (28 Days)' 
FROM 
    (SELECT 
     BBM.entity_code AS entityCode  
    , MAX(action_date) AS maxDate 
    , brand AS Brand 
    , brand_code AS brandCode 
    , ROUND(((SELECT (BBM.line_value * B.pack_volume) 
     FROM master_data.brand_master B 
     WHERE BBM.brand_code = B.brand_code AND BBM.brand_code = B.brand_code) 
    /--THIS IS NOT A BUG, JUST TRYING TO CLEARLY INDICATE THE TWO SELECTS BEING DIVIDED AND CALCULATED 
    (SELECT C.box_volume 
     FROM master_data.brand_master C 
     WHERE BBM.brand_code = C.brand_code AND BBM.brand_code = C.brand_code)),2) 'brand_volume' 
    FROM 
     am_lines.brand_module BBM 
    WHERE 
     line_field_id IN (3154, 3655) 
    AND action_date BETWEEN DATE(DATE_SUB(CURDATE(), INTERVAL 28 DAY)) AND DATE(DATE_SUB(CURDATE(), INTERVAL 0 DAY))  
    GROUP BY 
    -- action_date 
     entity_code 
    , brand_code) AS X 
GROUP BY 
    x.entityCode 
, x.brand;  

SAMPLE DATA (Упаковка Объем и Box Volume просто справочная таблица, которая показывает общие единица в упаковке/коробке и используется для расчета и поэтому я не включил его в выборку данных):

entity_code | action_date| brand | line_value 
    ------------+------------+----------+----------- 
    108792  |2016-12-07 |brand 001 | 25 
    108793  |2016-12-08 |brand 002 | 36 
    108795  |2016-12-06 |brand 003 | 10 
    108796  |2016-12-05 |brand 004 | 55 
    108795  |2016-12-13 |brand 001 | 5 
    108792  |2016-12-14 |brand 003 | 2 
    108793  |2016-12-14 |brand 005 | 15 
    108796  |2016-12-16 |brand 006 | 25 

ТОКА ИСХОДОВ, что работа:

  • Каждый Выберите Qu ery Выполняется в течение нескольких минут (максимум 2) и дает желаемый результат .
  • Идентификаторы action_date и line_field_id.
  • Добавление индекса в entity_code замедляет таблицу по неизвестной причине.

ТЕКУЩИЕ ПРОБЛЕМЫ ОПЫТНЫЙ/желаемому результату:

  • Весь запуск запроса, как один берет навсегда, чтобы работать в избытке 2 часов.
  • Каждая компания будет продавать/удерживать акции ряда брендов. Мне нужно определить холдинг MAXIMUM в 28-дневном цикле, а также через месяц (Max Holding 28 Days Column in Desired set).
  • Мне нужно будет также показать последнюю инвентаризацию запасов в неделю (марка холдинга в желаемом наборе).

DESIRED РЕЗУЛЬТАТ SET VIEW:

entity_code | Last Date | brand holding | Max Holding (28 Days) |Brand 
    ------------+------------+------------------+-----------------------+----------+ 
    108792  |2016-12-27 |10    | 25     |Brand 001 
    108792  |2016-12-27 |36    | 36     |Brand 002 
    108792  |2016-12-27 |5     | 10     |Brand 003 
    108792  |2016-12-27 |25    | 55     |Brand 004 
    108792  |2016-12-27 |4     | 5     |Brand 005 
    108783  |2016-12-15 |80    | 80     |Brand 001 
    108783  |2016-12-15 |36    | 41     |Brand 002 
    108783  |2016-12-15 |12    | 12     |Brand 003 
    108783  |2016-12-15 |8     | 11     |Brand 004 
    108783  |2016-12-15 |20    | 90     |Brand 005   

QUERY PLAN (store_code такой же, как код объекта, я просто переименовал его с целью поста): QUERY PLAN (store_code is the same as entity code, I just renamed it for the purpose of the post):

Я скорректированной мой индекс должен быть на action_date и line_field_id.

SHOW CREATE TABLE Image: enter image description here

+0

бренд таблица имеет несколько миллионов строк. И индекс помещается в код сущности. –

+0

вы можете предоставить нам план запроса? – Moudiz

+0

Query Plan Added - Обратите внимание, что store_code - это то же самое, что и код сущности. Я только изменил имя столбца для цели сообщения. –

ответ

0

Позвольте мне дать вам несколько советов. Если их недостаточно, давайте начнем.

  • Многие из подзапросов, которые у вас есть, не нужны; вам будет лучше с JOINs.
  • CURDATE не успевает, поэтому он не нуждается в преобразовании в DATE: DATE(DATE_SUB(CURDATE(), INTERVAL 28 DAY)) ->(CURDATE() - INTERVAL 28 DAY)
  • Пожалуйста, используйте какое-то отступ, чтобы помочь дифференцировать подзапросы.
  • Что гарантирует, что (SELECT ROUND... возвращает только одну строку?Возможно, GROUP BY избыточен?
  • Иногда вы используете brand, иногда brand_code; это «ошибка»?
  • Добавьте индексы ниже; Я не могу сказать, какие из них были бы лучшими.

Индексы:

INDEX(action_date, entity_code, brand_code) 
INDEX(line_field_id, action_date) 
INDEX(entity_code, brand, action_date) 

Addenda

  • Не используйте VARCHAR для значений, которые необходимо вычислить с, например MAX(A.line_value * B.pack_volume).
  • Не слепо используйте (255) на VARCHAR, используйте «разумные» максимальные длины.
  • У вас есть PRIMARY KEY на любой таблице InnoDB.
  • Несоответствующие типы, такие как line_field_id IN (3154, 3655) с VARCHAR(900), предотвращают разумную оптимизацию и могут дают «неправильные» результаты.

(я не буду рассматривать этот вопрос дальше, пока по крайней мере, типов данных «фиксированные».) Модуль

+0

Спасибо за отзыв. Я попытаюсь выполнить некоторые из предлагаемых вами изменений. Я просто хочу спросить, где вы предлагаете использовать JOINS вместо подзапросов? Я заметил, что с индексом на моем entity_code также немного замедлился мой запрос, поэтому я изменил его (не уверен, почему это произойдет). Поэтому я изменил свой индекс на line_field_id и action_date. –

+0

«изменил мой индекс» - я надеялся, что вы добавите индексы, а не измените один индекс. –

+0

Пожалуйста, предоставьте 'SHOW CREATE TABLE'. С ними, возможно, я могу догадаться, как использовать 'JOIN'. –

 Смежные вопросы

  • Нет связанных вопросов^_^