如何以高性能且准确的方式增加主表列中的值与详细信息表中的记录数?

Ami*_*shi -1 sql-server-2008 sql-server count update query-performance

我使用的是 SQL Server 2008 及以上版本。

我有以下两个表:

MasterTable
MId
DetailsCount DEFAULT 0

DetailsTable
DId
MId
Run Code Online (Sandbox Code Playgroud)

在 中,我将匹配的MasterTable.DetailsCount记录数存储在 中。DetailsTableMId

首先将记录插入到主表中,然后将给定 MId 的数千条记录插入到详细信息表中。这发生在多个线程上。每个线程都有自己的SqlConnection.
详细信息表中的总记录数为数百万,并且还在不断增加。

DetailsTable.MId列上添加非聚集索引。无法添加聚集索引。

我尝试过两种维护DetailsCount专栏的方法:

  1. 扫描详细信息表以获取计数
    插入详细信息表后,更新DetailsCount使用查询:
UPDATE MasterTable
SET DetailsCount = (SELECT COUNT(*) FROM DetailsTable WHERE MId = ?)
WHERE MId = ?
Run Code Online (Sandbox Code Playgroud)

由于详细信息表中有数百万条记录,这种方法的性能不高,因为每次在其中添加新记录时我都需要扫描详细信息表(以获取计数)。即使使用非聚集索引,它的性能也不佳。如果我们简单地评论该列的更新,我们会看到性能的显着提高。

  1. 主表中的增量计数
    在详细信息表中插入后,更新DetailsCountusing 查询:
UPDATE MasterTable
SET DetailsCount = DetailsCount + 1
WHERE MId = ?
Run Code Online (Sandbox Code Playgroud)

这种方式更好,因为我不需要访问详细信息表。
但是,详细信息表中的插入发生在多个线程上。每个线程使用不同的SqlConnection实例。
这就是为什么DetailsCount经常会更新错误的值。

我查看了Computed Column,但我认为它只适用于单个表;不是主从表。

我正在寻找高效的方法来DetailsCount准确维护色谱柱。

Pau*_*ite 5

我鼓励你根本不要实现这个设计。

详细记录的计数与表无关。当计数与详细记录的数量不匹配时,它表示数据重复和潜在的异常源。计数是派生数据,应根据需要计算以满足读取请求:

SELECT 
    MT.MId
    DetailCount =
    (
        SELECT COUNT_BIG(*) 
        FROM Details AS D
        WHERE D.MId = MT.MId
    )
FROM MasterTable AS MT
WHERE 
    MT.Mid = {?};
Run Code Online (Sandbox Code Playgroud)

您应该首先关注良好且正确的关系设计,并且只有在您可以证明存在实际问题且除了重复之外无法通过任何其他方式解决时才担心性能。

数以百万计的详细信息行毫无意义。详细信息表的 MId 列上的 B 树索引将使按需计算计数变得非常快。

您提供的唯一包含运行时统计信息的更新执行计划现已删除。它运行了零毫秒,并显示了对不存在的主记录的查找,该记录无论如何都不会访问详细信息表。信息不是很丰富。

计划

该问题缺乏必要的细节,但您看到的任何不良性能似乎都是由(不必要的)更新和阻塞引起的,当多个线程在每次详细行插入后尝试更新相同的主记录时。从主表中删除计数列,这个问题就消失了。