2011-07-14 10 views
0

私は2つのテーブルを持っています(「キー」は約6つのフィールドで構成され、「統計」は約65のフィールドで構成されています)。SQLクエリを最適化する方法は?

フレーズテキストを複製せずに両方のテーブルに行を挿入したいとします。私は次のようなものを使用します:

UPDATE Keys SET CommandType = 'ADDED', CommandCode = @CommandCode WHERE 
KeyText = @KeyText AND Tab_ID = @TabID AND CommandType = 'DELETED'; 

INSERT INTO Keys (IsChecked, KeyText, AddDateTime, Tab_ID, KeySource_ID, CommandCode, CommandType) 
SELECT 0, @KeyText, datetime(), @TabID, @KeySourceID, @CommandCode, 'ADDED' 
WHERE NOT EXISTS (SELECT 1 FROM Keys WHERE Tab_ID = @TabID AND KeyText = @KeyText); 

INSERT INTO Statistics (Key_ID) 
SELECT ID FROM Keys WHERE KeyText = @KeyText AND Tab_ID = @TabID AND (CommandType IS NULL OR CommandType <> 'DELETED') AND 
NOT EXISTS (SELECT 1 FROM Statistics WHERE Key_ID = (SELECT ID FROM Keys WHERE KeyText = @KeyText AND Tab_ID = @TabID AND (CommandType IS NULL OR CommandType <> 'DELETED') LIMIT 1)); 

どうすれば最適化できますか?このクエリフィールドで使用されるすべてのインデックスを作成します。たぶんあなたは私にいくつかのソリューションをお勧めできますか?

私の悪い英語を助けてくれてありがとう。

+1

最適化が必要なのは何ですか?挿入に時間がかかりますか? – Randy

+1

SQLプロファイラを試しましたか? –

+0

うん!問題は私のテーブルのインデックスが悪いことです。私はそれを再構築し、いくつかのクエリパラメータを静的なコンテンツに置き換えて、うまくいく! ありがとうございます! – Dmitriy

答えて

0

テーブルのインデックスに問題があります。私はそれを再構築し、いくつかのクエリパラメータを静的なコンテンツに置き換えて、うまくいく!

1

挿入/更新文を1つの文にMERGE文を組み合わせることができます。 キーの変更を統計にコピーする場合は、OUTPUT文を使用できます。

質問にインデックスを追加すると、その効果についてコメントできるようになりますが、基本的には、where句のすべての列を含む各テーブルに単一のインデックスが必要です。 where句に含まれていない選択項目のインクルード列を使用したいとします。

最適化する最適な方法は、推定/実際のクエリプランを取得し、クエリのどの部分が遅いかを確認することです。 SQL Serverでは、これは「クエリ」メニューから実行されます。基本的には、「スキャン」とは何かを探します。つまり、インデックスがないことを意味します。 "シーク"は良いです。

ただし、クエリプランは、微調整に最も役立ちます。この場合、(merge/outputのような)別のアルゴリズムを使用すると、より劇的な違いが生じます。 SQL Serverでの

、結果は次のように多少なります

INSERT INTO [Statistics] (ID) 
SELECT ID FROM 
(
    MERGE [Keys] AS TARGET 
    USING (
     SELECT @KeyText AS KeyText, @TabID AS TabId, @CommandCode AS CommandCode, @KeySourceID AS KeySourceID, 'Added' AS CommandType 
    ) AS SOURCE 
    ON (target.KeyText = source.KeyText AND target.Tab_Id = @TabID) 
    WHEN MATCHED AND CommandType = 'DELETED' THEN 
     UPDATE SET Target.CommandType = Source.CommandType, Target.CommandCode = Source.CommandCode 
    WHEN NOT MATCHED BY TARGET THEN 
     INSERT (IsChecked, KeyText, AddDateTime, Tab_Id, KeySource_ID, CommandCode, CommandType) VALUES (0, KeyText, getdate(), TabId, KeySourceId, CommandCode, CommandType) 
    OUTPUT $Action, INSERTED.ID 
) AS Changes (Action, ID) 
WHERE Changes.Action = 'INSERT' 
AND NOT EXISTS (SELECT 1 FROM Statistics b WHERE b.ID = Changes.ID) 
+0

良い例がありますが、SQliteデータベースを使用しています:( – Dmitriy

+0

ええ!問題はテーブルのインデックスが悪いため、再構築していくつかのクエリパラメータを静的コンテンツに置き換えるとうまくいきます! 助けてくれてありがとう! – Dmitriy

1

は、インデックスを作成するインデックスはデータと一緒に更新しなければならないため、挿入と更新クエリが遅くなります。特定の挿入ステートメントを最適化するには、典型的なselectステートメントでは必要のないインデックスを取り除きます。次に、「存在しない」句を単純化する作業を行います。これらは、あなたが得ようとしている業績向上の唯一の源泉です。サブクエリを単純化したら、そのサブクエリを高速化するインデックスを作成してみてください。