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

本文涉及的产品
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介:


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


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


对内存计算意义不大


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


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


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


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


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


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


索引效率低


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


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


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


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


分段并行麻烦


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


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


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


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


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


结语


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


专栏作者简介

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

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


数据蒋堂

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



原文发布时间为:2017-05-27 

本文作者:蒋步星

本文来自云栖社区合作伙伴“数据派THU”,了解相关信息可以关注“数据派THU”微信公众号

相关实践学习
基于MaxCompute的热门话题分析
Apsara Clouder大数据专项技能认证配套课程:基于MaxCompute的热门话题分析
相关文章
|
2月前
|
数据采集 数据可视化 JavaScript
用 通义灵码和 PyQt5 爬虫智能体轻松爬取掘金,自动化采集技术文章和数据
本文介绍了如何利用智能开发工具通义灵码和Python的PyQt5框架,构建一个自动化爬取掘金网站技术文章和数据的智能爬虫系统。通过通义灵码提高代码编写效率,使用PyQt5创建可视化界面,实现对爬虫任务的动态控制与管理。同时,还讲解了应对反爬机制、动态内容加载及数据清洗等关键技术点,帮助开发者高效获取并处理网络信息。
|
3月前
|
机器学习/深度学习 自然语言处理 前端开发
国内快递地址解析技术的工作原理详解
随着电商和快递行业快速发展,非结构化地址问题日益突出,如字段混杂、拼写错误等,传统方式难以高效处理。为此,探数平台推出基于NLP和地理信息的快递地址解析API,可将原始地址文本解析为标准结构化字段(如省、市、区、街道等),并支持收件人姓名与电话提取。 技术上,该API采用深度学习模型(如BERT、BiLSTM)进行语义理解,结合地址知识图谱实现纠错与补全。服务支持SaaS调用或私有化部署,性能稳定,适用于各类前端场景。通过地址结构化处理,企业可显著提升订单处理效率,减少配送错误,优化用户体验,助力全链路智能化升级。无论是电商平台还是物流系统,均可从中受益。
284 0
|
监控 安全 中间件
Python Django 后端架构开发: 中间件架构设计
Python Django 后端架构开发: 中间件架构设计
232 1
|
JavaScript 前端开发
JS二进制转10进制、十六进制
JS二进制转10进制、十六进制 【8月更文挑战第9天】
384 6
|
决策智能 Windows
运筹优化学习01:Lingo入门与错误列表分析(二)
运筹优化学习01:Lingo入门与错误列表分析
运筹优化学习01:Lingo入门与错误列表分析(二)
|
存储 算法 数据库
一次难得的分库分表实践(上)
一次难得的分库分表实践
|
自然语言处理 算法
NLP系列(三)LDA主题模型
LDA模型是NLP中很基础也是大家广为熟知的模型,在面试过程也经常遇到。本文简单讲述下其大致流程。
810 0
NLP系列(三)LDA主题模型

热门文章

最新文章