创建动态1:MSQL表的正确方法

创建动态1:MSQL表的正确方法,sql,performance,database-design,architecture,one-to-many,Sql,Performance,Database Design,Architecture,One To Many,简化示例:两张表-人员和时间。目标是记录一个人走过门口的所有时间 一个人每天在times表中可能有0到50个条目 记录这些记录的正确和最有效的方法是什么?是吗 times table ----------- person_id timestamp 我担心这张桌子很快就能超过一百万张唱片。插入和检索时间至关重要 还有:显然是非标准化的,但这样做会更好吗 times table ----------- person_id serialized_timestamps_for_the_day date

简化示例:两张表-人员和时间。目标是记录一个人走过门口的所有时间

一个人每天在times表中可能有0到50个条目

记录这些记录的正确和最有效的方法是什么?是吗

times table
-----------
person_id
timestamp
我担心这张桌子很快就能超过一百万张唱片。插入和检索时间至关重要

还有:显然是非标准化的,但这样做会更好吗

times table
-----------
person_id
serialized_timestamps_for_the_day
date

我们需要访问此人的每个时间戳,但只查询日期或此人id的记录。

我认为第一个选项是更好的选项

即使您选择第二个选项,索引的大小也可能不会减少。事实上,将有一个额外的专栏

而且不同用户的数据不相关,您可以基于person_id对数据库进行分片。也就是说,您的数据不能放在单个数据库服务器节点上,需要两个节点。然后,一半用户的数据将存储在一个节点上,其余数据将存储在另一个节点上


这可以通过使用诸如MySQL之类的RDBMS或诸如and之类的面向文档的数据库来实现。

考虑一下我们在这里讨论的是什么。只考虑原始数据
(事件时间,用户id)
这将是
(4+4)*每1M行1M~8MB
。让我们试着用DB粗略估计一下

一个整数4字节,时间戳4字节;行标题,比如说18个字节——这使得行大小的第一个估计值为
4+4+18=26个字节。使用大约0.7的页面填充因子;=><代码>26/0.7~37
每行字节数

因此,对于1m行,大约是37mb。您需要在
(用户id、事件时间)
上建立索引,因此我们只需将原始索引加倍到
37*2=74 MB

这使得非常粗略、不准确的估计达到了每100万行74MB

因此,要始终将其保存在内存中,此表的每1M行需要0.074 GB

为了得到更好的估计,只需创建一个表,添加索引并用几百万行填充即可

考虑到预期的数据量,即使是在笔记本电脑上,也可以轻松地用1000万行数据对这些数据进行测试——测试总是比猜测要好


另外,您的选项2对我来说确实不是“明显更好的主意”。

第二种解决方案有一些问题:

  • 由于您需要访问单个时间戳1,因此无法考虑当天的序列化时间戳,这将违反1NF,导致错误
  • 除此之外,您还引入了冗余:
    date
    可以从当天的
    序列化时间戳的内容推断出来,并且您的应用程序代码需要确保它们永远不会“去同步”,这很容易受到bug的攻击。2
因此,采用第一种解决方案。如果这样的话,一个基于现代硬件的现代数据库可以处理的不仅仅是“远远超过一百万条记录”。在这种情况下:

  • {person_id,timestamp}上的复合索引将允许您通过简单的索引范围扫描来查询person或person和date的组合,这可能非常有效
  • 如果只需要“按日期”查询,则需要{timestamp}上的索引。通过搜索给定日期的00:00到24:00范围,可以轻松搜索特定日期内的所有时间戳

1即使不查询单个时间戳,仍然需要将它们逐个写入数据库。如果您有一个序列化字段,则首先需要读取整个字段以仅附加一个值,然后将整个结果写回数据库,这可能会很快成为性能问题。还有其他问题,正如上面链接中提到的


2作为一般规则,可以推断的内容不应存储,除非有很好的性能理由这样做,我在这里没有看到任何原因。

您的简化示例与问题的其余部分不匹配。要跟踪一个人走过门口的天数,您只需要每天最多1条记录的个人id和日期。一个人可以一天多次“走过门口”吗?如果是,您需要单独跟踪所有这些事件吗?@Brian update更清楚。需要跟踪个人进门的时间,但可以按日期分组。将只查询个人id和日期,而不考虑模式。@BrankoDimitrijevic一个人每天可以穿过门口0到50次。我们需要能够访问每个单独的时间戳,但只能查询个人id和/或日期的记录。因此,我们可以将一天中的所有时间戳分组到一个记录中,但该记录可能在一天内更新50次。