在大型表(13亿条记录)上尝试非常简单的UPDATE操作时,DB需要一个多小时。执行计划显示Eager假脱机,因此我假设它在影响更改之前将表大部分或全部复制到临时数据库。
出于我的目的,我正在循环一系列候选更新,我只需要在这个大表的每次传递中快速更改0-10条记录,并且需要以亚秒级方式继续。关于如何实现这一目标的任何想法?我已经尝试过提示和更改索引结构,但我对任何想法都持开放态度。
表格布局:
CREATE TABLE [dbo].[its_financial_suppl_jnl]
(
[financial_suppl_jnl_key] [bigint] NOT NULL IDENTITY(1000000, 1),
-- ... { Omitting several column definitions }
[location_key] [int] NULL,
-- ... { Omitting several column definitions }
) ON [TA2]
GO
ALTER TABLE [dbo].[its_financial_suppl_jnl] ADD CONSTRAINT [PK_its_financial_suppl_jnl] PRIMARY KEY CLUSTERED ([financial_suppl_jnl_key])
GO
-- ... { Omitting 3 Non-clustered index definitions }
CREATE NONCLUSTERED INDEX [tmp1] ON [dbo].[its_financial_suppl_jnl] ([location_key], [financial_suppl_jnl_key]) ON [TA2]
-- ... { Omitting 12 FK definitions }
示例更新声明:
UPDATE its_financial_suppl_jnl
SET location_key = 964672
WHERE location_key = 507289
(有趣的是,上面的查询会更新0条记录,因为表中不存在Location_Key 507289.)
答案 0 :(得分:0)
你没有足够的代码让我知道你如何进行循环的细节或你有什么样的系统,但是让我对校长提出一些想法。
当您在大型表中循环执行更新时,每个更新语句都可以快速找到适用的记录,这一点至关重要。在这种情况下,您似乎正在执行此操作...索引tmp1适用于update语句中location_key的过滤器。我在这个网站上看到过许多解决方案,建议使用更新语句来执行类似SET columnA = columnB WHERE columnA != columnB
的操作,这对于第一个循环似乎没问题,但随着循环的进行会导致越来越糟糕的性能。
如果所有循环都是同一事务的一部分,那么循环遍历记录以一次执行可管理数量的记录的点就会失败。最简单的方法是在每个循环中发出CHECKPOINT
。或者,如果您想要更多控制或信息,您可以执行TRY / CATCH并手动处理交易。如果需要全部或全部(一个大事务),你当然可以这样做,但循环对你没有任何好处...你仍然会锁定整个表,直到事务提交或滚动回来,由于循环,你也会有一些最小的性能损失。
如果您考虑这些因素,整个批次仍然需要一段时间,但个别更新应该很快并且可以让您的表格在操作上可访问。如果你做了所有这些事情并且你仍然遇到问题,请更加具体地了解你所看到的内容并包括执行计划。
至于更新13亿条记录所需的时间......这实际上取决于您的系统和I / O性能。不要忘记,您不仅要更新群集数据,还要更新受影响的任何索引。如果不了解有关您的数据,系统和实际花费的时间的更多细节,我无法说出您所看到的内容是否脱节。