前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据蒋堂】列式存储的另一面

【数据蒋堂】列式存储的另一面

作者头像
数据派THU
发布2018-01-29 14:58:42
9400
发布2018-01-29 14:58:42
举报
文章被收录于专栏:数据派THU数据派THU

来源:数据蒋堂

作者:蒋步星

本文长度为2400字,建议阅读3分钟

本文针对只读的分析计算任务探讨列存的缺点。

列存是常见的数据存储技术,在许多场景下也确实很有效,因而也被不少数据仓库类产品采用,在业内列存也常常就意味着高性能。

可是,列存真有这么好吗?搜索一下,容易找到的列存缺点一般是针对数据修改的,而对于只读的分析计算任务,却很少能见到较详细的讨论。我们在这里来研究一下这个问题。

对内存计算意义不大

列存的原理很简单:由于磁盘不适合跳动式读取,采用行式存储时在读取数据时会扫描所有列,而一次运算可能只涉及很少的列,这样就会多读很多用不上的数据。采用列存则只需要读取需要用到的列,数据访问量会大幅减少,而大数据计算中磁盘扫描时间的占比很大,减少访问量就能节约大量时间。另外,如果同一列中有很多相同的数据,采用列存更容易做合并压缩,从而进一步减少数据存储量,提高性能。

从原理可以看出,列存能提高性能主要是因为减少了磁盘访问量,但对于计算量减少并没有帮助。如果数据已经被加载进内存,再采用列存就没多大意义了。普通结构化数据运算都是以行为单位的,在内存中使用列存反而会加大构造完整记录的复杂度,降低性能。所以,除了专业的向量式运算(数据挖掘中常用,运算本身就是以列为单位的)外,类似关系型数据库的内存运算(包括内存数据库)并不适合采用列式存储。

加剧硬盘的不连续访问程度

列式存储时,各列是连续存储的,这样同时访问多个列进行计算时,就会造成不连续的随机访问,访问的列越多造成的不连续性就越强。而针对机械硬盘的不连续读取会严重影响性能,在访问列数较多或总列数并不多时,就有可能发生列行性能不如行存的现象,因为列行跳动的成本可能会超过行存连续访问的成本。如果有并发任务(以及下面会说到的并行计算)还会严重加剧这一问题,当然行存并发时也会发生磁盘跳动,但程度比列存轻得多,列存是每多一个并发计算任务会多出几个(涉及列数)对磁盘的并发访问请求,行存则只会多一个磁盘并发请求。

一个办法是加大读取缓存区以减少磁盘寻道时间的占比,但这样为每个涉及列都设置缓存区,列较多时会占用大量内存。另一个办法是增加磁盘数量,把不同的列存储到不同的磁盘上,不过列存一般应用场景都是总数列很多的情况,常常远大于机器可以接受的硬盘数量,还会较大概率地造成磁盘随机访问冲突。

固态硬盘没有寻道时间的问题,列式存储更适合采用固态硬盘。

索引效率低

索引也是常用技术,用于从大数据集中按键值找出指定记录。我们在以前文章中讲过,索引的本质是排序,索引表中将存储有序的键值及该键值对应的原表记录位置。对于行式存储来说,整条记录的位置可以用一个数表示;但列存就不一样了,整条记录的每个列分别有各自的位置,原则上需要都记录下来,这样一来,索引表几乎和原表一样大,访问成本变高很多,空间占用也太大,这和复制原表后排序区别并不大了。

每条记录只存储一个序号,然后用乘法计算出位置,这样可以吗?有些数据类型的字段值的长度本身就是不固定的(串型),而固定长度的字段值(整数、日期)也可能因为要压缩编码(列存中常用的技术)而变成不固定的,如果一定要用定长方式存储,索引倒是简单了,访问也很快,但会加大存储量,遍历时又不划算了,而这是列存更主要的应用场景。

实际常用的手段是把数据分块,块内数据采用列存,索引只建立在块上。这样可以用索引迅速定位所需要的数据在哪个块中,然后只要在块内进行扫描即可。

这种索引比行存索引会多一个块内扫描的过程,性能要低一些。如果原数据按索引键值有序(索引键常常就是原表主键),那可以很容易地定位出目标数据所在的少量的几个块(大概率只在一块中),这时性能损失还可以容忍,可适用于按唯一ID值找出指定记录的场景。但如果原数据对索引键无序,那这个索引几乎没有用处,目标数据可能落在几乎所有的块中,这就和全表扫描区别不大了。

分段并行麻烦

