繁体   English   中英

将此数据 model 存储为非关系数据?

[英]Store this data model as non-relational?

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

该表有 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)

以下是一些事实:

  • 数据库表有约 800.000.000 条记录,并且增长速度比预期的要快
  • 请求数量很少到很少,但每个请求的工作量很高

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
  • 以前的 FK1 和 Fk2 现在是一个集群的唯一复合 PK,因为 95% 正在选择和更新它
  • 这当然意味着当我在 5% 的情况下运行时,我必须加载比我实际需要的更多的负载,但我认为这仍然值得
  • 我当然必须知道 Json FK3 在请求之前,但我这样做是因为其他一些逻辑
  • 我也不需要将复合唯一约束与 FK3 一起使用。
  • FK3 的外键约束也不是必须的。
  • 没有任何形式的 SQL 专门读取或搜索特定的前值列,例如 WHERE Value5 = 'ABC'

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

或者你有一些完全不同的想法?

谢谢你的帮助!

或者你有一些完全不同的想法?

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

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 设为非聚集 PK 会更好。 对于检索少量行的查询,使用从非聚集 PK 到复合聚集索引的嵌套循环连接应该没问题。 但是通过 (Fk1,Fk2) 查询时进行 300,000 次查找会很昂贵。 它是如此昂贵,以至于这些查询可能会进行表扫描。

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

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

暂无
暂无

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

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