2017-08-21 19 views
0

こんにちは、誰かが私のSQL理論を助けることを望んでいます。私は、複数のテーブルからの結合を使用する一連のレポートを作成する必要があります。これらのレポートは私が望むよりもはるかに低速で実行されており、私の知識は壁に打ちのめされていますが、Googleで何かを見つけることはできませんが、私はSQLを最適化したいと考えています。SQL複数テーブルの結合 - 最適な最適化

私はここに誰かが私にいくつかのベストプラクティスのガイダンスを与えることを望んでいます。それは私がインナー正方形でブルーのアイテムに参加することを理解大幅にデータを削減

Items INNER JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square' 
      LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID 
      LEFT JOIN ItemDates ON Items.ItemID = ItemDates.ItemID 
WHERE ItemDates.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017' 

後で合流する行数が中に含ま減らすために戻ってくるよう

は基本的に私は、結果セットにフィルタを適用しようとしていますこの時点で設定しますか?

また、Where句は実行時にデータセットを減らすのに十分なインテリジェントなことも理解していますか?私は間違っていますか?すべてのデータを返してから、そのデータをフィルタリングするだけですか?

この種のクエリを高速化する方法についてのガイドラインは素晴らしいと思いますが、インデックスなどは既に導入されています。残念なことに、データベースは実際には他の人によって見直されており、データベースに基づいてレポートを作成しています。これは、データそのものではなく、クエリを最適化できることを制限しています。

この時点では、SQLでデータをフィルタリングし、実際に使用されているデータセットを減らし、単純にフィルタリングするさまざまな方法をSQLがどのように処理するかに関する知識を向上させることができました。すべての指導は非常に高く評価されるでしょう!

+0

'インデックスのようなものがすでに置かれています。 '...あなたはインデックス作成に関してあなたが行ったことを表示/伝えることができますか? –

+0

こんにちはティム、物事の側面は私の送金の外ですが、本質的に、すべてのItemIDフィールドなどの主キーフィールドにインデックスが存在することがわかります。残念なことに、データベースは実際には他の人によって見直されており、データベースに基づいてレポートを作成しています。これは、データそのものではなく、クエリを最適化できることを制限しています。 – SqlQuery123

答えて

0

主キーはすべて索引付けされていると述べましたが、主キーフィールドの場合は常にそうです。この恩恵を受ける現在のクエリの唯一の部分は、Itemsの最初の結合です。他の結合およびWHERE句の場合、これらの主キーフィールドは使用されていません。

この特定のクエリのために、私は次のインデックスをお勧めします:ItemHistory表について

ALTER TABLE BlueItems ADD INDEX bi_item_idx (ItemID, shape) 
ALTER TABLE ItemHistory ADD INDEX ih_item_idx (ItemID) 
ALTER TABLE ItemDates ADD INDEX id_idx  (ItemID, ManufactureDate) 

、インデックスih_item_idxItemID外部キーを含む加入スピードアップする必要があります。同じ名前の列も他の2つの結合に関係しているため、他のインデックスの一部です。複合インデックス(すなわち複数の列を含むインデックス)の理由は、結合またはWHERE節に現れるすべての列をカバーしたいからです。

+0

こんにちはTim、 アドバイスをいただきありがとうございますが、クエリレベルでどのように動作するかについて詳しく知りたいと思っています。インデックスを最適化しても、WHERE句が一般的には結合を行い、その段階で関連するデータのみを含めるよりも使用する方が良いか悪いのだろうかと思います。私は、どのくらいのデータが処理されているのか、そしてそのようなことにどのように影響するかを知りたいと思っています。 – SqlQuery123

+0

あなたは 'WHERE'節に1つの条件しかないので、順序は無関係でなければなりません(そして、私は一般的に重要ではないと思います)。リンゴとオレンジの結合は 'WHERE'との比較です。彼らは非常に異なるものです。現時点では、インデックスを追加するだけで、現在のパフォーマンスに対して唯一大きな改善が得られる可能性があります。 –

0

日付がパラメータとして渡されている場合は、これらのコメントは、それがあるパラメータスニッフィングかもしれません(私は彼らは推測している)...本当に

コメントに置くための答えが、大きすぎるではありません問題の原因となります。クエリが悪い計画を使用している可能性があります。

これは特に、between演算子を使用した場合によく見られます。クエリーの末尾にOPTION(RECOMPILE)を追加してみてください。これは直感的ではないように見えるかもしれませんが、試してみてください。コンパイルされたクエリは、再コンパイルするよりも速くなければなりませんが、悪い計画が使用されていると、状況が遅くなる可能性があります。

また、ItemDatesが大きい場合は、yuorでフィルタ処理した結果を一時表にダンプして結合してください。あなたが唯一持っているアイテムを選択しているように私はまた、(暗黙的に内部結合)JOINLEFT JOINあることから、JOINに変更

SELECT * INTO #id FROM ItemDates i WHERE i.ManufactureDate BETWEEN '01/01/2017' AND '01/05/2017' 

変更

SELECT * 
    FROM Items 
    JOIN BlueItems ON Items.ItemID = BlueItems.ItemID AND BlueItems.shape = 'square' 
    JOIN #id i ON Items.ItemID = i.ItemID 
    LEFT JOIN ItemHistory ON Items.ItemID = ItemHistory.ItemsID 

ようなものにするためにあなたのメインクエリItemDatesに一致しますのでLEFTに参加しても意味がありません。