我正在努力将客户端与数据同步,以实现最终的一致性。服务器将发布数据库 ID 和行版本/时间戳的列表。然后,客户端将请求版本号不正确的数据。数据不一致的主要原因是代理节点之间的网络问题、裂脑等。
当我从表中读取数据时,我根据不是主键的谓词请求数据。我迭代可用区域以读取每个区域的数据。这是我的选择:
SELECT DatabaseId, VersionTimestamp, OperationId
FROM TableX
WHERE RegionId = 1
由于这会导致每个查询都进行索引扫描,我想知道我的 RegionId 列上是否有一个非聚集索引,并在该索引中包含选定的列:
CREATE NONCLUSTERED INDEX [ID_TableX_RegionId_Sync]
ON [dbo].[TableX] ([RegionId])
INCLUDE ([DatabaseId],[VersionTimestamp],[OperationId])
VersionTimestamp是 rowversion/timestamp 列,并且当然会在更新行时更改,所以我想知道在索引中包含此列是否是一个糟糕的设计选择,因为它需要在每次插入/更新时更新/删除?
由于这将导致n次索引扫描,而不是n次索引搜索,因此最好读取一次所有数据,然后按 regionId 分组并填充 regionId 没有任何数据的行的空列表。
现实生活中的场景要复杂一些,因为还必须查询表关系。我还没有考虑在我的版本查询中包含一对多关系。
这主要是为了更好地理解覆盖索引的影响并弄清楚如何更好地使用它们。由于无论如何我都会从表中读取所有数据,因此一次加载它们可能更便宜。但是,从上面的查询中读取它们,它使我的代码对于这个简单的无关系示例来说更加清晰。
编辑: 备选方案 2 想到的另一个选项是在RegionId上创建一个覆盖索引,并包含我的主键(DatabaseId)。
SELECT DatabaseId
FROM TableX WHERE RegionId=1
然后是一个新查询,我在其中选择所需的列 WHERE DatabaseId IN(list, of, databaseId)
对于当前场景,表中最多只有数千行,而不是数百万行。两个 (x n ) 查询的网络流量很可能超过使用索引的好处,并且是过早的优化。