下面是一个更新查询,用于更新包含大约40000条记录的表:
UPDATE tableName
SET colA = val, colB = val
WHERE ID IN (select RecordIDs from tableB where needUpdate = 'Y')
执行上述查询时,我发现以下查询花了~15秒
SELECT RecordIDs
FROM tableB
WHERE needUpdate = 'Y'
但是当我拿走where子句(即update tableName set colA = val, colB = val
)时,查询运行顺利。
为什么会这样?有没有办法缩短执行时间?
编辑:
以下是两个表格的结构:
tableName:
ID int,
VehicleBrandID int,
VehicleLicenseExpiryDate nvarchar(25),
LicensePlateNo nvarchar(MAX),
ContactPerson nvarchar(MAX),
ContactPersonID nvarchar(MAX),
ContactPersonPhoneNumber nvarchar(MAX),
ContactPersonAddress nvarchar(MAX),
CreatedDate nvarchar(MAX),
CreatedBy nvarchar(MAX)
PRIMARY KEY (ID)
tableB:
RowNumber int
RecordIDs int
NeedUpdate char(1)
PRIMARY KEY (RowNumber)
被修改
屏幕截图是更新查询的执行计划
答案 0 :(得分:2)
我想你是以下两种情况之一:
1 / STATISTICS are not updated由于您最近在表中进行了一些修改。在这种情况下,您应该执行此操作:
UPDATE STATISTICS tableB
2 /我想a wrong query plan is used,我建议执行此操作以强制重新编译查询:
SELECT RecordIDs
FROM tableB
WHERE needUpdate = 'Y'
OPTION (RECOMPILE)
告诉我们结果,我们会详细介绍。
答案 1 :(得分:2)
执行计划显示您正在使用表变量并且缺少有用的索引。
将现有PK保留在@output
DECLARE @output TABLE (
ID INT PRIMARY KEY,
VehicleBrandID INT,
VehicleLicenseExpiryDate NVARCHAR(25),
LicensePlateNo NVARCHAR(MAX),
ContactPerson NVARCHAR(MAX),
ContactPersonID NVARCHAR(MAX),
ContactPersonPhoneNumber NVARCHAR(MAX),
ContactPersonAddress NVARCHAR(MAX),
CreatedDate NVARCHAR(MAX), /*<-- Don't store dates as strings*/
CreatedBy NVARCHAR(MAX))
并将 new 索引添加到@tenancyEditable
DECLARE @tenancyEditable TABLE (
RowNumber INT PRIMARY KEY,
RecordIDs INT,
NeedUpdate CHAR(1),
UNIQUE (NeedUpdate, RecordIDs, RowNumber))
使用这些索引进行以下查询
UPDATE @output
SET LicensePlateNo = ''
WHERE ID IN (SELECT RecordIDs
FROM @tenancyEditable
WHERE NeedUpdate = 'Y')
OPTION (RECOMPILE)
可以生成更高效的外观
此外,您应该使用适当的数据类型,而不是将所有内容存储为NVARCHAR(MAX)
。个人姓名最多不需要nvarchar(100)
,CreatedDate
应该存储为date[time2]
。
答案 2 :(得分:0)
您可以使用内部联接而不是IN子句。
update t
set
t.colA = val, t.colB = val
From tablename
inner join tableb x on
t.id = x.recordid
where x.needUpdate = 'Y'
虽然UPDATE...FROM
语法在某些方面至关重要
情况下,我更喜欢使用
子查询(通过使用IN子句)
可能的。
答案 3 :(得分:0)
这是另一种选择。在您的环境中尝试是值得的,因为已经证明其他人可以更快。
MERGE INTO tableName tn
USING (
SELECT recordIDs
FROM tableB
WHERE needUpdate = 'Y'
) tb
ON tn.ID = tb.recordID
WHEN MATCHED THEN
UPDATE
SET colA = tb.val,
colB = tb.val;
编辑: 我并不认为这在每种情况下或在每个设置/环境中都更快 - 只是值得一试,因为它对我和我曾经合作或阅读的其他人有用。