度量存储的关系型数据库模式设计

9
考虑一个具有以下特征的系统:
- 存储从多个传感器/输入收集的时间序列数据/指标。 - 收集的数据点(指标)来自不同的系统和不同时期。 - 每个度量通常是一个数据点(例如,温度和湿度不是同时报告的,而是单独报告,并且将具有不同的时间戳) - 收集的度量类型会随时间扩展 - 系统开放,并且随着时间的推移将支持其他输入(例如,今天我们收集温度,湿度和CPU,明天可能添加监视CO2和RAM的传感器)。 - 需要通过查询获取给定时间段内所有度量的摘要,并且很可能是最常见的查询场景。
我可以想到三种建模方式:
1. 宽表 - 以类别为表格(已覆盖)
注意:由于数据点单独收集,因此具有许多稀疏值。存储新度量需要新列
2. 窄表 - 每个指标为表格(已覆盖)
注意:存储新指标需要新表
3. 类型表(未覆盖)- 单个指标表(未覆盖)
注意:存储新指标只需要在metricType表中添加一行,无需模式更改。担心块大小的性能影响,尽管在所有指标上按时间段分组不需要联接,因此可能更快?
我想知道是否有人可以评论所提供的选项,指向包括3以及1和2在内的性能基准,或者一般地提供关于每种方法的适用性的建议。我计划对此进行自己的实验,并在完成后发布结果,但是目前阶段的任何见解都将不胜感激。 :)
请注意,不要提出nosql解决方案,我已经了解该空间中的选项,并正在单独评估该选项

嗨,Sam,你最终确定了模式吗?如果是的话,你是采用关系数据库还是时间序列数据库呢?你能帮我看一下你最终确定的模式吗? - Subbi Reddy K
6个回答

23

1 提案

“宽表”

这个表格存在着严重的规范化错误(同时,如果认真考虑的话,它还有大量的空值和完整性问题)。它是不可用的,不需要进一步评论。

“窄表”

这个表格没有错误,但是规范化还没有完成。

“类型表”

这个表格已经算是比较完整的了,是你三种方案中最好的。但是它只是从一个狭窄的角度来看待问题,并且与问题所处的环境完全隔离。因此,它存在其他错误,而不仅仅是你所询问的那些问题。

2 问题

  1. 第一个问题是,你正在比较三件不合理可比、彼此不相等的事物。

  2. 第二个问题是,EAV是当下流行的趋势,吸引了很多人。然而,它存在重大问题,如果要实现数据完整性,就需要额外的“元数据”表。问题在于,其实并不需要使用EAV。

3 解决方案

收集的指标类型将随时间扩展 - 系统是开放的,随着时间的推移将支持更多的输入(例如,今天我们收集温度、湿度和CPU使用率,明天可能会添加一个传感器来监测CO2和RAM)。

这实际上是一个简单的关系型数据库问题,可以通过完全普通的关系设计来解决,提供完整的关系强度、关系完整性和速度(其他设计没有的)。

3.1 注意事项

但是有一些注意事项,因为所谓的“关系型”并不是真正的关系型。

  1. 摒弃{{Record ID}}字段,它们与关系型数据库相悖。

    • {{Record ID}}将你的模式降低到了上世纪70年代的文件系统水平(为方便起见,存储在SQL容器中)。
    • {{Record ID}}并不能提供行唯一性,而这是关系模型所要求的。
    • 此外,它们需要每个文件增加一个额外字段和一个额外索引
  2. 在建模数据库(无论是关系型还是非关系型)时,把数据视为数据,不要从GUI或某些查询等需求的角度来看待数据。

  3. 在这个(建模)阶段关注性能问题是错误的。首先做对,其次才考虑如何让它变快。不要颠倒顺序。

  4. 关系键提供了含义以及关系完整性(这是逻辑上的,不同于SQL的物理参照完整性)。这解决了对象存在的上下文问题。

    • Sensor并不是孤立存在的(除非它在商店里的货架上被包装...但即使这样,它也存在于商店库存的上下文中)
    • 一个活动的Sensor仅存在于它所在物体的上下文中。你并没有提供任何关于这方面的信息。我们把这个物体称为通用标签Article
    • 此外,需要对Article进行度量范围的限制(用于超出范围警报等),而不是对Sensor本身进行限制。(传感器可能有一个范围,但那是另一回事。)
    • 同样地,Sensor存在于Location中,这是第二个向量。否则,Article存在于Location中,而Article键携带了Location。我已经建模了后者。

3.2 数据模型

以下是解决方案: 传感器数据模型

