更新查询需要 2 秒来更新表
Posted
技术标签:
【中文标题】更新查询需要 2 秒来更新表【英文标题】:Update query is taking 2 seconds to update the table 【发布时间】:2016-09-27 20:16:46 【问题描述】:我在 SQL DB Server 中有一个表。 (表名称:材料,6 列)。它包含 260 万条记录。我需要根据两列值更新此表。对于更新,系统需要 2 秒。
请帮助我如何优化下面的查询。
UPDATE Material
SET Value = @Value,
Format = @Format,
SValue = @SValue,
CGroup = @CGroup
WHERE
SM = @SM
AND Characteristic = @Characteristic
【问题讨论】:
那么有什么问题,如果你百万数据,那么简单的逻辑它需要时间来更新? 2秒也不算多。您是否在 where 子句中使用索引列,如主键列。如果没有,那将带来好处。 您可以通过提供查询计划来提高获得有用答案的机会。 因为我会连续运行SQL查询命令。每天我需要运行 88000 次查询来更新或插入此表中的行。如果一个查询需要 2 秒,那么我每天不能运行 88000 个查询。请帮助我。 (致 Ajay2707) @MuthukrishnanR 您可以将更改排队并分批运行它们,而不是一次运行一个吗?如果您可以将其减少到 88 次运行 1000 次更新(甚至 880 次运行 100 次更新),则可以完全避免问题。 你可以试试批量更新 【参考方案1】:您确实需要提供查询计划,然后我们才能确定地告诉您什么(如果有的话)可能会有所帮助。
话虽如此,我要检查的第一件事是计划是否显示大量时间进行表扫描。如果是这样,如果它是一个大表,则可以通过在 SM
和 Characteristic
上添加索引来显着提高性能 - 这将允许分析器使用索引来执行索引查找而不是表扫描,并且可以改进性能显着。
【讨论】:
我应该对 SM 和 Charactersric 使用 NON-CLUSTER 索引吗? 我的查询计划我会连续运行SQL查询命令。每天我需要运行 88000 次查询来更新或插入此表中的行。如果一个查询需要 2 秒,那么我每天不能运行 88000 个查询。请帮我解决这个问题 @MuthukrishnanR 我不知道。您将不得不查看该表是否在其他情况下被频繁查询,它当前是否具有聚集索引,以及向它们添加索引是否有意义。但是,如果它们不是唯一的,我会非常谨慎地将其设为聚集索引,即使它们是唯一的,我也会谨慎。 @MuthukrishnanR 这不是我所说的查询计划的意思。 SQL 服务器管理工作室通常可以为您生成查询计划 - 有一个关于如何做的谷歌 - 它应该看起来像某种图像。 我为“SM”应用了聚集索引,为“Characterstic”应用了非聚集索引。现在查询执行速度非常快。谢谢杰夫。但是我有一个疑问,聚集和非聚集索引列应该是唯一的吗?【参考方案2】:当您获得大数据时,一些调整可以提高查询性能
(1)如果要更新的列有索引,则删除索引
(2) 小批量执行更新
DECLARE @i INT=1
WHILE( @i <= 10 )
BEGIN
UPDATE TOP(20000) Material
SET Value = @Value,
Format = @Format,
SValue = @SValue,
CGroup = @CGroup
WHERE
SM = @SM
AND Characteristic = @Characteristic
SET @i=@i + 1
END
(3) 禁用删除触发器(如果有)
希望这会有所帮助!
【讨论】:
注意那个循环 - 因为SM
和Characteristic
没有被更新,它很可能只是不断地更新相同的行。删除索引和触发器显然是有风险的举动,您应该确保在执行此操作之前了解所有后果 - 妥协可能是在进行更新时禁用索引,然后重新启用它,如果您做了很多更新。
但是在这个查询执行中,系统总是给前 20000 个匹配的记录总是正确的。它将如何给其他记录匹配?
“Where”子句是否假定在每个更新周期都会更改?更新前 20000 行时,将从结果集中跳过的那些行为下一个更新批次拾取。如果我遗漏了什么,希望这有意义或纠正我。
萨米,我已经更新了你给出的内容并运行了查询。完成时间超过 3 秒。【参考方案3】:
尝试为 SM & Characteristic 设置复合索引。这样做,sql server 将能够更轻松地选择记录。在操作方面,更新是插入和删除的组合。如果您的表有更多列,即使您不尝试更新所有列,它也可能会减慢更新速度。
我喜欢的步骤
-
尝试用SM&Characteristic放复合索引
尝试重新创建包含所需列的表并在需要时使用连接。
【讨论】:
【参考方案4】:260 万行并不多。 2 秒的更新可能太多了。
话虽如此,更新时间可能取决于两件事。
首先,使用单个更新命令更新了多少行,即它只是一行还是更大的集合?对此你真的无能为力,只是说应该考虑到这一点。
另一件事是索引 - 你可能有太多或不够。
如果表缺少(SM,Characteristic)或(Characteristic,SM)上的索引,具体取决于选择性,那么它可能每次都进行全表扫描。如果更新只涉及几行,那就是浪费时间。所以,首先要检查。
如果受影响列上的索引过多,这也会减慢更新速度,因为每次数据更改都必须维护这些索引。您可以通过查询 sys.dm_db_index_usage_stats DMV(互联网上有很多解释,所以我在这里不再赘述)来检查索引的有用性,并删除未使用的索引。请小心并彻底测试。
要检查的另一件事是受影响的列是否是某些外键约束的一部分。在这种情况下,引擎必须每次检查约束的有效性(检查新值是否存在于被引用的表中,或者检查引用表中是否有数据,具体取决于列在 FK 的哪一侧)。如果没有支持该检查的索引,则会导致(再次)对所涉及的其他表进行扫描。
但要真正确定,请检查执行计划和 IO 统计信息 (SET STATISTICS IO ON),它会准确告诉您发生了什么。
【讨论】:
以上是关于更新查询需要 2 秒来更新表的主要内容,如果未能解决你的问题,请参考以下文章
Oracle中事务的处理,比如要对表A操作,我先查询在更新,是不是需要将查询放在事务,求高手解答!