2016-12-29 42 views
0

私は最後に実行するために永遠に奪取されていたクエリを前に週に同様の問題がありました。このクエリを書く際に、他のクエリから学んだことのいくつかを適用しようとしましたが、実行に非常に時間がかかります。クエリの最適化/固定

クエリの2つの部分を実行すると、それぞれが完了するまでに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;  

サンプルデータ(パックボリュームとボックスボリュームはパック/ボックスに全単位を示し、計算に使用されるだけで、参照テーブルであると私はそのためではない持っています)サンプルデータでそれを含める:

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 

WORK CURRENTアウトカム:

  • 各選択屈原ery数分で実行し(最大で2)、 の結果が得られます。
  • action_dateとline_field_idにはインデックスが付けられています。
  • entity_codeにインデックスを追加すると、何らかの不明な理由によりテーブルが減速します。 1は2 時間を超えて、実行するように永遠に取るよう

    • クエリ全体の実行:/望ましい結果を経験し

    現在の問題。

  • 各エンティティは、多数のブランドの在庫を販売/保持します。私は、28日周期で1月に最大ストックを保持することを決定する必要があります。
  • また、最新の株価情報を表示する必要があります。

望ましい結果のセットビュー:

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   

クエリ・プラン(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 TABLEイメージを作成します:enter image description here

+0

ブランドモジュールのテーブルには、数百万行を持っています。エンティティコードにインデックスが付けられます。 –

+0

あなたは私たちにクエリプランを提供できますか? – Moudiz

+0

クエリプランが追加されました - store_codeはエンティティコードと同じものです。私は投稿の目的のために列名を変更しました。 –

答えて

0

は、私はあなたにいくつかのヒントを与えてみましょう。十分でない場合は、やり直してください。

  • 多くのサブクエリは必要ありません。あなたはJOINsの方が良いでしょう。
  • CURDATEは時間をしていないので、DATEに変換する必要はありません。DATE(DATE_SUB(CURDATE(), INTERVAL 28 DAY)) - >(CURDATE() - INTERVAL 28 DAY)
  • サブクエリを区別を助けるためにインデントのいくつかの種類を使用してください。
  • (SELECT ROUND...は1行しか返さないことを保証するものはありますか?おそらくGROUP BYは冗長でしょうか?
  • brand、時にはbrand_codeを使用することもあります。これは「バグ」ですか?
  • 以下のインデックスを追加してください。どちらが最善かは分かりません。

インデックス:

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

補遺

  • は、MAX(A.line_value * B.pack_volume)として、あなたがして計算する必要がある値のためVARCHARを使用しないでください。
  • 盲目的に(255)VARCHARに使用しないで、「合理的な」最大長を使用してください。
  • すべてのInnoDBテーブルにPRIMARY KEYがあります。
  • line_field_id IN (3154, 3655)と一致しないタイプがVARCHAR(900)であると、妥当な最適化が妨げられ、がの場合があります。が「間違った」結果をもたらします。

は(私は、少なくともデータ型は「固定」されるまで、さらにこの質問を考慮しません。)

+0

フィードバックいただきありがとうございます。あなたが提案した変更のいくつかを実装しようとします。サブクエリではなくJOINSを使用することをお勧めする場所を尋ねたいだけです。 私のentity_codeにインデックスを付けると、クエリがかなり遅くなってしまいましたので、私はそれを変更しました(その理由は分かりません)。 したがって、私のインデックスをline_field_idとaction_dateに変更しました。 –

+0

"私のインデックスを変更しました" - 私はあなたが単一のインデックスを変更するのではなく、インデックスを追加することを望んでいた。 –

+0

'SHOW CREATE TABLE'を提供してください。それらを使って、 'JOIN'の使い方を推測できます。 –