我们在使用微软企业库3.0的.net应用程序(Windows服务)中调用的存储过程遇到了性能问题。SQL Server过程只是检查记录是否存在,如果记录不存在,则将记录插入到表中,否则只返回记录。
表中有以下列:
create table AlarmLog
(
Id bigint
MessageId int
MessageTime datetime
ControllerId int
InterfaceHardwareId int
IDType int
MapId int
RelatedEmployeeId int
RelatedCardId int
);
Id
列是主键,其上有聚集索引。
作为业务规则,在插入记录时,我们需要确保组合(MessageId, MessageTime, ControllerId, InterfaceHardwareId, IDType, MapId
)是唯一的。因此,我们设置了一个if exists
条件来检查组合是否已经存在。此条件检查耗费了很长时间。
我们已经尝试在MessageId, MessageTime, ControllerId, InterfaceHardwareId, IDType, MapId
上添加一个非聚集索引。
在我们实验室的一台测试服务器上,大约有30,000,000条记录,即使条件满足,使用相同的.net服务,它插入400+行的速度也要快得多。我们还尝试添加了上述非聚集索引,并发现了一些明显的改进。
在生产服务器上,大约有300,000+记录,当我们在条件适当的情况下从.net应用程序(Windows服务)逐行插入时,它每分钟只插入10到20行。如果我们删除条件检查,那么插入的行数将达到每分钟300到400+行。我们还尝试添加/删除上面的非聚集索引,但没有发现任何明显的改进。
因此,我们暂时禁用了它。有趣的是,如果我们从SQL Server Management Studio运行存储过程以插入1条记录,则没有问题,我们还检查了实际的执行计划,没有发生表扫描,存储过程也没有花费任何时间。
4.0
还尝试了其他性能调优活动:重建、重组、更新统计信息、存储过程重新编译和参数嗅探。然而,似乎什么都不起作用。
我们现在有麻烦了。我们找不到任何替代方案。如果你能给我们一些建议/指导,那将是很有帮助的。
提前谢谢。Ujjal
发布于 2018-06-01 02:49:54
添加唯一的约束而不是索引,如下所示:
alter table AlarmLog add constraint uq_alarmlog_row unique (
MessageId, MessageTime, ControllerId,
InterfaceHardwareId, IDType, MapId);
这将自动拒绝插入其值与此列组合完全匹配的新行。
这在性能方面也应该是快速的。不需要调用一个过程来运行以前的select
并检查这些值是否存在。
只要运行一个简单的SQL insert
,问题就解决了。
发布于 2018-06-01 03:00:59
您的生产环境可能已接近带宽上限。由于当前在其中运行的其他操作。正在处理的查询数量使您的网络趋于饱和。
https://stackoverflow.com/questions/50630874
复制相似问题