6

我有很多文本文件,它们的总大小约为 300GB ~ 400GB。它们都是这种格式

key1 value_a
key1 value_b
key1 value_c
key2 value_d
key3 value_e
....

每行由一个键和一个值组成。我想创建一个数据库,它可以让我查询一个键的所有值。例如,当我查询 key1 时,返回 value_a、value_b 和 value_c。

首先,将所有这些文件插入数据库是一个大问题。我尝试使用 LOAD DATA INFILE 语法将几 GB 大小的块插入 MySQL MyISAM 表。但似乎 MySQL 不能利用多核来插入数据。它像地狱一样慢。所以,对于这么多记录,我认为 MySQL 不是一个好的选择。

此外,如果可能,我需要定期、每周甚至每天更新或重新创建数据库,因此,插入速度对我来说很重要。

单个节点不可能有效地进行计算和插入,要高效,我认为最好在不同节点中并行执行插入。

例如,

node1 -> compute and store 0-99999.txt
node2 -> compute and store 10000-199999.txt
node3 -> compute and store 20000-299999.txt
....

所以,这是第一个标准。

标准 1. 分布式批处理方式插入速度快。

然后,正如您在文本文件示例中看到的那样,最好为不同的值提供多个相同的键。就像示例中的 key1 映射到 value_a/value_b/value_c 一样。

标准 2. 允许多个键

然后,我需要查询数据库中的键。不需要关系或复杂的连接查询,我只需要简单的键/值查询。重要的部分是相同值的多个键

标准 3. 简单快速的键值查询。

我知道有 HBase/Cassandra/MongoDB/Redis....等等,但我对它们都不熟悉,不确定哪一个适合我的需求。所以,问题是 - 使用什么数据库?如果它们都不符合我的需求,我什至打算建立自己的,但这需要努力:/

谢谢。

4

6 回答 6

3

可能有很多系统可以满足您的需求。您的要求通过以下几种方式让事情变得轻松愉快:

  • 因为您不需要任何跨键操作,您可以使用多个数据库,通过散列或范围分片在它们之间划分键。这是解决您在 MySQL 中观察到的缺乏并行性的简单方法,并且可能会在许多其他数据库系统中观察到。
  • 因为您从不进行任何在线更新,所以您可以批量构建一个不可变数据库,然后在一天/一周的剩余时间里查询它。我希望您通过这种方式获得更好的性能。

我倾向于构建一组散列分片LevelDB表。也就是说,我不会使用leveldb::DB支持更复杂数据结构(一堆表和一个日志)的实际,以便您可以进行在线更新;相反,我会直接使用leveldb::Tableleveldb::TableBuilder对象(没有日志,给定键只有一个表)。这是一种非常有效的查询格式。如果您的输入文件已经像您的示例中那样排序,那么表格构建也将非常有效。您可以通过增加分片数量来实现所需的任何并行性——如果您使用 16 核、16 磁盘机器来构建数据库,则至少使用 16 个分片,所有这些分片都是并行生成的。如果您使用 16 台 16 核、16 磁盘机器,则至少 256 个分片。如果像现在很多人一样,您的磁盘数量比核心数量少得多,请同时尝试两者,但您可能会发现更少的分片可以更好地避免寻道。如果你小心点,我认为你基本上可以在构建表时最大限度地提高磁盘吞吐量,这就是我所说的很多。d 由于键前缀压缩(以及可选的 Snappy 块压缩),预计这些表明显小于您的输入文件。您将主要避免搜索,因为除了您通常可以在 RAM 中缓冲的相对较小的索引之外,leveldb 表中的键的存储顺序与您从输入文件中读取它们的顺序相同,再次假设您的输入文件已经排序。如果不是,您可能需要足够的分片,以便您可以在 RAM 中对分片进行排序,然后将其写出,也许更按顺序处理分片。再次假设您的输入文件已经排序。如果不是,您可能需要足够的分片,以便您可以在 RAM 中对分片进行排序,然后将其写出,也许更按顺序处理分片。再次假设您的输入文件已经排序。如果不是,您可能需要足够的分片,以便您可以在 RAM 中对分片进行排序,然后将其写出,也许更按顺序处理分片。

于 2012-04-08T09:30:31.530 回答
1

我建议你使用 SSDB(https://github.com/ideawu/ssdb),一个适合存储数据集合的 leveldb 服务器。

您可以将数据存储在地图中:

ssdb->hset(key1, value1)
ssdb->hset(key1, value2)
...

list = ssdb->hscan(key1, 1000);
// now list = [value1, value2, ...]

SSDB速度快(速度是Redis的一半,每秒30000次插入),是leveldb的网络封装,单线安装启动。其客户包括 PHP、C++、Python、Java、Lua、...

于 2013-08-27T00:39:56.183 回答
0

传统的答案是,如果你有大笔钱,就使用 Oracle,如果你没有,就使用 PostgreSQL。但是,我建议您也看看像 mongoDb 这样的解决方案,我发现它非常快,并且还可以适应您的架构不固定并且可以在您的数据中更改的场景。

于 2012-04-05T09:00:29.517 回答
0

由于您已经熟悉 MySQL,因此我建议您在迁移到新系统之前尝试所有 MySQL 选项。许多大数据系统针对非常具体的问题进行了调整,但在 RDBMS 认为理所当然的领域表现不佳。此外,大多数应用程序需要常规 RDBMS 功能以及大数据功能。因此,迁移到新系统可能会产生新问题。

还要考虑您选择的系统周围可用的软件生态系统、社区支持和知识库。

回到解决方案,数据库中有多少行?这是一个重要的指标。我假设超过1亿。

尝试分区。它可以帮助很多。您的选择标准很简单,而且您不需要连接,这一事实只会让事情变得更好。

Postgres 有一种处理分区的好方法。它需要更多的代码来启动和运行,但提供了惊人的控制。与 MySQL 不同,Postgres 对分区数量没有硬性限制。Postgres 中的分区是常规表。这使您可以更好地控制索引、搜索、备份、恢复、并行数据访问等。

于 2012-04-08T10:24:41.020 回答
0

看看HBase。您可以使用列针对一个键存储多个值。与 RDBMS 不同,您不需要在每一行中具有固定的列集,但可以在一行中具有任意数量的列。由于您通过键(HBase 用语中的行键)查询数据,因此您可以通过读取该行中所有列的值来检索给定键的所有值。

HBase 也有保留期的概念,因此您可以决定哪些列可以存活多长时间。因此,数据可以根据需要自行清理。人们采用了一些有趣的技术来利用保留期。

HBase 具有很强的可扩展性,并且支持非常快速的读取和写入。

于 2012-07-30T18:01:31.863 回答
0

InfoBright 或许是个不错的选择。

于 2012-10-30T14:08:37.153 回答