【问题标题】:How to avoid table scan on SQL Server in this situation在这种情况下如何避免 SQL Server 上的表扫描
【发布时间】:2020-07-07 20:43:41
【问题描述】:

有两个表,CostsLogsCosts表中的数据可以是百万行,Logs表中可以是数十亿行。

我需要在生产环境中的服务任务中更新Costs 表中的CostBy 列,每次运行100 条记录。

CREATE TABLE Cost
(
    C_PK uniqueidentifier primary key not null,
    C_CostBy varchar(3) not null
)

CREATE TABLE Logs
(
    L_PK uniqueidentifier primary key not null,
    L_ParentTable varchar(255) not null,  -- Table Cost and other table's name
    L_ParentID uniqueidentifier not null, -- Cost's pk and other table's pk
    L_Event varchar(3) not null, -- Part are 'ADD' and other event types
    L_User varchar(3) not null 
 )

CREATE NONCLUSTERED INDEX [L_ParentID] 
    ON [dbo].[Costs] ([L_ParentID] ASC)

这是原始的更新声明:

UPDATE TOP(100) Costs
SET CostBy = ISNULL(L_User, '~UK')
FROM Costs
LEFT JOIN Logs ON L_ParentID = C_PK AND L_Event = 'ADD'
WHERE CostBy = ''

但是,该语句引入了一个巨大的性能问题,Costs 表中的表扫描成本很高。

我的问题是如何避免Costs表中的表扫描或者如何优化更新语句?

提前致谢。

【问题讨论】:

  • 您显示的 T-SQL 无法编译,请发布正确的代码。此外,几行样本数据会很好。
  • 只更新前 100 行的原因是什么?这是功能要求,还是您这样做是为了一次更新几个结果/进行多次调用?
  • 这是一次性任务,还是会定期使用此代码(即是否需要每 10 分钟/每次有人执行某些操作/等时更新成本表,或者这只是纠正临时任务中的一些无效数据吗?

标签: sql-server database-performance query-performance full-table-scan


【解决方案1】:

您可能想尝试以下方法。

首先,在 Logs 上创建索引,包括所有相关列:

CREATE INDEX ix ON Logs 
(
  L_Parent_ID -- join condition, variable
)
INCLUDE 
(
  L_User -- no filter condition, but you use it your update
)
WHERE 
(
  L_Event = 'ADD' -- join condition, constant
)

如果这是一个唯一索引,即。对于给定的父 ID,ADD 事件只会存在一行,请确保将其设为唯一索引,因为它可以显着提高性能。

其次,这是一个命中注定的情况,您可以尝试使用 CostBy (CostBy) 索引,因为您只是在寻找要更新的空 CostBy 值。该索引需要根据您的查询进行更新,因为它正在更新它,因此它可能会减慢您的查询速度而不是加快它的速度。这取决于许多因素。

如果您有企业许可证,请同时使用WITH (DATA_COMPRESSION = PAGE),它可以显着提高 IO 时间,但会以 CPU 为代价。这取决于哪个是您的瓶颈。

此外,根据您数据的性质,更新统计信息可能会改进您的查询。如果其中 CostBy = '' 的行数与其他值不成比例,您可能会从该字段的完整统计信息中受益。如果您只需要它们来执行此特定查询,请考虑 NORECOMPUTE,这一次。

CREATE STATISTICS st_Costs_CostBy
ON Costs (CostBy)  
WITH FULLSCAN, NORECOMPUTE;  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2011-01-09
    • 2020-10-30
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多