漫谈OceanBase 列式存储
列式存储主要的目的有两个:
- 大部分OLAP查询只需要读取部分列而不是全部列数据,列式存储可以避免读取无用数据;
- 将同一列的数据在物理上存放在一起,能够极大地提高数据压缩率。
OLAP和OLTP
OLAP,也叫联机分析处理(Online Analytical Processing)系统,有的时候也叫DSS决策支持系统,就是我们说的数据仓库。在这样的系统中,语句的执行量不是考核标准,因为一条语句的执行时间可能会非常长,读取的数据也非常多。所以,在这样的系统中,考核的标准往往是磁盘子系统的吞吐量(带宽),如能达到多少MB/s的流量。
在OLAP系统中,常使用分区技术、并行技术。
分区技术在OLAP系统中的重要性主要体现在数据库管理上,比如数据库加载,可以通过分区交换的方式实现,备份可以通过备份分区表空间实现,删除数据可以通过分区进行删除,至于分区在性能上的影响,它可以使得一些大表的扫描变得很快(只扫描单个分区)。另外,如果分区结合并行的话,也可以使得整个表的扫描会变得很快。总之,分区主要的功能是管理上的方便性,它并不能绝对保证查询性能的提高,有时候分区会带来性能上的提高,有时候会降低。
在OLAP系统中,不需要使用绑定(BIND)变量,因为整个系统的执行量很小,分析时间对于执行时间来说,可以忽略,而且可避免出现错误的执行计划。但是OLAP中可以大量使用位图索引,物化视图,对于大的事务,尽量寻求速度上的优化,没有必要像OLTP要求快速提交,甚至要刻意减慢执行的速度。
绑定变量真正的用途是在OLTP系统中,这个系统通常有这样的特点,用户并发数很大,用户的请求十分密集,并且这些请求的SQL 大多数是可以重复使用的。
OLTP,也叫联机事务处理(Online Transaction Processing),表示事务性非常高的系统,一般都是高可用的在线系统,以小的事务以及小的查询为主,评估其系统的时候,一般看其每秒执行的Transaction以及Execute SQL的数量。在这样的系统中,单个数据库每秒处理的Transaction往往超过几百个,或者是几千个,Select 语句的执行量每秒几千甚至几万个。典型的OLTP系统有电子商务系统、银行、证券等,如美国eBay的业务数据库,就是很典型的OLTP数据库。
列组(Column Group)
OceanBase通过列组支持行列混合存储,每个列组存储多个经常一起访问的列。
如上图所示,OceanBase SSTable首先按照列组存储,每个列组内部再按行存储。分为几种情况:
- 所有列属于同一个列组。数据在SSTable中按行存储,OLTP应用往往配置为这种方式。
- 每列对应一个列组。数据在SSTable中按列存储,这种方式在实际应用中比较少见。
- 每个列组对应一行数据的部分列。数据在SSTable中按行列混合存储,OLAP应用往往配置为这种方式。
OceanBase还允许一个列属于多个列组,通过冗余存储这些列,能够提高访问性能。例如,某表格总共包含5列,用户经常一起访问(1,3,5)或者(1,2,3,4)列。如果将(1,3,5)和(l,2,3,4)存储到两个列组中,那么,大部分访问只需要读取一个列组,避免了多个列组的合并操作。
列式存储提高了数据压缩比,然面,实践过程中我们发现,由于OceanBase最初的几个版本内存操作实现得不够精细,例如数据结构设计不合理,数据在内存中膨胀很多倍,导致大查询的性能瓶颈集中在CPU,列式存储的优势完全没有发挥出来。这就告诉我们,列式存储的前提是设计好内存数据结构,把CPU操作优化好,否则,后续的工作都是无用功。为了更好地支持OLAP应用,新版的OceanBase将重新设计列式存储引擎。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
并发技巧清单
如何尽量保证线程安全 可变状态是至关重要的。 所有并发访问都可以归结为如何协调对并发状态的访问,可变状态越少,越容易确保线程安全性。 尽量将域声明为final类型,除非需要它们是可变的。 不可变对象一定是线程安全的。 不可变对象能极大地降低并发编程的复杂性。它们更为简单且安全,可以任意共享而无须使用加锁或保护性复制等机制。 封装有助于管理复杂性。 在编写线程安全的程序时,虽然可以将所有数据都保存在全局变量,但为什么要这样做? 将数据封装在对象中,更易于维护不变性条件:将同步机制封装在对象中,更易于遵循同步策略。 用锁保护每个可变变量。 当保护同一个不变性条件中的所有变量时,要使用同一个锁。 在执行复合操作期间,要持有锁。 如果从多个线程中访问同一个可变变量时没有同步机制,那么程序会可能出问题。 不要故作聪明地推断不需要使用同步。 在设计过程中考虑线程安全,或者在文档中明确地指出塔不是线程安全的。 将同步策略文档化。 使用ThreadLocal保存状态变量 避免死锁 1.对于资源的加锁时间必须足够短,也就是必要时进行锁 2.访问资源过程中的锁需要按照一致的顺序进行获取,否则需要提升出一个...
- 下一篇
浅谈前端响应式设计(一)
现实世界有很多是以响应式的方式运作的,例如我们会在收到他人的提问,然后做出响应,给出相应的回答。在开发过程中笔者也应用了大量的响应式设计,积累了一些经验,希望能抛砖引玉。 响应式编程(Reactive Programming)和普通的编程思路的主要区别在于,响应式以推(push)的方式运作,而非响应式的编程思路以拉(pull)的方式运作。例如,事件就是一个很常见的响应式编程,我们通常会这么做: button.on('click', () => { // ... }) 而非响应式方式下,就会变成这样: while (true) { if (button.clicked) { // ... } } 显然,无论是代码的优雅度还是执行效率上,非响应式的方式都不如响应式的设计。 Event Emitter Event Emitter是大多数人都很熟悉的事件实现,它很简单也很实用,我们可以利用Event Emitter实现简单的响应式设计,例如下面这个异步搜索: class Input extends Component { state = { value: '' } onChange = ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker使用Oracle官方镜像安装(12C,18C,19C)