要充分利用多CPU(核),多线程并行能力是个必须考虑的问题,而要并行这就需要先把数据分段。

分段有两个基本需求:每段数据量基本相同(每线程处理能力相当),可以较灵活的分段(事先不能预测线程数)。行式存储时相对容易实现分段,只要每条(也可以每N条)记录后做一个结束标记,在分段时按字节数平均分成K段,然后在每段中寻找到结束标记后作为开始点即可。但列式存储不能采用同样的办法,由于前述原因,字段值是不定长的,某个列的分段点未必和另一个列的同样的分段点同步落在同一条记录上,这会错位导致错误的数据。

列式存储的分段一般也是采用前述的分块方案:分段必须以块为单位,在块内不再分段并行。这样就会有一个矛盾,首先,分块数不能太少了,否则就无法做到灵活分段了(只有5个分块时不可能做出10个分段),按现代服务器的CPU(核)数,要有上百个分块才能比较自由地平衡分段;但是,分块数又不能太多,列数据在物理上会被拆成多个不连续的小块,不仅使得遍历代码复杂很多,而且还会多读入少量两块之间的无用数据,对于机械硬盘还有寻道时间问题,分块数越多这些问题就越严重。

只有分块内列数据占用空间比读入缓冲区大很多时,无用数据读入时间和寻道时间的占比才会比较小,这就要求每个分块中有足够多的记录数,也就是说,实现列存并行,数据量要足够大才有意义,对于机械硬盘(包括用机械硬盘构成的阵列)上一般得达到单机单表十亿记录、空间约在百G以上。规模较小的数据量就不容易获得并行计算的性能提升,而特别适合使用列存的多维分析业务的数据量就处于这种尴尬的规模中。

另外,分块容量在数据追加前就要确定下来,随着数据的不断追加,相邻分块却不能物理上合并,分块数就会越来越多,这将给管理造成不少麻烦,需要可扩展的空间专门存储分块的索引信息。

结语

我们在这里介绍列存的另一面,并非要否定列存在许多计算场景时的巨大优势 ,但完全不区分情况地全面采用列存也是不负责任的。对于数据仓库类产品,正确的做法应当将这个自由度留给系统管理员,由用户来决定是否采用列存、如何分块、哪些数据采用列存、有些数据甚至会行存和列存共存,以冗余换取更高的性能。

专栏作者简介

蒋步星,润乾软件创始人、首席科学家

清华大学计算机硕士,著有《非线性报表模型原理》等,1989年,中国首个国际奥林匹克数学竞赛团体冠军成员,个人金牌;2000年,创立润乾公司;2004年,首次在润乾报表中提出非线性报表模型,完美解决了中国式复杂报表制表难题,目前该模型已经成为报表行业的标准;2014年,经过7年开发,润乾软件发布不依赖关系代数模型的计算引擎——集算器,有效地提高了复杂结构化大数据计算的开发和运算效率;2015年,润乾软件被福布斯中文网站评为“2015福布斯中国非上市潜力企业100强”;2016年,荣获中国电子信息产业发展研究院评选的“2016年中国软件和信息服务业十大领军人物”;2017年, 自主创新研发新一代的数据仓库、云数据库等产品即将面世。

数据蒋堂

《数据蒋堂》的作者蒋步星,从事信息系统建设和数据处理长达20多年的时间。他丰富的工程经验与深厚的理论功底相互融合、创新思想与传统观念的相互碰撞,虚拟与现实的相互交织,产生出了一篇篇的沥血之作。此连载的内容涉及从数据呈现、采集到加工计算再到存储以及挖掘等各个方面。大可观数据世界之远景、小可看技术疑难之细节。针对数据领域一些技术难点,站在研发人员的角度从浅入深,进行全方位、360度无死角深度剖析;对于一些业内观点,站在技术人员角度阐述自己的思考和理解。蒋步星还会对大数据的发展,站在业内专家角度给予预测和推断。静下心来认真研读你会发现,《数据蒋堂》的文章,有的会让用户避免重复前人走过的弯路,有的会让攻城狮面对扎心的难题茅塞顿开,有的会为初入行业的读者提供一把开启数据世界的钥匙,有的甚至会让业内专家大跌眼镜,产生思想交锋。

往期回顾:

【数据蒋堂】我们需要怎样的OLAP

【数据蒋堂】1T数据到底有多大

【数据蒋堂】索引的本质是排序

【数据蒋堂】功夫都在报表外--漫谈报表性能优化

【数据蒋堂】非结构化数据分析是忽悠?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据派THU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档