【问题标题】:Slow updates using LIKE on where在 where 上使用 LIKE 缓慢更新
【发布时间】:2013-11-27 17:25:13
【问题描述】:

我应该对几列的 2 个表进行多次更新。表都是大约 100 万行。我必须在 3 台不同的服务器上进行更改。更新很简单,只需删除一个子字符串。子字符串大约 200 个字符长,列是 VARCHAR(MAX)。更改将影响大约三分之一的行。这是查询:

DECLARE @myVar varchar(250) = 'blablabla2345f25wdf34gqefblablabla...blablablabla'
UPDATE myTable
    SET myCol = REPLACE(myCol, @myVar, '')
WHERE myCol LIKE '%' + @myVar + '%'

问题是我从一个表开始并且需要很长时间才能执行,我在 10 分钟后停止了执行。第一个服务器只是测试/沙盒服务器,但其他服务器是预生产和生产。关于如何加快查询速度的任何建议?

【问题讨论】:

  • 考虑批量更新(例如,每条语句执行 10K 更新,重复直到完成)。

标签: sql tsql sql-server-2008-r2 sql-update


【解决方案1】:

它慢的原因是你的 WHERE 语句没有命中任何索引。当字符串以通配符开头时,就像不能使用索引一样。根据服务器,如果您的搜索词是“someterm%”,您也许可以使用索引

有什么方法可以修复查询,以便有一个索引供它查找?

【讨论】:

  • 已经试过了。子字符串可以在文本中的任何位置找到。
  • @Yaroslav 在索引方面你不走运;(加速UPDATE 的一种方法是SELECTing 需要单独更新并使用的行的ID这些 id 直接在更新中,总共不会为您节省任何时间
  • @DrCopyPaste,遗憾的是,也尝试过,但改进为零。我几乎无法考虑修改查询以使用索引。此外,我可以在测试服务器上执行此操作,但不能在其他 2 上执行,因为我只能启动 DML 语句,无法添加/修改索引等。
  • @Yaroslav 是的,如果您搜索以通配符开头的字符串,select 不会使用任何索引; update 但是,如果您将 id 列表直接传递给更新查询,则会使用您在 id 列上的索引
  • 好吧,最终混合使用了 cmets 和答案。将更新(gvee 推荐的批次)拆分为较小的块,因为我意识到我可以通过语言进行过滤。还进行了更仔细的搜索,发现超过一半的子字符串出现在主字符串的开头,因此修改了查询以更好地使用可用索引。我没有在速度上取得太大的进步,但这样服务器在很长一段时间内都不会太过载,所以 DBA 不会在我肩上
【解决方案2】:

三个原因(至少):

  1. 您正在过滤未索引的列表达式,因此需要进行表扫描
  2. 您在 VARCHAR(MAX) 列中进行搜索,该列可能存储在与主表数据不同的页面中,因此需要额外的 I/O(加上额外的字符串比较开销)
  3. 您正在修改 VARCHAR(MAX) 数据,因此数据可能需要重新组织以适应新空间,从而导致额外的 I/O。李>

除非有其他可以过滤的字段,否则我想不出加快速度的方法。分批运行它会减少事务日志开销,并向您显示增量进度,这至少 感觉速度更快。

【讨论】:

  • 哎哟!没有考虑影响 I/O 开销的VARCHAR(MAX)。是的,@gvee 在 cmets 上建议可以选择批处理
猜你喜欢
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 2017-10-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
相关资源
最近更新 更多