繁体   English   中英

SQL Server 2012:一个查询中的SELECT和UPDATE会降低性能

[英]SQL Server 2012 : SELECT and UPDATE in one query slow performance

我正在运行SQL Server 2012,这一查询正在破坏我的数据库性能。

我的文本消息提供程序不支持预定的文本消息,因此我有一个文本消息引擎,该引擎从数据库中提取消息并在预定的时间发送它们。 我将这个查询放在一起可以从数据库中获取消息,还可以更改它们的状态,以免再次被拾取。

该查询工作正常,这仅导致CPU上的等待时间,特别是因为它每隔一秒钟运行一次。 我安装了一个数据库性能软件,它说此查询占实例执行时间的92%。 该软件还表示,每执行一次就执行347,267个逻辑读取。

关于如何使此效果更好的任何想法?

我应该选择一个临时表并在返回结果之前更新这些结果吗?

这是当前查询:

    UPDATE TOP (30) dbo.Outgoing
    SET Status = 2
    OUTPUT INSERTED.OutgoingID, INSERTED.[Message], n.PhoneNumber, c.OptInStatus
    FROM dbo.Outgoing o
    JOIN Numbers n on n.NumberID = o.NumberID
    LEFT JOIN Contacts c on c.ContactID = o.ContactID
    WHERE Scheduled <= GETUTCDATE() AND SmsId IS NULL AND Status = 1

这是执行计划 执行计划

此查询涉及三个表:去电,电话号码和联系方式

发送是该查询处理的主表。 现在只有两个索引,一个是OutgoingID [PK,bigint,not null]上的群集主键索引,另一个是SmsId [varchar(255),null]上的非群集,非唯一索引,它是从在系统中成功接收到消息后,我们的文本消息提供者。 状态列只是一个整数列,它与几种不同的状态(计划的,已排队的,已发送的,失败的,等等)相关

数字只是一个简单的表,我们在其中存储唯一的手机号码,该号码的某些不同格式以及一些识别客户的基本信息,例如名字,运营商等。它在NumberID [bigint]上只有一个聚集的主键索引。 PhoneNumber列只是一个varchar(15)。

联系人表仅将个人(电话号码)连接到我们的一位商人,并保持该号码的选择状态以及与客户/商人关系有关的其他信息。 与该查询相关的唯一列是OptInStatus [位,不为null]和ContactID [PK,bigint,不为null]

-更新-

在Outgoing表上使用列(Scheduled,SmsId,Status)列添加了非聚集索引,这似乎将执行时间从2秒以上减少到了毫秒。 我明天将使用性能监控软件进行检查,以了解其改进情况。 谢谢大家到目前为止的帮助!

正如一些评论者已经指出的那样,您需要在dbo.Outgoing表上dbo.Outgoing一个新索引。 服务器正在努力寻找要更新/输出的行。 这很可能是问题所在:

WHERE Scheduled <= GETUTCDATE() AND SmsId IS NULL AND Status = 1

为了提高性能,您应该在dbo.Outgoing上创建这些索引所在的位置。 这将使Sql Server更容易找到正确的行。 另一方面,由于将有一个新索引在更新时需要注意,因此它将为实际更新创建更多工作。

在进行此操作时,缩短SmsId列可能是一个好主意,除非您实际需要将其长度设置为255个字符。 最好在创建索引之前。

正如你可能想具有用于是传出和那些outgone消息单独的表的替代解决方案。 那么你也能:

  • 从插入所有记录OutgoingOutgone
  • 像您当前正在执行的那样,使用output子句从Outgoing删除所有记录。

确保insertdelete操作是在一个事务中完成的,否则您很快就会在数据库中出现奇怪的不一致之处。

这只是在CPU上引起等待时间,特别是因为它每隔一秒运行一次。

摆脱TOP 30并使其运行的频率要比每隔一秒钟一次(可能每两或三分钟一次)少得多。

您可以启用sql服务器的最大并行度,以加快处理速度

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM