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

时间:2015-08-19 17:20:50

标签: sql-server sql-server-2012

我正在运行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

这是执行计划 ExecutionPlan

此查询涉及三个表:Outgoing,Numbers,&amp;联系人

Outgoing是此查询处理的主表。现在只有两个索引,OutgoingID上的聚簇主键索引[PK,bigint,not null]和SmsId [varchar(255),null]上的非聚集,非唯一索引,它是从在系统中成功接收消息后,我们的文本消息提供程序。 Status列只是一个与一些不同状态(Scheduled,Queued,Sent,Failed等等)相关的整数列

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

“联系人”表格仅将个人(电话号码)与我们的某个商家联系起来,并保持号码的选择状态以及与客户/商家关系相关的其他信息。与此查询相关的唯一列是OptInStatus [bit,not null]和ContactID [PK,bigint,not null]

  

- UPDATE -

在Outgoing表上添加了一个非聚集索引,其中包含列(Scheduled,SmsId,Status),这似乎已将执行时间从2秒减少到毫秒。我将在明天检查我的性能监控软件,看看它是如何改进的。感谢大家到目前为止的帮助!

3 个答案:

答案 0 :(得分:1)

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

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

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

当您正在努力解决此问题时,缩短SmsId列可能是个好主意,除非您实际需要它长度为255个字符。最好在创建索引之前。

作为替代解决方案,您可能会考虑为传出的消息和 outgone 的消息分别创建表。然后你可以:

  • Outgoing的所有记录插入Outgone
  • 删除Outgoing中的所有记录,并使用与您当前正在执行的输出子句。

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

答案 1 :(得分:0)

  

它只是导致CPU的等待时间,特别是因为它每隔一秒运行一次。

摆脱TOP 30并且每隔一秒运行一次,而不是每隔一秒......也许每两到三分钟。

答案 2 :(得分:-2)

您可以启用sql server的最大并行度以加快处理速度