最好的数据存储数十亿行

我需要为数十亿条logging(一年约30亿/月)存储less量的数据(大约50-75字节)。

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

我是一个SQL服务器的人,我认为SQL Server 可以做到这一点,但所有关于BigTable,CouchDB和其他nosql解决scheme的讨论,听起来越来越像一个传统的RDBS的替代可能是最好的,由于优化分布式查询和缩放。 我尝试了cassandra,而.net库目前没有编译,或者都可能随着cassandra本身而改变

我已经查看了许多可用的nosql数据存储,但无法find满足我需求的一个强大的生产就绪平台。

如果你必须存储360亿个小logging,这样才能从.net访问,那么会select什么,为什么?

存储〜3.5TB的数据和插入大约1K /秒的24×7,也查询速度没有指定,这是可能的与SQL Server,但还有更多的问题:

  • 你有什么可用性要求? 99.999%的正常运行时间,还是95%够了?
  • 你有什么可靠性要求? 缺less一个插入花费你$ 1M?
  • 你有什么可恢复性要求? 如果你松动了一天的数据,这是否重要?
  • 你有什么一致性要求? 是否需要保证在下一次读取时可以看到写入?

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

所以显然你已经放松了一些这些要求。 有一个很好的视觉指南,比较基于“视觉指南”中的“挑选2”3范例的nosql产品与NoSQL系统 :

nosql comparisson

OP评论更新后

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

  • 一个表集群(GUID,时间)键。 是的,会变得分散 ,但是碎片会影响预读,只有在大范围扫描时才需要预读。 由于您只查询特定的GUID和date范围,因此碎片并不重要。 是的,是一个很宽的关键,所以非叶页密度将会很差。 是的,这将导致差的填充因子。 是的,页面拆分可能会发生。 尽pipe存在这些问题,给出了要求,仍然是最好的集群关键select。
  • 按时间划分表格,以便通过自动滑动窗口实现高效删除已过期的logging。 使用上个月的在线索引分区重build来增加此值,以消除由GUID集群引入的糟糕的填充因子和碎片。
  • 启用页面压缩。 由于首先通过GUIDbuild立聚簇键组,GUID的所有logging将彼此相邻,从而为页面压缩部署字典压缩提供了一个很好的机会。
  • 你需要一个快速的IOpath来存放日志文件。 您对高吞吐量感兴趣,而不是为了保持1K插入/秒的低延迟,所以剥离是必须的。

分区和页面压缩都需要企业版SQL Server,它们将不能在标准版上工作,而且两者对于满足要求都非常重要。

作为一个侧面说明,如果logging来自前端Web服务器场,我会把每个Web服务器上的Express,而不是后端的INSERT,我会将信息SEND到后端,使用本地连接/ Express上的交易与Web服务器位于同一位置。 这给解决scheme提供了更好的可用性故事。

所以这就是我如何在SQL Server中做到这一点。 好消息是,你将面临的问题是很好的理解和解决scheme是已知的。 这并不意味着这比用Cassandra,BigTable或Dynamo可以实现的更好。 我会让更多的人知道在没有sql-ish的事情上争论他们的情况。

请注意,我从来没有提到编程模型,.Net支持等。 我真的认为他们在大型部署中无关紧要。 他们在开发过程中有很大的不同,但是一旦部署,开发速度有多快并不重要,如果ORM开销杀死性能:)

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

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

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

另一个主要的NoSQL选项是分布式Key-Value Store,如BigTable或Cassandra。 如果要在运行商用硬件的许多机器上扩展数据库,这些特别有用。 他们在服务器上的工作也很好,显然,但不要利用高端硬件以及SQL Server或Oracle或其他devise用于垂直缩放的数据库,显然,它们不是关系型的,不利于执行规范化或约束。 另外,正如你所注意到的,.NET支持往往是最好的。

所有关系数据库产品都支持有限种类的分区。 它们不像BigTable或其他DKVS系统那样灵活,它们不能在数百台服务器之间轻松分区,但实际上听起来并不像你想要的那样。 只要您正确地对数据进行索引和规格化,在强大的硬件上运行数据库(尤其是SSD,如果您能负担得起的话),并且跨2或3或5个物理磁盘进行分区,那么他们在处理数十亿的logging计数方面相当出色。必要。

如果你符合上述标准,如果你在一个企业环境中工作,并有钱花费体面的硬件和数据库优化,我现在坚持使用SQL Server。 如果您正在为便携式计算机购买硬盘,并且需要在低端Amazon EC2云计算硬件上运行这个硬件,那么您可能会select使用Cassandra或Voldemort(假设您可以使用.NET)。

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

每个月有360亿,每月30亿,即每天约1亿,每小时416万,每分钟约7万行,每秒钟有1.1万行,持续12个月,假定没有停机时间。

