问题如下...
考虑到 192 万亿条记录,我应该考虑什么?
我主要关心的是速度。
这是表格...
CREATE TABLE `ref` (
`id` INTEGER(13) AUTO_INCREMENT DEFAULT NOT NULL,
`rel_id` INTEGER(13) NOT NULL,
`p1` INTEGER(13) NOT NULL,
`p2` INTEGER(13) DEFAULT NULL,
`p3` INTEGER(13) DEFAULT NULL,
`s` INTEGER(13) NOT NULL,
`p4` INTEGER(13) DEFAULT NULL,
`p5` INTEGER(13) DEFAULT NULL,
`p6` INTEGER(13) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY (`s`),
KEY (`rel_id`),
KEY (`p3`),
KEY (`p4`)
);
以下是查询...
SELECT id, s FROM ref WHERE red_id="$rel_id" AND p3="$p3" AND p4="$p4"
SELECT rel_id, p1, p2, p3, p4, p5, p6 FROM ref WHERE id="$id"
INSERT INTO rel (rel_id, p1, p2, p3, s, p4, p5, p6)
VALUES ("$rel_id", "$p1", "$p2", "$p3", "$s", "$p4", "$p5", "$p6")
这里有一些注释...
- SELECT 的执行频率比 INSERT 要高得多。不过,有时我想一次添加几百条记录。
- 从负载角度来看,几个小时内不会有任何变化,然后可能会同时出现几千个查询。
- 我觉得我无法再进行标准化(需要组合的 p 值)
- 整个数据库具有很强的关系性。
- 这将是迄今为止最大的表格(下一个最大的表格约为 900k)
更新(2010 年 8 月 11 日)
有趣的是,我有了第二种选择……
我可以存储 192 万亿,而不是2.6*10^16(15 个零,代表 26 千万亿)...
但在第二种选择中,我只需要将一个 bigint(18) 存储为表中的索引。就是这样 - 只有一列。所以我只需要检查值是否存在。偶尔添加记录,从不删除它们。
所以这让我认为一定有一个比 mysql 更好的解决方案来简单地存储数字......
有了第二个选择,我应该选择它还是坚持第一个……
[编辑]刚刚收到一些已完成测试的消息 - 使用此设置的 1 亿行数据可在 0.0004 秒内返回查询[/编辑]
答案1
pQd 对 7PB 的估计看起来合理,而且对于 RDBMS 来说,这是大量的数据。我不确定我是否听说过有人使用任何共享磁盘系统处理 7PB,更不用说 MySQL 了。使用任何共享磁盘系统查询这种数据量都会慢得无法使用。最快的 SAN 硬件即使在针对大型流式查询进行调整时也只能达到 20GB/秒。如果您能负担得起这种规格的 SAN 硬件,那么您可以使用比 MySQL 更适合这项工作的东西。
事实上,我很难想象这样一种情况:您有预算购买这种规格的磁盘子系统,但没有预算购买更好的 DBMS 平台。即使使用 600GB 磁盘(目前市场上最大的 15K“企业”驱动器),您也需要大约 12,000 个物理磁盘驱动器来存储 7PB。SATA 磁盘会更便宜(而使用 2TB 磁盘,您需要大约 1/3 的数量),但速度会慢得多。
EMC 或 Hitachi 等主要供应商提供的这种规格的 SAN 价格将高达数百万美元。上次我使用主要供应商提供的 SAN 设备时,IBM DS8000 上的空间传输成本超过 10,000 英镑/TB,还不包括控制器的任何资本津贴。
对于如此多的数据,您确实需要一个像 Teradata 或 Netezza 这样的无共享系统。对 MySQL 数据库进行分片可能有效,但我建议使用专门构建的 VLDB 平台。无共享系统还允许您在节点上使用更便宜的直接连接磁盘 - 了解 Sun 的 X4550(thumper)平台是一种可能性。
您还需要考虑您的性能要求。
- 查询的可接受运行时间是多少?
- 您多久查询一次数据集?
- 大多数查询是否可以使用索引来解决(即,它们是否只查看一小部分 - 比如说:不到 1% 的数据),或者它们是否需要进行全表扫描?
- 数据加载到数据库的速度有多快?
- 您的查询是否需要最新的数据或您是否可以使用定期刷新的报告表?
简而言之,反对 MySQL 的最有力论据是,如果可能的话,您将竭尽全力才能在 7PB 数据上获得不错的查询性能。这种数据量确实使您陷入了无共享领域,无法制作可以相当快速地查询它的东西,并且您可能需要一个从一开始就为无共享操作设计的平台。单是磁盘成本就足以让任何合理的 DBMS 平台的成本相形见绌。
笔记:如果您确实拆分了运营数据库和报告数据库,则不必对两者使用相同的 DBMS 平台。从同一张 7PB 表获取快速插入和亚秒级报告至少是一项技术挑战。
鉴于您表示可以忍受报告延迟,您可以考虑使用单独的捕获和报告系统,并且可能不需要将所有 7PB 数据都保存在操作捕获系统中。考虑使用 Oracle 等操作平台(MySQL 可以使用 InnoDB 实现这一点)进行数据捕获(同样,除非您有很多用户)和 VLDB 平台,例如Teradata, Sybase IQ, 红砖, 网通(注:专有硬件)或绿梅用于报告
答案2
将其分片。在这种规模下,拥有一个大型实例无异于自杀 - 考虑可能的备份恢复,表空间损坏,添加新列或任何其他“内部管理”流程 - 所有这些都不可能在这种规模下在合理的时间内完成。
简单的信封背面计算 - 假设除 64 位 id 之外的所有列都是 32 位整数;不包含索引:
每行 8*4B+8B = 40B(这是非常乐观的)
192 万亿行,每行 40B,总计近 7 PB
也许您可以重新考虑整个事情,总结信息以便快速报告,并在有人需要深入了解细节时存储给定时间间隔的压缩记录。
要回答的问题:
- 如果系统崩溃/重启,可以接受的停机时间是多长?
- 当您需要恢复备份或将服务器从生产中拉出来进行计划维护时,可访问的停机时间是多少。
- 您想要多久备份一次以及备份到哪里?
随机链接-插入速度:
- http://highscalability.com/blog/2010/5/20/strategy-scale-writes-to-734-million-records-per-day-using-t.html
- https://stackoverflow.com/questions/654594/
2022-07-22 编辑:已经过去了很多时间,新的解决方案也出现了。值得考虑 ClickHouse、Apache Druid 和其他可以大量压缩数据的列式数据库引擎。
答案3
可能还有其他方法,如果您只想查看它们是否在集合中,而不是存储数千万亿个数字。 布隆过滤器是一种概率方法,通过多种方式进行哈希处理。此外,可能出现误报,但不可能出现漏报。(因此,它可能会说数字在集合中 - 并且是错误的,但如果它确实在集合中,它不会说它不在那里)。还存在需要存储大量项目的问题,但至少它可以稍微减少工作数据集的大小。
答案4
除了疯狂地调整数据库参数(使用 mysqltuner 帮助)以尽可能多地缓存 SELECT 之外,在插入几百条记录时,您可能需要调查的一件事是 START TRANSACTION/CoMMIT(假设是 InnoDB),以避免逐行锁定开销,并大大缩短插入时间。我还会将表创建为 MyISAM 和 InnoDB,并在其上运行测试,以查看在缓存收紧后哪个真正更快 - MyISAM 并不总是读取速度更快 - 看看这个:
http://www.mysqlperformanceblog.com/2007/01/08/innodb-vs-myisam-vs-falcon-benchmarks-part-1/
在测试期间,并发线程的数量也应该上下变化,直到找到服务器上可以承受的用于调整缓存的 RAM 大小的最佳点;您可能会发现,虽然通过计算可以支持更多线程,但如果线程数过高,数据库本身的性能实际上可能会更差。
此外,如果您使用 MyISAM 和/或 InnoDB file-per-table,您可以研究为 /var/lib/mysql 创建不同的文件系统挂载点,该挂载点已调整为较小的块大小并调整了 fs-type 参数 - 即 ext3/ext4/resiserfs,您可以使用 data=writeback 作为日志并禁用更新文件系统上的访问时间以提高 I/O 速度。