2011-07-14 80 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语句不需要的任何索引。然后努力简化那些“不存在”的条款。这些是你将获得的任何性能提升的唯一来源。尝试创建索引以加快子查询的速度,一旦你简化了它。