译者 | 布加迪
审校 | 孙淑娟
说到为具体应用选择数据库,有很多不同的选项。经常讨论的话题似乎是选择SQL数据库还是选择NoSQL数据库,即数据应该存储在关系数据库中,还是存储在键值、文档或图形数据库之类的NoSQL数据库中。

另一种选择是索性使用列数据库。本文介绍为什么有必要做出这种选择,以及列数据库的一些优缺点。
顾名思义,列(或列式)数据库将按列组织而不是按行组织的数据存储在磁盘上。以物联网传感器为例,基于行的数据库会如图所示将数据存储在磁盘上:

而列数据库将组织相同的数据,以便每个列值按顺序存储在磁盘上:

列数据库的主要优点是,由于压缩比提高,它可以大大缩减存储数据所需的磁盘空间。此外,列数据库在处理分析型查询时比基于行的传统数据库要快得多。
那么,改变数据的存储格式究竟如何提升性能的呢?与传统数据库相比,有几个因素导致列数据库能够为联机分析处理(LAP)工作负载提供高得多的性能。
第一个原因是压缩比提高。这是由于列数据库能够为每种类型的数据使用最佳压缩算法,因为每列都是相同类型的数据,而不是一行混合类型的数据。这不仅降低了磁盘上的存储成本,还提高了性能,因为需要的磁盘寻道更少,内存可以容纳更多的数据。
列数据库提升性能的另一种方法是实际上在底层存储同一列的多个不同版本,这些版本按不同的顺序进行排序,以便为某些查询加快过滤和选择的速度。
列数据库还可以通过许多其他方法来提升性能。下面是几个例子:
这篇论文分析了列数据库的性能,作为论文一部分进行的测试的示意图显示了上述优化的结果。基于TPC-H数据仓库基准数据集,列数据库的运行速度比传统的行结构数据库快10倍左右。

该图显示了哪些优化对列数据库的性能影响最大,在此处,后期物化带来的性能提升最大。
与计算机科学界的几乎所有事情一样,列数据库性能方面也进行了一番取舍。它们针对分析型工作负载进行了优化,本身不适合传统的联机事务处理(OLTP)工作负载,而关系数据库为这种工作负载而设计。
最大的性能牺牲将出现在试图更新特定数据点或写入单个数据点的情况下。就列数据库而言,您希望尽可能批量插入数据。
列数据库还会对读查询有影响,您获取一行中的所有数据,就像使用关系数据库一样。由于必须重新构造每一列才能创建整行,因此性能会受到影响。
列数据库非常适合您想要分析大量数据的任何情况。不妨看一下几个常见的用例。
列数据库非常适合分析销售数据,因为它们让您可以以各种方式划分信息。这可以帮助您确定可能无法看到的趋势和模式。比如说,可以使用列数据库按位置、品牌或产品类别来比较一段时间不同产品的销售数据。
应用程序性能监控是使用列数据库帮助提高软件可靠性和性能的另一种常见情况。通过跟踪和分析有关应用程序运行状况的数据,您可以在问题导致应用程序崩溃或变慢之前发现问题。这有助于避免停运时间,并确保用户获得最佳体验。如果使用列数据库,您可以存储粒度更细的数据以获得更深入的洞察力,同时因出色的数据压缩而降低成本。
组织在部署越来越多的联网设备,其中许多设备收集用于分析工作负载的数据。列数据库可用于存储这些数据,以实现实时警报,还可用于生成预测,在许多不同行业提高效率。
到目前为止,我们已经大体了解了列数据库及其优点。虽然所有列数据库有相同的特征,可以有效地用作通用数据仓库或数据湖,不过下面介绍如何针对更具体的性能特征对它们进行调优和优化。
InfluxDB IOx是一款面向InfluxDB的开源列存储引擎,为处理时间序列数据进行了优化。时间序列数据在性能方面带来了独特的挑战:
时间序列数据还往往大批量到达,这需要快速获取能力,以便能够快速索引和查询数据,用于实时监控和警报。此外,许多用户希望能够长期存储这些数据,用于历史分析和预测,又不必担心成本过高。
InfluxDB让用户可以集两者之所长,其办法是管理数据的生命周期,并在热存储和冷存储之间移动数据,历史数据方面获得快速性能,同时通过对未频繁查询的数据使用更便宜的对象存储来降低存储成本。
实现这一目标的关键手段就是构建和贡献Apache Arrow、DataFusion和Parquet之类的项目。Arrow允许数据在内存中以列格式压缩,并在数据库的不同部分之间移动。Parquet用于高效的持久性存储,DataFusion提供高性能查询和SQL支持。其他许多主要项目和厂商也在夯实Parquet和Arrow项目,这些项目还能够与更广泛的大数据生态系统实现集成和兼容。
Apache Druid是一款拥有底层列数据结构的实时数据库。Druid适用于典型的数据仓库类型工作负载,比如您期望从列数据库获得的工作负载,但它也优先考虑低延迟响应时间,常常用于交互式用户界面之类的对象。
DuckDB是为OLAP工作负载设计的进程内数据库,实际上旨在成为面向分析的SQLite。DuckDB使用列式矢量化处理,以出色的性能运行SQL查询,可以轻松嵌入到应用程序中。DuckDB的主要卖点是,在大多数OLAP数据库要么云托管要么需要复杂安装过程的环境下,它很容易在本地设置和运行。
说到底,技术决策归结为什么技术对您的用例有意义。说到长期构建应用程序,选择数据库可能是最重要的选择之一,因此有必要了解所有可用的选项,选择最适合的那一种。
如果您在处理主要用于分析的大量数据,那么列数据库可能是个不错的选择。
原文标题:What Is a Column Database and When Should You Use One?,作者:Charles Mahler
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h