将此数据模型存储为非关系型?

Store this data model as non-relational?

我目前处于一种情况,我想将我的一个经典关系数据库 table 重新设计为非关系设计,但我不确定是否应该这样做。原因是性能问题完全失控了。

这个table有11列,设计如下:

Id bigint (PK)  -- Clustered Index
FK1 bigint (FK) -- Non-Clustered Unique Composite Index ( FK1_FK2_FK3 in this order )
FK2 bigint (FK) -- Non-Clustered Unique Composite Index ( FK1_FK2_FK3 in this order )
FK3 bigint (FK) -- Non-Clustered Unique Composite Index ( FK1_FK2_FK3 in this order )
Value1 nvarchar(100)
Value2 nvarchar(100)
Value3 nvarchar(100)
Value4 nvarchar(100)
Value5 nvarchar(100)
Value6 nvarchar(100)
Value7 nvarchar(100)
Value8 nvarchar(100)

以下是一些事实:

5% 的请求如下所示:

SELECT * 
FROM myTable 
WHERE Id = 12346 -- (works perfectly)

SELECT * 
FROM myTable 
WHERE Id IN (123456, 654321) -- (works OK because IN list contains only a small number of IDs)

UPDATE myTable 
SET .....
WHERE Id = 123456 (works perfectly)

不幸的是,95% 的请求看起来像这样:

SELECT *
FROM myTable 
WHERE Fk1 = 123456 AND FK2 = 654321 
-- works badly because it gets 100.000 - 300.000 records but I need all of them. Yes, unique index is used because order of index is correct )

UPDATE myTable 
SET Value1 = '1', Value2 = '2', Value3 = '3', Value 4 = '4', 
    Value5 = '5', Value6 = '6', Value7 = '7', Value8 = '8' 
WHERE Fk1 = 123456 AND FK2 = 654321   -- horrible because also 300.000 and yes, unique index is used because order of index is correct )

相反,我想这样设计它:

Id1 bigint (PK) -- Clustered Composite Index (former FK1 column)
Id2 bigint (PK) -- Clustered Composite Index (former FK2 column)
ContentColumn JSON -- Contains all former Value columns and the FK3 column as an array of objects. A object is column FK3, Value1, Value2 ....
ArrayLength INT -- length of json array

那么你们怎么看呢?我应该试一试吗?

或者你有什么完全不同的想法?

感谢您的帮助!

Or do you have some completely different ideas?

您可以使用一组更好的索引设计来做得更好。您想要针对最昂贵的查询进行优化:

SELECT *
FROM myTable 
WHERE Fk1 = 123456 AND FK2 = 654321 
-- works badly because it gets 100.000 - 300.000 records but I need all of them. Yes, unique index is used because order of index is correct )

UPDATE myTable 
SET Value1 = '1', Value2 = '2', Value3 = '3', Value 4 = '4', 
    Value5 = '5', Value6 = '6', Value7 = '7', Value8 = '8' 
WHERE Fk1 = 123456 AND FK2 = 654321 

做成FK1_FK2_FK3聚簇索引,把ID做成non-clusteredPK会更好。对于检索少量行的查询,使用从 non-clustered PK 到复合聚集索引的嵌套循环连接应该没问题。但是在通过 (Fk1,Fk2) 进行查询时进行 300,000 次查找将非常昂贵。这些查询可能会进行 table 扫描,因为它非常昂贵。

并且在通过 (FK1,FK2,FK3) 对 table 进行聚类后,考虑通过 FK2 将其划分为 10-100 个单独的分区。那么像 WHERE Fk1 = 123456 AND FK2 = 654321 这样的谓词将只需要扫描包含 FK2=654321 的分区,并且可以在该分区中直接查找 FK1=123456 的第一页。

此外,如果 PAGEIOLATCH 等待是查询运行时的重要部分,请考虑 ROW 或 PAGE 压缩。