2011-07-14 120 views
0

我有2個表格('鍵'由大約6個字段組成,'stats'由大約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 Profiler? –

+0

是啊!問題出在我的表格的糟糕索引上。我重構它,並用靜態內容替換一些查詢參數,它效果很好! 感謝您的幫助! – Dmitriy

回答

0

問題出在我的表的不好的索引上。我重構它,並用靜態內容替換一些查詢參數,它效果很好!

1

可以使用MERGE語句將插入/更新語句組合成單個語句。 如果要將密鑰的修改複製到統計信息中,可以使用OUTPUT語句。

您必須將索引添加到問題中才能評論它們的有效性,但基本上需要在每個包含where子句中所有列的表上使用單個索引。您希望使用包含列來處理select中不在where子句中的任何內容。

優化的最佳方法是獲取估計/實際查詢計劃並查看查詢的哪些部分較慢。在SQL Server中,這是從「查詢」菜單完成的。基本上,看看有什麼說「掃描」,這意味着你錯過了一個索引。 「尋求」是好的。

但是,查詢計劃對於微調很有幫助。在這種情況下,使用不同的算法(如合併/輸出)將會產生更大的差異。

在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

是啊!問題出在我的表的錯誤索引。我重建它,並用靜態內容替換一些查詢parametrs,它很好! 感謝您的幫助! – Dmitriy

1

創建索引減慢INSERT和UPDATE查詢,因爲索引必須與數據一起更新。要優化特定的插入語句,請刪除典型的select語句不需要的任何索引。然後努力簡化那些「不存在」的條款。這些是你將獲得的任何性能提升的唯一來源。嘗試創建索引以加快子查詢的速度,一旦你簡化了它。