在某些浏览器中,内联图形可能无法显示。在这种情况下,请参阅 PDF 版本。

  • 它将满足OLTP和OLAP(维度-事实)的要求。

    • 如果您提供更多上下文,我们可以精确地对其进行建模。这可能需要一些来回沟通。
  • 它仅限于提供的信息。

    • 我认为和是同义词。
    • 显示为依赖于(存在于)中,或者它们可以是单独的向量。无论如何,
      和共同限定了。
    • 由于是唯一的(AK2),因此是唯一的。不需要索引。但是,如果通过单独查询的查询很多,则此类索引将提高性能。
  • 请随时提问,我会回答。

  • 对于那些完全不了解IDEF1X的人,请参阅IDEF1X Introduction

  • 对于那些熟悉IDEF1X并且只想刷刷存在的人,请参阅IDEF1X Anatomy

4 性能

您关注性能问题是好的,但现阶段过早考虑。首先要正确获取数据模型,其次要快速获取数据结构。这样做的原因有很多,其中最重要的是当数据规范化、关联时,结构已经非常快了。此外,不应为特定查询进行优化(如果需要,在第二阶段可以添加索引)。

尽管如此,我会回答您提出的问题。

  • 例如,在预定的Reading PK上创建一个聚集索引将:
    • 服务于大多数查询,大多数维度(除了使用SensorSerialNo单独的查询,在这种情况下,我建议添加附加索引)
    • 服务于所有OLTP事务,并确保最高并发性,因为传感器根据现实世界分布:跨越位置和文章。
  • 而在Record ID上创建索引将保证每个单独的INSERT上出现热点。这对于创建死锁非常有用。

4.1 基准测试

我有一百多个数据结构的基准测试,这些测试是在过去四十年中收集的,用于OLTP和OLAP使用。我的大多数客户都是银行(想象一下:传感器读数非常像股票价格,在一天内变化;几个向量(维度);数十亿行)。银行非常严格保密,因此我不能按原样发布基准测试结果,而对其进行编辑需要时间和精力。

我有一个非常相似的需求的基准测试是公开的。实际上,它被包含在一个关于时间序列数据的SO问题的答案中,但寻求者让版主将其删除了(这对Oracle来说很尴尬)。以下是Sybase ASE与Oracle 10.2基准测试(针对固定DDL(时间序列数据)和人口)的基准摘要

最后,所需的结构和代码足够简单,可以运行自己的基准测试。

5 对其他答案的回应

对Neville的评论:

然而,如果您还必须回答“当CPU高于30%而湿度低于56%超过3小时时是哪一天”,则EAV模型变得非常难以使用。这些查询会迅速变得非常难以编写和理解-每个条件至少需要1个自连接。

请注意,他的评论涉及EAV,但可能意味着它同样适用于本例中的主题表(普通关系数据库表(非EAV)Reading),因为它涉及查询类型(而不是EAV概念与关系概念):

  • 这个声明不适用于关系表(它可能适用于EAV;由于记录ID引入的大量问题等)

  • 只要您有一个真正的关系数据库模式(如我所建议的),以及一个真正的SQL平台(不是虚假的“sql”,它不符合但欺诈性地使用了名称),并且您理解IN和NOT IN以及如何在SQL中比较集合,这些查询就很容易编码。

    1. 一个真正的关系数据库模式(如我所建议的)
    2. 一个真正的SQL平台(不是虚假的“sql”)
    3. 你理解IN和NOT IN,以及如何在SQL中比较集合
  • 这样的查询很容易编码。

6回应评论

记录ID是反关系的

你有没有关于记录ID为什么是反关系的链接,我一点都不怀疑你,但我很想了解为什么这种反范式如此普遍。

在这个反科学的混乱中,学者们制造和捏造各种“解决方案”来解决在关系模型中不存在的“问题”,然后你会有第二层无休止的“辩论”,关于哪种非问题的修正更好或更差。

您不需要链接,因为没有什么可“辩论”的,而且您可能阅读到的任何“辩论”都忽略了上述观点。

