为什么 OLAP 需要列式存储
为什么这么设计(Why’s THE Design)是一系列关于计算机领域中程序设计决策的文章,我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题,可以在文章下面留言。
ClickHouse 是最近比较热门的用于在线分析处理的(OLAP)[^1]数据存储,与我们常见的 MySQL、PostgreSQL 等传统的关系型数据库相比,ClickHouse、Hive 和 HBase 等用于在线分析处理(OLAP)场景的数据存储往往都会使用列式存储。
图 1 - OLAP 和 OLTP
对数据库稍有了解的读者都知道,在线事务处理(Online Transaction Processing、OLTP)[^2]和在线分析处理(Online Analytical Processing、OLAP)是数据库最常见的两种场景,这两种场景不是唯二的两种,从中衍生出来的还有混合事务分析处理(Hybrid Transactional/Analytical Processing、HTAP)[^3]等概念。
在线事务处理是最常见的场景,在线服务需要为用户实时提供服务,提供服务的过程中可能要查询或者创建一些记录;而在线分析处理的场景需要批量处理用户数据,数据分析师会根据用户产生的数据分析用户行为和画像、产出报表和模型。
标题中提到的列式存储与传统关系型数据库的行式存储相对应,如下图所示,其中行式存储以数据行或者实体为逻辑单元管理数据,数据行的存储都是连续的,而列式存储以数据列为逻辑单元管理数据,相邻的数据都是具有相同类型的数据。
既然我们已经了解了标题中提到的两个概念:OLAP 和列式存储,那么接下来将从以下两个方面分析为什么列式存储更适合 OLAP 的场景。
列式存储可以满足快速读取特定列的需求,在线分析处理往往需要在上百列的宽表中读取指定列分析;
列式存储就近存储同一列的数据,使用压缩算法可以得到更高的压缩率,减少存储占用的磁盘空间;
按需读取
在线服务需要应对用户发起的增删改查需求,虽然查询的需求往往都是写入请求的几倍、甚至几十倍,但是写操作带来的负责一致性问题成为了在线服务数据存储不得不解决的问题,MySQL 和 PostgreSQL 等使用关系型数据库提供的事务可以提供很好的方案。
正是因为 OLTP 场景中大多数的操作都是以记录作为单位的,所以将经常被同时使用的数据相邻存储也是很符合逻辑的,但是如果我们将 MySQL 等数据库用于 OLAP 场景,最常见的查询也可能需要遍历整张表中的全部数据。
如上图所示,当我们仅需要获取上表中年龄的分布时,也仍然需要读取表中的全部数据并在内存中丢弃不需要的数据行,其中黄色部分都是我们不关心的数据,这浪费了大量的 I/O 和内存资源。虽然我们可以使用辅助索引解决这些问题,但是对于 OLAP 中常见的几十列甚至上百列的宽表就捉襟见肘了。
列式存储会按列存储数据,这也意味着在读取数据表中的特定列时,我们只需要找到相应内存空间的起始位置,然后读取这片连续的内存空间就可以获得关心的全部数据。
哪怕在几百列的大表中找到几个特定列也不需要遍历整张表,只需要找到列的起始位置就可以快速获取相关的数据,减少了 I/O 和内存资源的浪费,这也是为什么面向列的存储系统更适合在 OLAP 的场景中使用。
数据压缩
因为列式存储将同一列的数据存储在一起,所以使用压缩算法可以得到更高的压缩率,减少存储占用的磁盘空间。压缩算法的基本原理其实很简单,它使用基于特定规则的数据表示原数据,如下所示的字符串中包含连续的相同字符,我们使用最符合直觉的压缩算法就可以减少字符串的长度:
上图中所有的黄色方块表示前面字符串的重复次数,这种简单的压缩策略可以在保证无损的情况下将字符串的长度压缩 33%,然而压缩率是由压缩算法和数据的特性共同决定的。与面向行的数据存储相比,面向列的数据存储会将相同类型的数据就近存储,这也给压缩算法的提供了更多发挥的空间。
虽然压缩算法实际上是一种使用 CPU 时间换取 I/O 时间和空间的策略,但是在多数情况下,这种生意都是稳赚不赔的。压缩算法通过减少数据的大小、减少磁盘的寻道时间提高 I/O 的性能、减少数据的传输时间并提高缓冲区的命中率,节省的 I/O 时间可以轻易补偿它带来的 CPU 额外开销[^4]。
总结
在线分析处理的场景虽然一直都存在,不过随着数字化浪潮的演进,我们也只是在最近才采集到了海量的用户数据。因为过去的系统无法满足今天海量数据的分析和处理需求,所以才出现了为细分场景设计的系统,面向列的存储系统也因为它的以下特性在 OLAP 的场景中焕发了光彩:
列式存储可以满足快速读取特定列的需求,在线分析处理往往需要在上百列的宽表中读取指定列分析,而传统的行式存储在分析数据时往往需要使用索引或者遍历整张表,带来了非常大的额外开销;
列式存储就近存储同一列的数据,使用压缩算法可以得到更高的压缩率,减少存储占用的磁盘空间,虽然带来了 CPU 时间的额外开销,但是节省的 I/O 时间比带来的额外开销更多;
列式存储在 OLAP 的场景中有着种种优势,不过它也不是数据存储中的银弹,仍然有很多缺点,不过在这里就不做讨论了。到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细思考一下下面的问题:
列式存储在 OLTP 的场景中有哪些优点?
HTAP 的场景会使用哪种方式存储数据?
推荐阅读
为什么 MySQL 使用 B+ 树
为什么数据库不应该使用外键
如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容。
图是怎么画的
技术文章配图指南
图灵新书预告
作者:[美] 马特·富勒(Matt Fuller) , [美] 曼弗雷德·莫泽(Manfred Moser) , [美] 马丁·特拉韦尔索(Martin Traverso)
译者:张晨 , 黄鹏程 , 傅宇
SQL 领域重磅力作,Presto 官方指南
Presto 创始团队、Apache Kafka 联合创作者推荐
多位国内一线技术大咖力荐
随着各行各业对大数据实时查询的需求持续增长,数据查询及分析引擎正变得不可或缺。Presto 是由 Facebook 开源的高性能分布式 SQL 查询引擎,其用户包括 Netflix、Airbnb、LinkedIn、Twitter、Uber 等知名公司。本书由 Presto 的核心开发人员参与撰写,教你系统地学习 Presto 的用法。书中内容涵盖 Presto 的安装、设计理念、查询操作、最佳实践、与主要云平台的结合等。本书分为三大部分:第一部分介绍 Presto 的基础知识;第二部分更进一步,介绍 Presto 架构、集群部署、与数据源的连接等;第三部分讲解安全配置以及 Presto 的实际用例。你可以通过本书学会针对不同的数据源快速执行交互式 SQL 数据分析,并利用 Presto 管理和使用海量数据。
为什么 OLAP 需要列式存储相关推荐
- 面向OLAP的列式存储DBMS-11-[ClickHouse]的常用字符串操作
ClickHouse 字符串的相关操作函数 1 常用函数 1.1 empty和notEmpty empty:检测一个字符串是否为空,为空返回 1,不为空返回 0. notEmpty:检测一个字符串是否 ...
- 行式和列式存储说明以及OLAP特点介绍
ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS). 在传统的行式数据库系统中,数据按如下顺序存储: Row WatchID JavaEnable Title Good ...
- 为什么列式存储会被广泛用在 OLAP 中?
大家好,我是大D. 不知是否有小伙伴们疑问,为什么列式存储会广泛地应用在 OLAP 领域,和行式存储相比,它的优势在哪里?今天我们一起来对比下这两种存储方式的差别. 其实,列式存储并不是一项新技术,最 ...
- OLAP列式存储之引擎特性
本文简要从存储结构.索引结构和数据更新方式等几个方面介绍当前比较热门的OLAT/HATP列式存储引擎,包括ClickHouse和SqlServer. ClickHouse 1.1 存储结构和索引结构 ...
- 深入解析:DB2 V10.5新特性列式存储表的优点与缺点
关注"数据和云",精彩不容错过 李培杨 云和恩墨西区交付技术顾问,有多年数据库运维经验,长期服务移动运营商行业客户,熟悉 DB2 数据库故障诊断,数据库迁移升级. >> ...
- 列式存储ClickHouse(一)概述
这里写目录标题 概述 优势特性 缺点特性 性能 安装 测试 创建表 导入数据 查询数据 ClickHouse,是一个快速,开源,OLAP的数据库管理系统.ClickHouse是列式存储的,支持实时使用 ...
- 列存储相关概念和常见列式存储数据库(Hbase、德鲁依)
Table of Contents 列式存储数据库 Examples of Column Store DBMSs Hbase Table Row Column Column Family Column ...
- 数据库—行式存储和列式存储
1. 数据库的存储模式 1.1 关系型数据库 关系型数据库RDS(Relational Database Service),大部分为行式存储数据. 行式存储: 据以行相关的存储体系架构进行空间分配,主 ...
- 数据库中的 【行式存储】和【列式存储】
传统的关系型数据库,如 Oracle.DB2.MySQL.SQL SERVER 等采用行式存储法(Row-based),在基于行式存储的数据库中, 数据是按照行数据为基础逻辑存储单元进行存储的, 一行 ...
最新文章
- ckeditor默认字体设置
- java工程师linux命令,这篇文章就够了
- linux c++线程池的实现
- Jquery操作Table
- html边框塌陷怎么,你不知道的CSS(边框塌陷)?
- String 是值类型还是引用类型
- php 多层 对象,php多层数组和对象的转换
- 办公用品管理系统VB——模块
- EmEditor中正则表达式
- vue+element+node构建单片机控制系统
- SeDebugPrivilege
- vs2015安装msdn_visual studio 2015离线版msdn下载和安装图文教程
- c语言中printf输出,C语言中printf输出的总结
- 极大似然估计和最大似然估计定义
- 神州数码交换机的数据备份
- pppoe按需连接服务器无响应,pppoe服务器无响应怎么解决_pppoe拨号失败怎么办
- 任意进制转换(2进制、8进制、16进制等)
- Qt示例解析 【Callout】
- 设置和取消Excel限制保护的两种方法
- 汉字点阵c语言程序,用c51单片机控制1616点阵显示汉字源代码
热门文章
- python 使用socks 爬虫_python爬虫基础之urllib的使用
- 头的大小是天生的吗_眼睛一单一双怎么办?可以只做一只吗?
- python神经结构二层_《python深度学习》笔记---8.3、神经风格迁移
- 挡d挡切换_新手司机请问开车可以直接从“D档”挂到“S档”吗?
- 输入20本书的书名,作者,出版社,出版日期,单价,按书名排序输出
- 团队工具_「管理工具」部门有效管理的5个工具,打造高效团队
- 哪一类功率放大电路效率最高_最简单逆变器电路讲解计算,电工电子动手学技术,电路好案例推荐...
- 架构之美(china-pub全国独家首发)
- Google发布App Engine第二代运行时,提供Python 3.7和PHP 7.2支持
- zabbix监控Tomcat