数十亿行的最佳数据存储

时间:2010-05-08 16:11:03

标签: sql-server nosql

我需要能够为数十亿条记录存储少量数据(大约50-75字节)(一年约30亿/月)。

唯一的要求是对具有相同GUID的所有记录进行快速插入和快速查找,并且能够从.net访问数据存储。

我是一个SQL服务器人,我认为SQL Server 可以这样做,但是在谈论BigTable,CouchDB和其他nosql解决方案时,它听起来越来越像一个替代由于分布式查询和扩展的优化,传统的RDBS可能是最佳的。我尝试了cassandra,.net库目前没有编译,或者可能会更改(以及cassandra本身)。

我已经研究过许多可用的nosql数据存储,但找不到满足我作为强大的生产就绪平台的需求。

如果您必须存储360亿个小而扁平的记录,以便可以从.net访问,那会选择什么以及为什么?

11 个答案:

答案 0 :(得分:98)

存储~3.5TB的数据并插入大约1K / sec 24x7,并且还以未指定的速率查询,可以使用SQL Server,但还有更多问题:

  • 您对此有何可用性要求?正常运行时间为99.999%,或者足够95%?
  • 您有什么可靠性要求?缺少一个插页会花费你100美元吗?
  • 您有哪些可恢复性要求?如果您丢失了一天的数据,这有关系吗?
  • 您有什么一致性要求?是否需要保证在下次读取时可以看到写入?

如果您需要我强调的所有这些要求,那么无论您尝试什么噱头(分片,分区等),您建议的负载将在关系系统,任何系统上花费数百万美元的硬件和许可。根据他们的定义,nosql系统不符合所有这些要求。

显然,你已经放宽了其中一些要求。有一个很好的视觉指南比较基于Visual Guide to NoSQL Systems的“挑选2出3”范例的nosql产品:

nosql comparisson

OP评论更新后

使用SQL Server,这将是直接实现:

  • 一个表聚簇(GUID,时间)键。是的,将获得fragmented,但碎片会影响预读,只有大范围扫描才需要预读。由于您只查询特定的GUID和日期范围,因此碎片无关紧要。是的,是一个宽键,所以非叶页的密钥密度很低。是的,这会导致填充因子不佳。是的,可能会发生页面拆分。尽管有这些问题,但鉴于要求,仍然是最佳的集群关键选择。
  • 按时间对表进行分区,以便您可以通过automatic sliding window实现有效删除过期记录。通过上个月的在线索引分区重建来增加此功能,以消除GUID群集引入的不良填充因子和碎片。
  • 启用页面压缩。由于首先是GUID的聚簇密钥组,因此GUID的所有记录将彼此相邻,从而使page compression很有可能部署字典压缩。
  • 您需要一个快速的IO路径来存储日志文件。您对高吞吐量感兴趣,而不是日志的低延迟以保持1K插入/秒,因此stripping是必须的。

分区和页面压缩都需要企业版SQL Server,它们不适用于标准版,两者对于满足要求非常重要。

作为旁注,如果记录来自前端Web服务器场,我会将Express放在每个Web服务器上,而不是在后端插入INSERT,我会SEND将信息发送到后面结束,使用与Web服务器共存的Express上的本地连接/事务。这为解决方案提供了更好的可用性故事。

所以这就是我在SQL Server中的表现。好消息是,您将面临的问题得到很好的理解,解决方案也是众所周知的。这并不一定意味着这比使用Cassandra,BigTable或Dynamo所能达到的要好。我会让一些人更多地了解无法解决问题的事情。

请注意,我从未提及编程模型,.Net支持等。老实说,我认为它们在大型部署中无关紧要。它们在开发过程中产生巨大的差异,但是一旦部署,开发的速度并不重要,如果ORM开销会导致性能下降:)

答案 1 :(得分:16)

与流行的看法相反,NoSQL不是关于性能,甚至是可扩展性。它主要是关于最小化所谓的对象 - 关系阻抗不匹配,但也是关于水平可伸缩性与RDBMS的更典型的垂直可伸缩性。

对于快速插入和快速查找的简单要求,几乎所有数据库产品都可以。如果要添加关系数据或联接,或者需要强制执行任何复杂的事务逻辑或约束,那么您需要一个关系数据库。没有NoSQL产品可以比较。

如果您需要无模式数据,那么您需要使用面向文档的数据库,例如MongoDB或CouchDB。松散的架构是这些的主要内容;我个人喜欢MongoDB并在一些自定义报告系统中使用它。当数据要求不断变化时,我发现它非常有用。

