我知道SQL表上的INSERT可能由于多种原因而变慢:


表上存在INSERT TRIGGER
必须检查很多强制约束(通常是外键)
在表中间插入一行时,页面会在聚集索引中拆分
更新所有相关的非聚集索引
从表上的其他活动进行阻止
IO写响应时间很差
...我错过了什么?

如何确定在我的特定情况下哪个原因?我如何衡量分页与非聚集索引更新与其他所有内容的影响?

我有一个存储过程,一次可插入约10,000行(从临时表中),大约需要每1万行90秒。这太慢了,因为它会导致其他spid超时。

我已经查看了执行计划,并且看到了FK查找中的INSERT CLUSTERED INDEX任务和所有INDEX SEEKS,但是仍然无法确定为什么要花这么长时间。没有触发器,但是表中确实有少数FKey(似乎已正确索引)。

这是SQL 2000数据库。

评论

是否在数据文件上启用了自动扩展?使用默认配置可能会导致性能问题。

我们是在谈论使用探查器吗? msdn.microsoft.com/zh-CN/library/ms187929.aspx

@Larry:数据文件具有很大的可用空间,所以我认为数据文件的增长不是问题。不过,这是添加到“检查事项”列表中的好方法。

@ user210:对语句完成进行概要分析仅向我显示它花费了90秒,但没有告诉我原因。除非您认为还有其他事件更能说明问题。

#1 楼

您可以查看一些内容...

将批处理大小从10000减小到较小的值,例如2000或1000(您没有说行的大小)。

尝试打开IO Stats来查看FK查询占用了多少IO。

插入时发生什么等待(master.dbo.sysprocesses)?

让我们从这里开始,看看我们的去向。

评论


减小批次大小确实有帮助(1000条记录大约需要25秒)。这可能是我们当前的“解决方法”。我将查看是否可以确定IO Stats并等待(该作业是在客户端有要处理的文件时按需运行的,因此我无法始终预测该作业实际何时运行)。

– BradC
2011年1月10日21:36

#2 楼

布拉德,

您应该检查查询的等待状态。对于SQL2000,您可以使用DBCC SQLPERF(“ waitstats”)语法来获取这些详细信息。

#3 楼

我可以说在分析查询性能时要寻找的内容。也许有帮助。


分析查询执行计划并检查索引扫描,表扫描,sql数据类型的convert_implicit函数的使用情况,并行性。
使用SET STATISTICS IO ON和SET STATISTICS TIME ON运行查询,以查看执行时间和每个插入的io读写。
从sysprocesses中检查您的会话spid的等待时间。
运行分析器并选择标准模板。选择以下各项:性能统计信息(如果重复进行,则您的计划将被编译很多次-不好),RPC:已完成,SQL:批处理已完成和SQL:批处理启动。向他们添加列行数,以查看批处理中的确切行数。筛选结果以仅查看查询。
最后从Windows perfmon收集“页面预期寿命”计数器,如果该计数器低于300(5分钟),则SQL内存不足。还收集磁盘计数器:磁盘队列长度,磁盘时间(您的数据文件驱动器),磁盘时间(您的日志文件驱动器),以查看磁盘是否受到压力。


#4 楼

尝试使用:

SET STATISTICS IO ON




SET STATISTICS PROFILE ON


统计信息IO


/>可以告诉您哪些
表正在执行最多的
表扫描,逻辑读取和物理
读取(我使用这三个来关注
查询计划的一部分需要最优化)


统计信息配置文件


将主要返回查询计划
以表格格式,然后可以在IO和CPU列上查找
查询中花费最多的内容
(是在您的临时表上进行的表格扫描
表与将其插入到群集键等中的排序进行比较...)