这些数字不是不可能长时间的,我做了更大的系统,但是你想再仔细检查一下这个数字是否是你的意思 – 很less有应用程序真的有这个数量。

在存储/检索方面,还没有提到的相当关键的方面是老化数据 – 删除不是免费的。

正常的技术是看分区,然而,基于GUID的查找/检索将导致性能较差,假设你必须在整个12个月期间获得每个匹配值。 您可以在GUID列上放置聚簇索引,将相关的数据聚集在一起进行读取/写入,但是在这些数量和插入速度下,碎片将会太高而无法支持,并且会落在地板上。

我还build议,如果这是一个具有OLTPtypes响应速度的严重应用程序,那么需要一个非常好的硬件预算,这是通过一些近似的猜测,假设只有很less的索引开销,大约2.7TB的数据。

在SQL Server阵营中,您唯一可能需要考虑的是新的并行数据仓库版本(madison),该版本专门用于对数据进行分片并运行并行查询,以针对大型数据市场提供高速度。

“我需要能够存储数十亿条logging(大约每年30亿美元)的小数据(大约50-75字节)。

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

我可以从经验告诉你,这在SQL Server中是可以实现的,因为我在2009年初完成了这个工作,现在仍在运行,并且速度很快。

该表是分区在256个分区,请记住这是2005年的SQL版本…我们做了正是你说的,这是通过GUID存储信息的位,并通过GUID快速检索。

当我离开时,我们有大约2-3亿条logging,并且数据检索仍然非常好(即使数据保留策略即将被实例化,如果通过UI获得1-2秒,或者在RDBMS上获得更less)。

所以,长话短说,我从GUIDstring中取出了第8个字符(即中间的某个地方),SHA1对它进行了散列处理,并将其转换为小的int(0-255),并存储在相应的分区中,并在获取相同的函数调用时数据回来了。

如果你需要更多信息,请给我打电话

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

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

只需要20列,GUID上的非聚集索引将工作得很好。 您可以在另一列上进行群集以便跨分区进行数据分散。

我有一个关于数据插入的问题:它是如何被插入的?

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

我想这些都需要回答,以帮助理解等式的一个方面。

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

从文章:

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

  • 具有定义聚集索引的表中的数据越多,导入未sortinglogging的速度就越慢。 在某些时候,它变得太慢而不切实际。
  • 如果要将表导出到尽可能最小的文件,请将其设置为原始格式。 这对于包含大多数数字列的表格效果最好,因为它们在二进制字段中比字符数据更紧凑。 如果你所有的数据都是字母数字的,你将不会以原生格式输出。 不允许数字字段中的空值可以进一步压缩数据。 如果你允许一个字段为空,那么这个字段的二进制表示将包含一个1字节的前缀,表示将会有多less字节的数据。
  • BCP计数器variables是一个4字节的整数,因此您不能使用超过2,147,483,647条logging的BCP。 我无法在MSDN或互联网上find任何这方面的参考。 如果你的表包含
    超过2,147,483,647条logging,您将不得不将其导出为大块
    或编写自己的导出例程。
  • 在预先填充的表上定义聚簇索引需要大量的磁盘空间。 在我的testing中,我的日志爆炸到原来的10倍
    桌子大小在完成之前。
  • 使用BULK INSERT语句导入大量logging时,请包含BATCHSIZE参数并指定多less个logging
    logging一次提交。 如果你不包含这个参数,
    您的整个文件被导入为单个事务,
    需要大量的日志空间。
  • 将数据导入到具有聚簇索引的表中的最快方法是首先对数据进行预处理。 然后您可以使用BULK导入它
    INSERT语句与ORDER参数。

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

最好用于报告目的,尤其是聚合。 来自单个表的数据存储在亚马逊云中的不同服务器上,通过定义的表分配,因此您依靠分布式CPU的能力。

所以select和特别是聚合的select是闪电般的。 加载大量数据应该最好使用Amazon S3 csv文件中的COPY命令完成。 缺点是删除和更新比平常慢,但这就是为什么Redshift不是主要跨国数据库,而是更多的数据仓库平台。

您可以尝试使用Cassandra或HBase,但您需要阅读如何根据您的使用案例devise列族。 Cassandra提供了自己的查询语言,但是您需要使用HBase的Java API直接访问数据。 如果您需要使用Hbase,那么我build议使用来自Map-R(这是一个开源项目)的Apache Drill来查询数据。 Drill的查询语言符合SQL标准(钻取中的关键字与SQL中的关键字相同)。

以纯二进制文件(每个GUID一个文件)存储logging不会比这更快。

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

MongoDb中的分片还没有准备就绪。