我有一个问题,我需要非常快地将大量数据(5+十亿行)加载到数据库中(理想情况下不超过30分钟,但越快越好),最近有人建议我研究postgresql (我使用mysql失败了,正在寻找hbase/cassandra)。我的设置是我有一个生成大量数据的集群(目前是8台服务器),我在考虑在集群中的每台机器上本地运行数据库,它在本地快速写入,然后在最后(或在整个数据生成过程中)将数据合并在一起。数据没有任何顺序,所以我不关心它在哪个特定的服务器上(只要它最终在那里)。
我的问题是,有没有好的教程或地方可以学习PostgreSQL自动分片(我发现像sykpe这样的公司做自动分片的结果,但没有教程,我想自己玩这个)?我想要做的事情是可能的吗?因为数据没有任何顺序,所以我打算使用自动递增的ID号,如果合并数据会导致冲突吗(这已经不是一个大问题了)?
更新:下面Frank的想法消除了我所问到的自动递增冲突问题。基本上,现在的问题是,我如何学习自动分片,以及它是否支持将数据分布式上传到多个服务器?
发布于 2012-04-26 11:22:03
首先:您真的需要将集群中生成的数据直接插入到关系数据库中吗?您并不介意在最后合并它,那么为什么还要费心将其插入到数据库中呢?在你的位置上,我会让你的集群节点写平面文件,可能是gzip格式的CSV数据。然后,我使用pg_bulkload之类的工具批量导入和合并该数据。
如果您确实需要直接插入到关系数据库中:这就是PgPool-II和(特别是) PgBouncer的作用所在。将PgBouncer配置为跨不同节点进行负载均衡,这样您就可以很好地进行排序了。
请注意,PostgreSQL是一个具有强大数据持久性保证的事务性数据库。这也意味着,如果你以一种简单的方式使用它,那么做大量的小写操作可能会很慢。您必须考虑在数据持久性、速度和硬件成本之间做出什么样的权衡。
在一个极端情况下,每个INSERT可以是它自己的事务,在返回成功之前同步提交到磁盘。这将每秒的事务数限制为您的磁盘子系统可以执行的fsync()数,通常每秒只能执行数十或数百个(没有备用电池的RAID控制器)。如果您没有执行任何特殊操作,并且没有将INSERT包装在BEGIN和COMMIT中,则这是默认设置。
在另一个极端,您说“我真的不在乎我是否丢失了所有这些数据”,然后使用unlogged tables进行插入。这基本上给了数据库在不能保证数据正常的情况下丢弃数据的权限-比如,在操作系统崩溃、数据库崩溃、断电等情况下。
中间地带可能是你想要的地方。这涉及到asynchronous commit、group commits (commit_delay和commit_siblings)的某种组合,将插入批处理到显式BEGIN和END中的组中,等等。您可以一次加载几千条记录,而不是插入批处理。所有这些东西都在数据持久性与速度之间进行了权衡。
对于快速的大容量插入,您还应该考虑插入到除了主键以外没有任何索引的表中。也许甚至连这都不是。批量插入完成后,创建索引。这将是一个地狱般的快得多。
发布于 2012-04-26 04:51:52
下面是一些可能会有帮助的事情:
(time timestamp, values double precision[])而不是更正确的(time timestamp, instrument_id int, value double precision)的表中来提高效率。这是一种明显的非正规化,有助于提高效率。(我blogged讲述了我自己使用这个方案的经验。)发布于 2017-08-17 19:55:59
对PostgreSQL自动分片使用citus。此外,this link也很有帮助。
https://stackoverflow.com/questions/10323327
复制相似问题