唯一的权威是伟大的Dr E F Codd。除Codd外,所有声称与关系模型有关的书籍和教科书的作者实际上都是错误的,它们是关于实现1970年代风格的记录文件系统和反关系(没有关系能力;没有关系完整性;没有关系速度)。从1970年起,他们犯了一个错误,试图将RM适应他们的1970年代RFS思维方式,而不是释放它并采用RM思维方式。他们花费了过去的五十年来加强这一点,甚至用“数学定义”来证明它;17个“关系代数”;42个异常的“正常形式”。全部都是反关系的。他们互相引用,因此可以出版。
第二个问题是,像SO这样的网站基于民粹主义的基础上。流行的答案不是最好或正确的答案。为此,您需要一个权威(对于民粹主义者来说非常可怕)和客观、绝对的真理。(人们喜欢他们的相对或主观的“真理”,这些真理随时会改变)。
因此,您只需要单一的、权威的定义,即原始论文关系模型
是的,这些术语已经过时,并且现在不太被理解。
是的,它是开创性的(每个词都很重要,具有深刻的含义)。
不,您不需要阅读第2节(数学)。
您需要从中获得以下信息:
关系键是“由数据组成”的(我的意思是,对于RM中的多个条目,它们是层,这是逻辑的),这是逻辑的。
代理人不仅违反了该定义,而且是预关系范例,即物理指针,这正是RM替换的内容,并明确禁止使用。
非常重要的是,您不仅需要了解关系键的定义,还需要了解其原因和目的。
例如。它超越了基于指针的系统所具有的导入/导出问题。
例如。时间定义(开创性;8个字母;可怕)。
因此,没有争论,也没有“辩论”。
任何反对这一点的人都是反对关系的。这不是因为我这么说,而是因为它与事实和单一权威相矛盾。
我已经命名了正确使用RM的显式技术优势(关系功率;关系完整性;关系速度),但是对此进行扩展需要相当大的努力。
不遵守RM的后果是,您既没有获得任何好处,也会出现1970年之前预关系记录文件系统所具有的完整问题集,并且“学者”提供的人为“解决方案”从未奏效。
如果您需要扩展RM的这些好处的内容,那么您当然需要在某种程度上了解它们,因为每个好处都非常深入和重要,我能提供的最好的东西就是这个。

为什么这种记录ID反模式如此普遍?

简短的回答是,人们喜欢他们的无知、主观的“真理”,并且会不遗余力地保护它。他们很快接受并重复任何为保持现状而进行的辩解。学习一些与他们所知道的范式完全不同的东西是非常可怕的,因为它威胁到了他们舒适的无知,并揭示了它的真实面貌。他们将不得不承认他们已经写了五十年的东西是错误的。这就是为什么民粹主义盛行。出于无知。

稍微长一点的答案是这样的。只需看看互联网即可。在旧时代,对于任何特定的主题,我们有一个来源,一个绝对权威:例如购买《大英百科全书》;花费整个童年时间来阅读它。永久的真理。诚实的历史。但现在,任何拥有键盘和两根手指以及一些结缔组织(不需要大脑)的人都可以发布内容。作为一个即时的“权威”。网络充满了(a)肤浅的答案(不是“那才是答案”)(b)有很多种类(c)因为民粹主义而被赞同(d)与正确或完整的答案相去甚远。可以轻松被大众理解的口号。很少有人想要深入了解完整的答案。

即使当某种权威得以建立(例如维基百科;Stack Overflow),也很容易被颠覆,因为有数百万人更改条目(真理不会改变,因此只要有东西在改变,它就不是真理)。大多数情况下是为了服务于他们的政治立场、意识形态、重新编写历史以使过去错误(事实上过去已经发生了),以及现在的疯狂“好”。

这个问题的明确答案是:学术嫉妒。花了整整十年时间才让Codd的关系模型被理解和接受。即使那时,只有少数人接受了它。IBM和Britton-Lee(后来成为Sybase)实现了Codd的RM,精神上和字面上。(Digital Equipment Corp也这样做了,但他们已经倒闭了。)那些似乎在与Codd合作的学者们最终证明是在反对他(根据证据)。他们讨厌这个事实,即他们自己没有想出来,一个人提出了第一个真正的模型,具有坚实的、逻辑的、数学的基础,包括关系代数。所有集成的。回答了当时的所有要求(例如物料清单问题)。这经受住了时间的考验:五十年过去了,没有任何东西被添加或改变。

通常他们会声明:“但Codd没有定义这个或那个,所以我在定义它...”。所以他们提出了自己的RA。现在他们有17种,都不相关。还有异常的“正规化形式”,将他们的记录文件系统的碎片化部分提升到“关系”的水平。现在他们有42个,都不相关。还有很多书声称是“关系”,但根据事实证明,是反关系的。每个“学者”都试图加强他们的“学术”地位,反对其他所有人。

这就是为什么我再次说,去找唯一的权威。不要读反关系群体的任何东西,因为它会削弱你对RM的理解(最好的情况),或者毒害你的思想(最坏的情况)。

一个澄清

如果您查看一个关系PK(例如)Location.Location,它可能看起来很奇怪。这是一个数据,即用户实际使用的%Code%ShortName。通常为4到6个字符,最多12个字符。与必须存在的长Name不同,它是一个备用键。当然,它绝不是任何类型的数字(不是数据,也不是用户使用的内容)。用户也喜欢他们的简称。显然,如果存在任何国际标准,请使用。

