当前位置: 首页 > 科技观察

哪些数据库是行存储?哪些是列存储?有什么不同?

时间:2023-03-13 22:31:52 科技观察

大多数数据库系统存储一组数据记录,这些记录由表中的列和行组成。字段是列和行的交集:某种类型的单个值。属于同一列的字段通常具有相同的数据类型。例如,如果我们定义一个包含用户数据的表,所有用户名将属于同一类型并属于同一列。逻辑上属于同一数据记录(通常由键标识)的值的集合构成一行。对数据库进行分类的一种方法是根据数据在磁盘上的存储方式:按行或按列。表可以水平分区(属于同一行的值存储在一起)或垂直分区(属于同一列的值存储在一起)。图1-2描述了这种区别:a)显示按列分区的值,b)显示按行分区的值。▲图1-2:面向列和行存储的数据布局面向行的数据库有很多例子:MySQL、PostgreSQL,以及大多数传统的关系型数据库。开源、面向列的数据存储的两个先驱是MonetDB和C-Store(C-Store是Vertica的开源前身)。01面向行的数据布局面向行的数据库按记录或行来存储数据。它的布局非常类似于表格的数据表示,其中每一行都有相同的字段集。例如,面向行的数据库可以有效地存储包含姓名、出生日期和电话号码的用户条目:|编号|名称|出生日期|电话号码||10|约翰|1981年8月1日|+1111222333||20|山姆|1988年9月14日|+1555888999||30|基思|多个字段由一个键(在本例中为单调递增的ID)唯一标识。代表单个用户的数据记录的所有字段通常一起读取。创建数据时(例如,当用户填写注册表时),我们也会将它们一起写入数据库。同时,我们可以单独修改一个字段。面向行的存储在需要逐行访问数据的情况下最有用,其中将整行存储在一起可以改善空间局部性。由于持久性介质(如磁盘)上的数据通常以块为单位进行访问(换句话说,磁盘访问的最小单位是块),因此单个块可能包含一行中所有列的数据。这对于我们想要访问整个用户记录的情况非常有用,但是这样的存储布局会使访问多个用户记录的一个字段的查询(例如,仅获取电话号码的查询)更加昂贵,因为数据其他字段在这个过程中也会被读入。02面向列的数据布局面向列的数据库将数据垂直(即按列)分区,而不是按行存储。在这种数据存储布局中,同一列的值连续存储在磁盘上(而不是像前面的示例那样连续存储行)。例如,如果我们要存储股票市场的历史价格,那么股票价格栏中的数据将被存储在一起。将不同列的值存储在不同的文件或文件段中可以实现高效的按列查询,因为它们可以一次性读出,而不是先读取整行并丢弃不需要的列表。面向列的存储非常适合计算聚合的分析工作负载,例如查找趋势、计算平均值等。如果一个逻辑记录有多个字段,但其中一些字段(在本例中为股票价格)具有不同的重要性并且字段存储的数据经常一起使用,那么我们通常使用复杂的聚合来处理这种情况。从逻辑上讲,代表股市价格的数据仍然可以用表格的形式来表达:|编号|符号|日期|价格||1|陶氏|2018年8月8日|24,314.65||2|陶氏|2018年8月9日||3|标准普尔|2018年8月8日|2,414.45||4|标准普尔|2018年8月9日|2,232.32|另一方面,列式存储看起来与上面的存储布局大不相同——属于同一列的值被紧密地存储在一起:符号:1:DOW;2:道琼斯指数;3:标准普尔;4:S&PDate:1:08Aug2018;2018年8月2日;2018年8月3日;2018-08-09价格:1:24,314.65;2,414.45;4:2,232.32为了重建数据元组(这对连接、过滤器和多行聚合很有用),我们需要在列级别保留一些元数据,以识别它与其他列中的哪些数据点相关联.如果你明确地这样做,你将需要每个值来保存一个键,这将导致数据重复并增加存储的数据量。为此,一些列存储使用隐式标识符(虚拟ID)并使用值的位置(换句话说,它的偏移量)将其映射回相关值。在过去的几年里,可能是由于越来越需要在不断增长的数据集上运行复杂的分析查询,我们看到了许多新的面向列的文件格式,例如ApacheParquet、ApacheORC、RCFile和面向列的存储,例如如ApacheKudu、ClickHouse和许多其他列式数据存储组件。03区别与优化仅仅认为行存和列存的区别只是数据的存储方式是不够的。选择数据布局只是列式存储一系列可能优化中的一个步骤。在一次读取中从同一列读取多个值可以显着提高缓存利用率和计算效率。在现代CPU上,矢量化指令使单个CPU指令能够一次处理多个数据点。此外,将相同数据类型的值存储在一起(例如,数字与数字和字符串与字符串)可以提高压缩率。我们可以根据不同的数据类型使用不同的压缩算法,针对每种情况选择最高效的压缩方式。要决定是使用面向列还是面向行的存储,您需要了解访问模式。如果需要读取记录中的大部分或所有列,并且工作负载主要由单个记录查询和范围扫描组成,则面向行的存储布局可能会产生更好的结果。如果扫描跨越多行,或者对列的子集执行计算聚合,则值得考虑面向列的存储布局。04WideColumnarStorage面向列的数据库不应与BigTable或HBase等宽列存储混淆。在这些数据库中,数据被表示为多维映射,列被分组到列族中(通常存储相同类型的数据),并且在每个列族中,数据逐行存储。此布局最适合存储通过一个键或一组键检索到的数据。BigTable论文中的一个典型示例是WebTable。WebTable存储了一个带有一定时间戳的快照,包括以下信息:网页内容、属性以及它们之间的关系。页面由反向URL标识,所有属性(例如页面内容和锚点)表示页面之间的链接,由生成这些快照的时间戳标识。简而言之,它可以表示为一个嵌套的映射,如图1-3所示。▲图1-3:WebTable的概念结构数据存储在多维排序图上,层次索引:我们可以通过特定网页的反向URL定位到与特定网页相关的数据,也可以通过时间戳内容或锚定位网页。每行都由其行键索引。相关的列被组合在一个列族中(在本例中为内容和锚点),这些列族分别存储在磁盘上。列族中的每一列都由列键标识,列键是列族名称和限定符的组合(在本例中为html、cnnsi.com、my.look.ca)。列族可以通过时间戳存储多个版本的数据。这种布局使我们能够快速定位更高级别的项目(在本例中为网页)及其参数(不同版本的内容和指向其他页面的链接)。虽然了解宽列商店的概念表示很有用,但它们的物理布局也不同。列族的数据布局示意图如图1-4所示:列族是单独存储的,但是在每个列族中,属于同一个key的数据是存储在一起的。