另一个主要的NoSQL选项是分布式键值存储,例如BigTable或Cassandra。如果要在运行商用硬件的许多计算机上扩展数据库,这些特别有用。显然,它们在服务器上运行良好,但不利用高端硬件以及SQL Server或Oracle或其他专为垂直扩展而设计的数据库,显然,它们不是关系型的并且不利于实施规范化或约束。另外,正如您已经注意到的那样,.NET支持最多也是不稳定的。

所有关系数据库产品都支持有限排序的分区。它们不像BigTable或其他DKVS系统那样灵活,它们不能在数百个服务器上轻松分区,但它听起来并不像您正在寻找的那样。他们非常擅长处理数十亿的记录数,只要您正确地索引和规范化数据,在强大的硬件上运行数据库(特别是如果你能负担得起的SSD),并在2或3或5个物理磁盘上进行分区。必要的。

如果您符合上述标准,如果您在公司环境中工作并且有钱花在合适的硬件和数据库优化上,我现在就坚持使用SQL Server。如果您需要购买便士且需要在低端的Amazon EC2云计算硬件上运行,那么您可能希望选择使用Cassandra或Voldemort(假设您可以使用.NET)。

答案 2 :(得分:12)

很少有人在数十亿行集大小的情况下工作,而且大多数情况下,我在堆栈溢出时看到这样的请求,数据没有接近报告的大小。

每月360亿,每月30亿,即每天约1亿,每小时416万,每分钟约70k行,每秒1.1k行进入系统,持续12个月,假设没有下降时间。

这些数字并非不可能很长,我已经完成了更大的系统,但是你想要仔细检查一下你的意思是什么数量 - 很少有应用确实拥有这个数量。

在存储/检索和非常重要的方面,你没有提到老化数据的老化 - 删除不是免费的。

正常的技术是分区,但是,基于GUID的查找/检索会导致性能不佳,假设您必须在整个12个月内获得每个匹配值。您可以在GUID列上放置聚簇索引,以使您的关联数据聚集为读/写,但是在这些数量和插入速度下,碎片将太高而无法支持,并且它将落在地板上。

我还建议你需要一个非常不错的硬件预算,如果这是一个具有OLTP类型响应速度的严肃应用程序,即通过一些近似的猜测,假设很少的开销索引,大约2.7TB的数据。

在SQL Server阵营中,您唯一想要关注的是新的并行数据仓库版本(麦迪逊),其设计更多用于分割数据并对其运行并行查询以提供针对大型数据集市的高速度

答案 3 :(得分:2)

“我需要能够为数十亿条记录存储少量数据(大约50-75字节)(一年约30亿/月)。

唯一的要求是对具有相同GUID的所有记录进行快速插入和快速查找,并且能够从.net访问数据存储。“

我可以从经验中告诉你,这在SQL Server中是可行的,因为我已经在2009年初完成了......而且它仍然可以运行到现在并且非常快。

该表分为256个分区,请记住这是2005年的SQL版本......我们完全按照你的意思行事,那就是通过GUID存储信息并快速通过GUID检索。

当我离开时,我们有大约2-3亿条记录,并且数据检索仍然非常好(如果通过UI,则为1-2秒,如果在RDBMS上,则为更少),即使数据保留策略即将实例化

所以,长话短说,我从GUID字符串中取出了第8个字符(即中间的某个地方),SHA1将其哈希并转换为小int(0-255)并存储在适当的分区中并使用相同的函数在获取数据时调用。

如果您需要更多信息,请告诉我......

答案 4 :(得分:2)

以下文章讨论了在Microsoft SQL中导入和使用 16 十亿 行表。 http://sqlmag.com/t-sql/adventures-big-data-how-import-16-billion-rows-single-table

来自文章:

  

以下是我的经验中提炼的一些提示:

     
      
  • 具有已定义聚簇索引的表中的数据越多,将未分类的记录导入其中的速度就越慢。在某些   这一点,实际上变得太慢了。
  •   
  • 如果要将表导出到可能的最小文件,请将其设置为本机格式。这适用于包含的表   主要是数字列,因为它们更紧凑   在二进制字段而不是字符数据。如果您的所有数据都是   字母数字,通过以原生格式导出它不会获得太多收益。   不允许数字字段中的空值可以进一步压缩   数据。如果允许字段可以为空,则为字段的二进制   表示将包含一个1字节的前缀,表示多少   将跟随数据字节。
  •   
  • 您不能将BCP用于超过2,147,483,647条记录,因为BCP计数器变量是一个4字节整数。我找不到任何东西   在MSDN或Internet上引用它。如果你的表包含
      超过2,147,483,647条记录,您必须以块的形式将其导出   或编写自己的出口例程。
  •   
  • 在预填充表上定义聚簇索引会占用大量磁盘空间。在我的测试中,我的日志爆炸到原来的10倍   表格大小在完成之前。
  •   
  • 使用BULK INSERT语句导入大量记录时,请包含BATCHSIZE参数并指定多少个   一次提交的记录。如果您不包含此参数,
      您的整个文件作为单个事务导入,其中   需要大量的日志空间。
  •   
  • 将数据放入具有聚簇索引的表中的最快方法是首先预先排序数据。然后,您可以使用BULK进行导入   带有ORDER参数的INSERT语句。
  •   