键必须是稳定的(不是静态的,在宇宙中没有什么是静态的),并且在现实世界中用于唯一标识对象(数据行)。

  • 例如,对于在美国上市的公司Security,它将是TickerSymbol,在澳大利亚则为ASXCode。 ISO代码,ISINCode是备用键。

  • 对于城市,使用地理位置标准之一:ISO; FIPS;等(我使用Statoids,因为它存在比其他人更久远,但那些日子已经数不清了)。 最差的情况下,使用机场代码。


真正的SQL平台

你认为真正的SQL是什么?我猜SQL Server、Postgres、MySQL和Oracle都是吧?

不是的。我的意思是任何实际遵守已发布的SQL标准的平台,因此可以实际支持关系表、集合的关系处理和ACID事务。

  • 这自动排除了免费软件/虚拟软件/无处可寻/"开源",因为这些软件的代码由分布在全世界的10000名开发人员编写,没有任何统一原则。例如,没有ACID事务或所需的结构,在每个代码段中都需要这些结构。现在插入太晚了,因为这将需要100%的重写,而且天哪...还需要一个服务器架构。

商业版
这意味着付费并得到支持非常重要。您可以签订维护合同,获得即时支持,或者发布错误报告并在接下来的一年或三年中每天检查更新。

服务器架构
如果需要可扩展性或性能(高吞吐量;高并发性;低延迟),则服务器架构最为重要。同样,这也排除了免费软件和Oracle,因为它们没有架构,它们是相互作用的程序的大量集合,让操作系统执行通常由架构化数据库服务器执行的所有功能。

请查看Oracle与Sybase架构比较

  • 同样适用于PostgreSQL和其他免费软件。PostgreSQL(Ingres的儿子)在压力下出现了大量锁定问题和非常低的并发性,因此声名狼藉。

1 高端商业SQL兼容数据库

市场占有率约为5%,但在金融服务和自动化市场占有率达95%。架构优秀,营销糟糕。

  • **Sybase ASE
  • IBM DB2**

2 商业SQL兼容数据库

  • MS SQL Server
    易用性最好的数据库。架构优秀(最初是从Sybase窃取),然后以微软一贯的疯狂方式“进步”。使用起来很痛苦;有大量开销;与各种附加组件集成不良,必须使用。

3 商业SQL不兼容数据库

架构糟糕,营销优秀。

  • Oracle
    一般来说,Oracle开发人员在使用该产品时非常擅长以必要的方式使其正常工作,但这意味着他们已经远离了关系模型。

    • 例如,在时间序列基准测试中,整个重点是当请求子查询时,Oracle会崩溃,因此必须使用“内联视图”。OP声称这与子查询一样快(避免了需要更多的代码,并且编码人员必须超出关系思维方式)。基准测试证明这是极其错误的,在每个测试场景中(Oracle比Sybase在COUNT()上慢3到4.8倍,在SUM()上慢26到36倍)。
    • ...而子查询(Sybase 2.1秒)在120分钟后不得不放弃。
    • 例如,Oracle不符合ACID事务标准,开发人员在一定程度上绕过该障碍,但幻影更新和丢失更新(技术术语)根本无法防止。如果绕过方式没有正确编写,整行数据(UPDATESINSERTS)将被删除。
    • 所有这些都适用于以下内容...

4非商业用途,SQL不符合标准

这些人花费了大量时间开发与关系数据库不相关但对反关系记录ID文件系统非常有吸引力的“特性”。
例如,“延迟约束检查”;ENUMs等。
他们缺乏SQL合规性的基础。例如,没有真正的ACID事务。
此外,正如上面所解释的那样,零架构。这导致系统在单一使用情况下表现出色,在并发或可扩展性方面受到任何压力时都会失败。
由于他们不符合SQL要求,他们费尽心思在命令手册的每一页上发布符合声明的通知。(只需要在手册前面声明一次符合即可)。当然,缺少的命令就是缺少了,所以他们没有符合声明。
PostgreSQL是自从Ingres以来我曾经检查过的最糟糕的软件。由于它是由一位“学者”编写的,所以深受“学术”界喜爱。5个用户最多,否则要处理并发问题(只需简要查看SO上报告的问题)。
MySQL在这个类别中头和肩膀高出PostgreSQL。InnoDB引擎在性能方面明显更好,但还远远达不到Sybase/DB2的水平(仍然没有真正的服务器架构)。在SQL不合规部门没有喘息的余地。
总之:一分钱一分货。
  • 服务器架构,最显著的是在任何场景下的性能。
  • 深思熟虑并在每个适用的代码段中实现的SQL合规性。
  • 最后但同样重要的是支持。

