2016-09-03 57 views
0

我必须优化我的小数据库,因为它太慢了,也许我们会一起找到另一个解决方案。构建数据库结构的另一种方法

首先让我们谈谈存储在数据库中的数据。有两个对象:users,让我们说messages

用户

有类似的东西:

+----+---------+-------+-----+ 
| id | user_id | login | etc | 
+----+---------+-------+-----+ 
| 1 | 100001 | A | ....| 
| 2 | 100002 | B | ....| 
| 3 | 100003 | C | ....| 
|... | ...... | ... | ....| 
+----+---------+-------+-----+ 

有这个表里面没有问题。 (不要怕iduser_iduser_id被其它应用程序,因此它必须是在这里。)

消息

,第二个表有一定的问题。每个用户有这样的例子消息:

+----+---------+------+----+ 
| id | user_id | from | to | 
+----+---------+------+----+ 
| 1 | 1  | aab | bbc| 
| 2 | 2  | vfd | gfg| 
| 3 | 1  | aab | bbc| 
| 4 | 1  | fge | gfg| 
| 5 | 3  | aab | gdf| 
|... | ...... | ... | ...| 
+----+---------+------+----+ 

没有必要edit消息,但应该有一个机会来更新用户信息列表。例如,外部服务将所有用户的消息发送到数据库,并且必须更新列表。 而最重要的是,大约有30亿的用户和普通用户有500多条消息。另一个问题,我必须通过搜索字段from并计算匹配数量。我使用join设计了一个简单的SQL查询,但获取数据需要太多时间。

所以......这是相当大的数据量。我决定不使用RDS(我使用Postgresql),并决定迁移到Clickhouse等数据库。

但是我遇到了一个问题,例如Clickhouse不支持UPDATE语句。

要解决此问题,我决定将消息存储为一行。所以表Messages应该是这样的:

    Here I'd like to store messages in JSON format 
       {"from":"aaa", "to":bbe"} 
       {"from":"ret", "to":fdd"} 
       {"from":"gfd", "to":dgf"} 
        ||       
        \/ 
+----+---------+----------+------+ And there I'd like to store the 
| id | user_id | messages | hash | <= hash of the messages. 
+----+---------+----------+------+ 

我认为messages柱内的全文搜索将节省一些时间资源等。

你有什么想法吗? :)

+0

我必须说你的问题非常广泛。首先,哪些类型来自并列太多?其次,当你使用PostgreSQL时,你是如何使用索引的?你看看分区吗? –

+0

'from'和'to'是varchar(255),我没有看分区......你能提供一些教程吗? – Ascelhem

回答

0

首先,当我们有这么大的数据集时,fromto列应该是整数,如果可能的话,因为它们的比较速度更快。

其次,您应该考虑创建适当的索引。由于每个用户的记录相对较少(500个而不是总共30M),它应该会给您带来巨大的性能优势。

如果一切都失败了,可以考虑使用分区:

https://www.postgresql.org/docs/9.1/static/ddl-partitioning.html

在你的情况,他们将是动态的,并阻碍第一次插入巨大,所以我认为他们只是在去年,如果非常有效的,采取。

2

在ClickHouse中,最优化的方法是将数据存储在“大平面表”中。 因此,您将每条消息存储在单独的行中。 即使在单个节点上,ClickHouse也有150亿行正确。

此外,每个用户直接在消息表(预加入)中属性是合理的,因此您不需要执行JOIN。如果用户属性没有更新,它是合适的。

这些属性将为每个用户的消息重复值 - 这是正确的,因为ClickHouse压缩数据,尤其是重复的值。

如果用户的属性已更新,请考虑将用户表存储在单独的数据库中,并使用“外部词典”功能将其加入。

如果消息更新,只是不更新​​它。用另一行修改消息写入另一个表,并保留旧消息。

重要的是您的表具有正确的主键。您应该使用MergeTree系列中的表格,它不断按主键对数据进行重新排序,从而保持范围查询的效率。主键不需要是唯一的,例如,如果您经常写“from = ...”,并且这些查询必须在短时间内处理,您可以将主键定义为(从)。

您可以使用user_id作为主键:如果用户标识查询频繁且必须尽可能快地处理,但随后使用谓词“from”查询将扫描整个表格(请注意,ClickHouse会进行全面扫描)。

如果您需要通过许多不同的属性进行快速查找,您可以使用不同的主键复制表格。通常情况下,表格将被压缩得足够好,并且您可以负担得起在不同范围查询中以不同顺序的少量副本中的数据。