繁体   English   中英

表分区以避免锁定

[英]Table Partitioning to avoid locks

TLDR ; 我正在尝试对表进行分区,以便可以在不锁定其他分区的情况下对每个分区进行操作,但它不起作用。

背景:我正在创建一个数据管道流程,将数据从中央企业数据库导出到 SQL 服务器数据库,可用于分析。 我每天都需要导出完整的表(目前删除旧表,稍后归档),它可以接近 10GB。

为了让它足够快以供使用,我根据“计划”列将表格分成 15 个块。 这是在数据管道中完成的,因此“计划”列中的 15 个可能值中的每一个都被独立处理; 从企业数据库中提取每个计划块,然后在 SQL 服务器表中删除该块的旧数据并上传新数据。

问题是,在 15 个块中执行此操作意味着所有进程相互阻塞。 一切都必须等待其他一切,最终使所有 go 非常慢,并且经常由于超时而失败。

为了解决这个问题,我已经:

  1. 为表中的表创建了 16 个 SQL 服务器文件组
  2. 向每个文件组添加一个文件
  3. 在计划列上对表进行分区(每个文件组的边界是一个计划的名称)

根据这里的答案,这应该允许我“一次性删除或添加大量数据”。

但这似乎没有帮助; 我仍然得到块。

所以两个问题

  1. 是否可以进行分区,以便可以处理每个分区而不会阻塞其他分区? 如果是这样,怎么做?
  2. 我必须每天重新运行分区作业吗? 我发现的有关分区的各种教程有时似乎暗示了这一点。 我不清楚数据库是否自动维护分区。

替代方案我还考虑将目标表分成 15 个表,并尝试将它们与视图重新组合。 那会更好吗? 更差?

过去我遇到过类似的问题,并发工作人员在单个物理分区和不同分区中处理行,但仍然相互阻塞。

发生这种情况的一个原因是,如果其中一名工作人员设法将他们的锁升级到表级别。 您需要在阻塞期间检查等待任务,看看这是否适用于您。

SQL 服务器确实支持将锁升级到分区级别,但这不是默认设置(因为在某些情况下可能会导致更大的死锁概率)。

要启用此选项,您需要设置LOCK_ESCALATION = AUTO

如果您正在做的工作是替换分区中的所有行,那么您应该考虑Charlieface 的评论并在每个分区的新空表中执行此操作,并使用TRUNCATE TABLE... WITH (PARTITIONS ())ALTER TABLE... SWITCH清除旧数据和ALTER TABLE... SWITCH引入新数据(通常都应该是非常快速的操作)。 这意味着插入是真正独立的,并且这种模式可能更有益 w.r.t。 插入的最小日志记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM