大多数数据库系统存储一组数据记录,这些记录由中的组成。字段是列和行的交集:某种类型的单个值。

属于同一列的字段通常具有相同的数据类型。例如,如果我们定义了一个包含用户数据的表,那么所有的用户名都将是相同的类型,并且属于同一列。在逻辑上属于同一数据记录(通常由键标识)的值的集合构成一行。

对数据库进行分类的方法之一是按数据在磁盘上的存储方式进行分类:按行或按列进行分类。表可以水平分区(将属于同一行的值存储在一起),也可以垂直分区(将属于同一列的值存储在一起)。图1-2描述了这种区别:a)显示了按列分区的值,b)显示了按行分区的值。

▲图1-2:面向列和行的存储中的数据布局

面向行的数据库的例子很多:MySQL、PostgreSQL大多数传统的关系数据库。而两个开源的、面向列数据存储的先驱则是MonetDBC-Store(C-Store是Vertica的开源前身)。

01 面向行的数据布局

面向行的数据库按记录或来存储数据。它的布局非常接近表格的数据表示方法,即其中每一行都具有相同的字段集合。例如,面向行的数据库可以有效地存储用户条目,其中包含姓名、出生日期和电话号码:

| ID | Name | Birth Date | Phone Number || 10 | John | 01 Aug 1981 | +1 111 222 333 || 20 | Sam | 14 Sep 1988 | +1 555 888 999 || 30 | Keith | 07 Jan 1984 | +1 333 444 555 |

这种方法适用于如下的场景:数据记录(姓名、出生日期和电话号码)由多个字段组成且由某个键(在本例中为单调递增的ID)所唯一标识。表示单个用户的数据记录的所有字段通常被一起读取。在创建数据时(例如,当用户填写注册表单时),我们也将它们一起写入数据库。与此同时,我们可以单独修改某个字段。

在需要按行访问数据的情况下,面向行的存储最有用,将整行存储在一起可以提高空间局部性。

因为诸如磁盘之类的持久性介质上的数据通常是按块访问的(换句话说,磁盘访问的最小单位是块),所以单个块可能将包含某行中所有列的数据。

这对于我们希望访问整个用户记录的情况非常有用,但这样的存储布局会使访问多个用户记录某个字段的查询(例如,只获取电话号码的查询)开销更大,因为其他字段的数据在这个过程中也会被读入。

02 面向列的数据布局

面向列的数据库垂直地将数据进行分区(即通过列进行分区),而不是将其按行存储。在这种数据存储布局中,同一列的值被连续地存储在磁盘上(而不是像前面的示例那样将行连续地存储)。

例如,如果我们要存储股票市场的历史价格,那么股票价格这一列的数据便会被存储在一起。将不同列的值存储在不同的文件或文件段中,可以按列进行有效的查询,因为它们可以一次性地被读取出来,而不是先对整行进行读取后再丢弃掉不需要的列。

面向列的存储非常适合计算聚合的分析型工作负载,例如查找趋势、计算平均值等。如果逻辑记录具有多个字段,但是其中某些字段(在本例中为股票价格)具有不同的重要性并且该字段所存储的数据经常被一起使用,那么我们一般使用复杂聚合来处理这样的情况。

从逻辑角度看,表示股票市场价格的数据仍旧可以表示为表的形式:

| ID | Symbol | Date | Price || 1 | DOW | 08 Aug 2018 | 24,314.65 || 2 | DOW | 09 Aug 2018 | 24,136.16 || 3 | S&P | 08 Aug 2018 | 2,414.45 || 4 | S&P | 09 Aug 2018 | 2,232.32 |

而列式存储则看起来与上述存储布局完全不同—属于同一列的值被紧密地存储在一起:

Symbol: 1:DOW; 2:DOW; 3:S&P; 4:S&PDate: 1:08 Aug 2018; 2:09 Aug 2018; 3:08 Aug 2018; 4:09 Aug 2018Price: 1:24,314.65; 2:24,136.16; 3:2,414.45; 4:2,232.32

为了重建数据元组(这对于连接、筛选和多行聚合可能很有用),我们需要在列级别上保留一些元数据,以标识与它关联的其他列中的数据点是哪些。如果你显式地执行此操作,则需要每个值都必须持有一个键,这将导致数据重复并增加存储的数据量。

针对这种需求,一些列存储使用隐式标识符(虚拟ID),并使用该值的位置(换句话说,其偏移量)将其映射回相关值。

在过去几年中,可能由于对不断增长的数据集运行复杂分析查询的需求不断增长,我们看到了许多新的面向列的文件格式,如Apache Parquet、Apache ORC、RCFile,以及面向列的存储,如Apache Kudu、ClickHouse,以及许多其他列式数据存储组件。

03 区别与优化

认为行存储和列存储之间的区别仅在于数据的存储方式有所不同,这是不充分的。选择数据布局只是列式存储所针对的一系列可能的优化的步骤之一。

在一次读取中,从同一列中读取多个值可以显著提高缓存利用率和计算效率。在现代CPU上,向量化指令可以使单条CPU指令一次处理多个数据点。

另外,将具有相同数据类型的值存储在一起(例如,数字与数字在一起,字符串与字符串在一起)可以提高压缩率。我们可以根据不同的数据类型使用不同的压缩算法,并为每种情况选择最有效的压缩方法。

要决定是使用面向列还是面向行的存储,你需要了解访问模式。如果所读取的记录中的大多数或所有列都是需要的,并且工作负载主要由单条记录查询和范围扫描组成,则面向行的存储布局可能产生更好的结果。如果扫描跨越多行,或者在列的子集上进行计算聚合,则值得考虑使用面向列的存储布局。

04 宽列式存储

面向列的数据库不应与宽列式存储(如BigTable或HBase)相混淆。在这些数据库中,数据表示为多维映射,列被分组为列族(通常存储相同类型的数据),并且在每个列族中,数据被逐行存储。此布局最适合存储由一个键或一组键来检索的数据。

BigTable论文中的一个典型示例是WebTable。一个WebTable存储着一个带有某个时间戳、包含如下信息的快照:网页内容、属性以及它们之间的关系。

页面由反向URL所标识,并且所有属性(如页面内容和锚,锚表示页面之间的链接)由生成这些快照的时间戳来标识。简而言之,它可以表示为一个嵌套的映射,如图1-3所示。

▲图1-3:WebTable的概念性结构

数据存储在具有层次索引的多维排序映射中:我们可以通过特定网页的反向URL来定位与该网页相关的数据,也可以通过时间戳来定位该网页的内容或锚。每一行都按其行键进行索引。

