创建分区会减少锁定,我们如何在 sql-server 中实现这一点?

Ada*_*ler 4 performance sql-server-2005 sql-server partitioning locking

客户希望我们的应用程序更快地处理更多数据,因此安排与他们的 dba 会面以讨论选项。

此应用程序会生成大量用于报告的数据。在每次运行之前,删除该项目的旧数据,执行计算,然后插入新数据。在繁忙时期,用户会排队数百个这样的生成任务,我们同时运行多达 30 个。每次运行可能会创建 60K 行。

dba 建议我们可以将应用程序更改为使用 30 个分区(例如,每个线程一个)以减少插入和删除期间线程之间的锁定。他们建议在标准 sql 中我们可以做类似的事情

INSERT INTO schema.table.partition (...) VALUES (...)
Run Code Online (Sandbox Code Playgroud)

我在msdn 文档中没有看到这种语法,这意味着更改这个应用程序很痛苦,但是否有可能做到这一点?据我了解,我们会改为使用分区函数基于表的列进行分区?

我已经阅读了创建分区函数文档,但我不完全确定如何创建一个函数来满足我们的需求。更糟糕的是,我还没有企业版来尝试这个,所以我为不正确的语法道歉。

我在想,例如,如果我们有一个 items 表和一个包含该项目数据的 itemdata 表,我们可能会通过基于类似的函数拆分数据来对 itemdata 表进行分区itemid mod 30。这会将项目 1 放在分区 1 中,将项目 2 放在分区 2 中,等等。我不确定我们是否可以在分区函数、方案、表声明中执行此操作,或者我们是否需要创建一个计算列并使用价值观条款?也不确定我们是否会看到任何性能改进?

这就是我认为我们可以实现的方式:

CREATE PARTITION FUNCTION SplittingItemIds_PFunc(decimal(18,0)) AS
RANGE LEFT FOR VALUES
(0,1,2,3, ... ,29)

CREATE PARTITION SCHEME SplittingItemIds_Scheme 
AS PARTITION SplittingItemIds_PFunc
ALL TO ([PRIMARY]);

CREATE TABLE ItemData  
(
    Id decimal(18,0),
    ItemId decimal(18,0),
    ...
)
ON PartitionSplittingItemIds_Scheme(ItemId % 30)

CREATE INDEX ItemData_ItemId_Idx ON ItemData(ItemId);
Run Code Online (Sandbox Code Playgroud)

这种做法对吗?从我读过的内容来看,索引将被自动分区 - 对吗?

gbn*_*gbn 8

如果底层 IO/磁盘对您不透明,则软件无法解决此问题。

  • 如果添加分区,则不会产生 30 个线程
  • 如果您的所有分区都在同一个卷上,您将降低吞吐量

我曾在类似的系统上工作过

  • 一个临时数据库
  • 分期的简单恢复
  • 超时删除(例如新的或更新的运行是插入)
  • 每次运行都有一个标题行来跟踪此状态
  • 当客户端准备好时刷新到真实数据库

我们还

  • 删除了主表的 FK 和其他调整
  • 将临时数据库放在单独的卷上。