答案 5 :(得分:1)

有一个不寻常的事实似乎被忽视了。

基本上在一天插入30Mil行后,我需要获取具有相同GUID(可能是20行)的所有行,并且相当确定我会将它们全部取回

仅需要20列,GUID上的非聚集索引就可以正常工作。您可以在另一列上进行聚类,以便跨分区进行数据分散。

我对数据插入有疑问:如何插入?

  • 这是按特定时间表(每分钟,每小时等)批量插入吗?
  • 这些数据的来源是什么(平面文件,OLTP等)?

我认为需要回答这些问题以帮助理解方程式的一方。

答案 6 :(得分:1)

Amazon Redshift是一项很棒的服务。当这个问题最初于2010年发布时,它不可用,但它现在是2017年的主要参与者。它是一个基于列的数据库,从Postgres分叉,所以标准的SQL和Postgres连接器库将与它一起使用。

最适合用于报告目的,尤其是聚合。来自单个表的数据存储在亚马逊云中的不同服务器上,由定义的表distkeys分配,因此您依赖于分布式CPU电源。

所以SELECT,尤其是聚合的SELECT都是闪电般快速的。最好使用Amazon S3 csv文件中的COPY命令来加载大数据。缺点是DELETE和UPDATE比平常慢,但这就是为什么Redshift主要不是跨国数据库,而是更多的数据仓库平台。

答案 7 :(得分:0)

您可以尝试使用Cassandra或HBase,但您需要了解如何根据您的用例设计列族。 Cassandra提供了自己的查询语言,但您需要使用HBase的Java API直接访问数据。 如果您需要使用Hbase,那么我建议使用来自Map-R的Apache Drill查询数据,这是一个开源项目。 Drill的查询语言是SQL兼容的(钻取中的关键字与SQL中的关键字具有相同的含义)。

答案 8 :(得分:0)

每年有那么多记录,您最终将用尽空间。 为什么不支持xfs之类的文件系统存储,它支持2 ^ 64个文件并使用较小的盒子。 不管人们想要多花钱,或者最终要花多少钱,使用一个具有任何数据库SQL NoSQL ..的系统,无论花多少钱,通常都是由电力公司和气象台/提供者(如环境部)控制的,全国各地的电台。 如果您正在执行存储压力..温度。风速..湿度等...之类的操作,并且guid是位置..您仍然可以按年/月/日/小时除以数据。 假设每个硬盘驱动器存储4年的数据。 然后,您可以在带有镜像的较小Nas上运行它, 还可以提供更好的读取速度,并具有多个安装点。 您可以简单地通过网络界面进行搜索 因此,转储location1 / 2001/06/01 / / temperature和location1 / 2002/06/01 / / temperature只会转储这2年(24h)中夏季第一天的每小时温度的内容* 2)48个小文件与搜索具有数十亿条记录并可能花费数百万美元的数据库有关。 查看事物的简单方法。与上帝一起,世界上有15亿个网站知道每个页面有多少页 如果像谷歌这样的公司不得不每30亿次搜索花费数百万美元来购买超级计算机,那它们就会破产了。 取而代之的是,他们拥有电力账单……几百万台废话电脑。 咖啡因索引...耐久..请继续添加。 是的,在SQL上运行索引很有意义,那么很棒 用诸如天气之类的固定事物来构建超级计算机来执行糟糕的任务...统计信息等等,以便技术人员可以吹牛他们的系统在x秒内崩溃xtb ...浪费了本可以花在其他地方的钱。通过运行10台Nas服务器之类的软件很快就不会达到数百万。

答案 9 :(得分:-2)

将记录存储在纯二进制文件中,每个GUID一个文件,不会比这更快。

答案 10 :(得分:-3)

您可以使用MongoDB并使用guid作为分片键,这意味着您可以在多台计算机上分发数据,但是您要选择的数据仅在一台计算机上,因为您通过分片键进行选择。

MongoDb中的分片尚未准备就绪。