在列族中,相关列被分组在一起(在本例中为contents和anchor),这些列族分别存储在磁盘上。列族中的每个列都由列键标识,该键是列族名称和限定符(在本例中为html,http://cnnsi.com,http://my.look.ca)的组合。

列族可以按照时间戳存储多个版本的数据。这种布局使得我们可以快速定位更高层的条目(在本例中为Web页面)及其参数(不同版本的内容和指向其他页面的链接)。

理解宽列式存储的概念表示是有用的,而它们的物理布局也有所不同。列族的数据布局示意图如图1-4所示:列族被单独存储,但在每个列族中,属于同一键的数据被存储在一起。

▲图1-4:WebTable的物理结构

[声明]本文版权归原作者所有,内容为作者个人观点,转载目的在于传递更多信息,如涉及作品内容、版权等问题,可联系本站删除,谢谢。

修改所有列_哪些数据库是行存储?哪些是列存储?有什么区别?相关推荐

  1. 三线表是什么?R语言使用table1包绘制(生成)三线表、使用单变量分列构建三线表、通过topclass参数自定义三线表表格的显示形式(显示为类似斑马线、并将所有列居中,包括包含行标签的第一列)

    三线表是什么?R语言使用table1包绘制(生成)三线表.使用单变量分列构建三线表.通过topclass参数自定义三线表表格的显示形式(显示为类似斑马线.并将所有列居中,包括包含行标签的第一列) 目录

  2. python提取文件指定列_如何从csv文件中提取特定列并使用python绘图

    我有一个csv文件,其中包含以下几行数据:# Vertex X Y Z K_I K_II K_III J 0 2.100000e+00 2.000000e+00 -1.000000e-04 0.000 ...

  3. mysql 指定位置添加列_给MySQL表增加指定位置的列_MySQL

    ALTER TABLE test ADD COLUMN id INT UNSIGNED NOT NULL auto_increment PRIMARY KEY FIRST 给表添加列是一个常用的操作, ...

  4. 增大mysql修改表空间_扩充数据库表空间

    ALTER TABLESPACE ADD DATAFILE , [REUSE] NEXT MAXSIZE <>中是你要填的内容,有|是选其一. 如:增加文件是d:\dbfs\mydatab ...

  5. sql 行转列_想要表格行转列?简单几行Python代码搞定

    前言数据的行转列操作,在实际工作过程中应用非常广泛.由于不同人员.不同部门对数据结构的认识是不大相同的,尤其是从基层人员手里拿到的数据,更是五花八门,横七竖八.比如有这样一张成绩表: 乍一看,好像没毛 ...

  6. sql将一列拆分为多列_【Excel实用技巧】把一列数据拆分为多列的三个菜鸟招数,你还有更菜的方法吗?...

    点上方关注Excel基础学习园地 公众号"Excel基础学习园地"是一个免费发布Excel基础知识.函数应用.操作技巧.学习方法等资讯的公众号,为了确保您能及时收到每天的教程,还请 ...

  7. vue树形多列_[vue]使用Element-ui的el-table实现多列同时排序。

    freddon 发表于2019-09-09 阅读 2673 | 评论 0 最近遇到默认排序只会保留当前排序,所以根据文档实现多列排序 直接切入正题. 多列排序主要用到el-table的`header- ...

  8. python 写入csv文件固定列_将元组列表写入csv文件保持列一致

    我用beauthulsoup抓取一个网站,页面的一半有常规数据,X#个字段每个字段有一个值,下半部分有Y#个字段,每个字段都有可变数量的值(很多时候只有一个值,其他的是任意数量的值).在 困扰我的是如 ...

  9. python dataframe索引转成列_如何将 Pandas DataFrame 的索引转换为列

    我们将介绍将 Pandas DataFrame 的索引转换为列的各种方法,例如 df.index,带有 rename_axis 的 reset_index 来重命名索引,以及 set_index. 我 ...

最新文章

  1. antd 中 Tree 的使用-默认选中问题
  2. 遍历list、set、map和array
  3. 增强画面纵深感的几个小技巧
  4. Python--第2次平时作业
  5. linux安装下载中文包,linux下安装中文包和字体
  6. Struts 2读书笔记-----使用Struts 2的输入校验
  7. Chrome TTFB中英文解释
  8. 机器学习公开课笔记(8):k-means聚类和PCA降维
  9. 从客户端(Content=p666/p)中检测到有潜在危险的 Request.Form 值。
  10. 连接ftp服务器响应时间长,事务响应时间
  11. 常用的JS与XML结合用法 简单示例
  12. 放弃 vs2005 的 crystal report 。推荐使用国内强人开发的第三方报表开发工具:袁氏报表 。...
  13. 女生学计算机和遥感哪个好就业,遥感科学与技术有性别歧视吗知乎
  14. 微信小程序毕业设计 基于微信小程序评选投票系统开题报告
  15. 数据库时间相减_SQL 日期相减(间隔)datediff函数,
  16. python seek_Python 文件 seek() 方法
  17. python的浅拷贝和深copy
  18. TMS320F280049C 学习笔记15 DAC
  19. Sql Server服务远程过程调用失败。[0x800706be]
  20. WEB——07JDBC

热门文章

  1. Ruby file操作cheatsheet
  2. 机器翻译软件从实验室走向市场
  3. 腾讯的强大不是偶然,小马哥很强大
  4. python中数字和字符串可以直接相加_用c语言或者python将文件中特定字符串后面的数字相加...
  5. gdiplus判断一个点是否在圆弧线上_福建教师招聘考试小学数学面试教案:圆的认识...
  6. Sqlserver备份存储过程
  7. 世上最简单的mysql_史上最简单安装MySQL教程
  8. html输入支付密码样式,基于JS实现类似支付宝支付密码输入框
  9. linux 恢复操作系统,如何恢复Linux操作系统的GRUB引导程?
  10. haarcascades---各种分类器xml文件下载地址