无论您选择什么,记住,当您将其移植到另一个平台时,您的SQL代码将需要完全检查和更改,因为SQL(或非SQL)的“风味”非常不同。 对于非商业程序套件,这意味着需要完全重写。 因此,请谨慎选择,考虑长期实施。


2
这很大程度上取决于您需要运行的查询类型。如果像您所说的那样,需要通过查询获取给定时间段内所有指标的摘要,这可能是最常见的查询场景,那么性能可能不是您最关心的问题。
由于所有情况下的查询都会命中可索引的时间戳列,因此这实际上只涉及到连接性能的问题,而几乎每个关系型数据库在这方面都非常出色。
如果您的查询真的只是“显示某个时间范围内的数据”,则从开发工作量的角度来看,选项3(一个实体/属性/值设计)是最有效的选择。
您的查询将有一个单独的内部连接,时间戳列将提供良好的索引。正如您所说,当收集新的测量点时,您不需要更改模式或查询。
另外两种设计需要为每个表进行外部连接。在性能方面,这并不是什么大问题,但管理模式和相关查询将是一件麻烦事。
然而,如果您还必须回答像“在什么日期CPU超过30%而湿度低于56%超过3小时”这样的问题,您的EAV模型将变得非常难以处理。 这些查询将迅速变得难以编写和理解 - 每个条件都至少需要一个自连接。

非常感谢您的回答,非常有用。对于使用EAV模型工作的困难性的一些担忧,是否可以通过为每个/每个有趣的度量类型创建一个视图来解决? - Sam Shiles
可能可以 - 但这样你就得在每次出现新的指标类型时改变你的数据库结构和查询,还不如直接选择选项一或二。 - Neville Kuyt

1
TimescaleDB的文档讨论了宽数据模型和窄数据模型:

https://docs.timescale.com/timescaledb/latest/overview/data-model-flexibility/

总结:

  • “如果您独立收集每个指标,那么窄模型是有意义的。它允许您通过添加新标签而无需进行正式模式更改来随时添加新指标。”
  • “如果您通常同时查询多个指标,则将它们存储在宽表格格式中既快速又容易。”

0

实际上,3的方式是一种在关系存储中包括时间戳的EAV建模。

+---------+            +-----+            +-------------+
| Sensors | -- 1:M --< | EAV | >-- M:1 -- | Value kinds |
+---------+            +-----+            +-------------+

需要通过查询获取给定时间段的所有指标的摘要,并且这可能是最常见的查询场景。
如果查询不需要连接但需要按时间分组,则时间戳列上的聚集索引可确保性能。
然而,任何具有连接的查询(即比较不同传感器的值)都有降低性能的风险。解决方案可以是为收集的EAV数据提供单独的OLAP存储。

0
从开发者的角度来看,我想推荐第三个选项。在您的第三个选项中,您可以考虑在 MetricType(即typeId)和timestamp列上建立索引,这将极大地优化查询性能。
而您的第一个表需要系统停机时间,因为当需要插入新列时,您需要先关闭您的实时系统以添加该列,初始化一些默认或空值,然后再将系统重新启动。在我看来,它将包含自添加到系统中的那一刻起之前行的无用数据(垃圾)。数据库表的大小将会很大,并且可能包含大量的垃圾数据,从而影响查询时间。
第二个想法比第一个有所改进,但是尽管存在垃圾数据,这将需要连接多个表,这将随着时间的推移增加查询性能。您不能像第三个选项那样在多个表上建立索引。
因此,我认为选择第三个选项是最有效的。表已经规范化,有效的索引将提供高效的查询结果。
我想提出另一点建议。您可能还应考虑拥有一个专门包含聚合数据的表格。例如,如果您的系统需要聚合数据,则可以考虑以非规范化的方式将数据存储在一个单独的表格中,并在其中存储特定时间轴的聚合值,以便您可以从已处理过的原始表格中删除数据。我指的是OLAP数据库,您可能考虑了解一下。

0

我不建议采用ERD设计,每当您添加传感器时就需要进行修改(只要您知道您会添加)。这就是为什么我认为您应该排除选项1。每当您更改表时,您将获得大量的空值和您可能在代码中遇到的不必要的工作。

Option 2同样适用,也许除了空值外,但每当您向系统添加新数据源时,仍然会出现不必要的工作。

Option 3对我来说看起来很不错,因为它可以扩展数据源并保持数据清洁整洁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接