Oracle关于内存列存有2篇文章,本文是第一篇。
Abstract
Oracle IMC是第一个商用的dual-format数据库。行存适用于点查点写的OLTP,而列存适用于对部分列的OLAP分析。没有任何一种存储格式能同时适用于所有的查询场景。
IMC是纯内存的列存,支持仅对需要分析的某个表的某个列进行加载。内存列存可以应用一些列的AP技术:压缩,向量化,内存索引。基于极快的内存扫描速度还可以进行Vector Group By等优化。
OLTP的DML操作需要对相关索引进行更新,用户为了加速OLAP的查询而建了大量的索引。而通过Oracle IMC可以去掉这部分索引,不仅能加速OLAP也提升了OLTP的DML性能。
由于Oracle IMC是在scan层,因此Oracle上层的大量语法/函数,高可用等特性都100%兼容。
IMC能够与RAC和Exadata有机结合,使得IMC能够ScaleOut。
1. INTRODUCTION
随着内存越来越大可以预见基于内存的Database也会成逐渐为主流,Oracle IMC有如下特性:
Dual format
列存:对少数列,大范围行操作,适用于OLAP,如:MonetDB,C-Store;
行存:对全部列,小范围行操作,适用于OLTP,包括内存事务型数据库,如:TimesTen,H-store;
Oracle IMC支持同时行存和列存:
- 数据的DML以行存的方式进行,确保OLTP的负载;
- 在内存中实时的转成列存,用于OLAP的分析负载;
内存列存并不要求内存翻倍:
- Oracle的Buffer Cache的高命中率,并不需要配置太多Buffer Cache;
- 另外,IMC能替代大部分索引的角色,Buffer Cache的需求量进一步减少;
- 建议80%的内存用于IMC;
Unlimited Capacity
并不需要把整个DB中的所有表都加载到内存中,只需要对热点的表或者分区加载到内存。其他表可使用类似Exadata的分层存储:高容量磁盘,高IO吞吐的PCI Flash ache,低延迟的DRAM。
Complete Transparency
IMC是在access层,对上层执行器层和优化器完全兼容,唯一需要考虑的是多了一个scan方法和代价上的不同。
2. NEW IN-MEMORY COLUMNAR FORMAT
Oracle 12.1.0.2发布的IMC,IMC所占用的内存是在SGA中分配,和Buffer Cache类似。
Populating the In-Memory Column Store
populate:从持久化存储的行存加载到内存中的列存IMC。
新增关键字INMEMORY,可以作用于4类对象:
- Tablespace
- Table
- Partition of a Table
- Sub-Partition within a Partition
populate过程是通过一组进程来并发的完成,进程数目可以配置:inmemory_max_populate_servers
不像其他内存数据库,IMC在加载的时候仍然能够通过buffercache来提供服务。
对于重要的对象可以优先加载,因此给不同的对象允许赋予不同的加载优先级
In-Memory Compression
前面提到过在SGA中给IMC分配一片内存:
IMCU:一批行数据(100w);
CU:IMCU中的每个列的内存区域,使用用户指定的压缩算法进行压缩;
3种主要的压缩算法使用不同的场景:
- FOR DML:最低级别的压缩,适用于有频繁DML的场景;
- FOR QUERY:大量高频次的查询,2到10倍压缩比,该压缩无需解压缩,无需额外内存;
- FOR CAPACITY:对容量敏感的应用,5到30倍压缩比,Oracle自研了OZIP压缩算法能结合自家硬件协处理器进行解压缩;
3. QUERY PROCESSING
In-Memory Scans
针对对IMC如下优化技术:
- 向量化:SIMD,提高CPU指令密度;
- bit-packey:列的bit位图更加紧凑,cache line能装更多的内容;
- IM索引(范围):每个CU都有min/max等统计;
- 字典索引,每个IMCU统计每列的distinct;
In-Memory Joins
扫小表,建立紧凑的bloom;
扫大表时减少数据量
In-Memory Aggregations and Groupings
Select Stores.id, Products.id, sum(Sales.revenue) From Sales, Stores, Products Where Sales.store_id = Stores.id And Sales.product_id = Products.id And Stores.type = “Outlet” And Products.type = “Footwear” Group by Stores.id, Products.id;
- 扫描STORES和PRODUCTS;
- KeyVector:每个列在内存构造Key Vector,把GroupBy中的key映射到连续的id;
- In-Memory Accumulator:内存中构造NxM的矩阵;
- 扫描SALES表,每行如果能在KyeVector中匹配上,则把相应的Sales.revenue加到矩阵中;
- 最终矩阵就是Agg的结果;
4. TRANSACTIONAL CONSISTENCY
Oracle默认的隔离级别是Consistent Read,每个事务都有一个单调递增的时间戳,也就是SCN。
IMC通过SCN支持Consistent Read的隔离级别:
- 在IMCU创建时对应一个SCN(populate时拿一个read SCN);
- 每个IMCU中有一块SMU:Snapshot Metadata Unit用来跟踪在read SCN之后对IMCU的更改;
- SMU transaction journal:每个事务如果涉及到IMCU,则变更会也要记录到SMU中的transaction journal中;
- 扫描IMCU时,除了要扫描IMCU全量数据,也要扫描SMU transaction journal,读取小于read SCN事务的更改,进行merge;
- 当变更超过了阈值,则触发repopulate;
5. IN-MEMORY COLUMN STORE SCALE-OUT
通过CacheFusion协议Oracle支持RAC架构可以扩展多个计算节点,每个计算节点可以存储部分IMC数据,整体上IMC的容量可以线性扩展。再通过Oracle的Parallel Execution来分布式并行查询。
Distributionand ParallelExecution
用户可以通过DISTRIBUTE子句来指定表在不同节点上的分布方式
- DISTRIBUTE BY PARTITION:对于分区表,可以按照子分区来分布,可以支持in-memory partition-wise join;
- DISTRIBUTE BY SUBPARTITION:一级分区可能存在skew问题,此时可以使用二级分区;
- DISTRIBUTE BY ROWID RANGE:按照ROWID RANGE来分布;
- DISTRIBUTE AUTO:根据统计数据自动选择上述3种;
In-Memory Fault Tolerance
对于Exadata,可以通过DUPLICATE子句指定IMCU的副本,做到IMC的高可用
- 节点间infiniband高速网络,对于SMU的更新可以直接RDMA;
- 强同步,每个副本都时刻可服务,独立维护和Populate;
- 小表可以指定ALL;
6. CONCLUSIONS AND FUTURE WORK
Oracle IMC在data access层实现了基于内存的dual-format引擎,因此:
- 兼容Oracle丰富的功能;
- 极致的OLAP性能;
- 支持Consistent Read隔离级别;
未来的一个方向是IMC和Automatic Data Optimization的结合,自动做分层管理;另外,大量数据结构原来是基于磁盘来设计的,现在搬到了内存中,可以进行深入的调优。
IMC涉及到大量的数据库子系统,本文仅涉及其中非常小的部分:Data,Space,Transaction,Optimizer,Parallel Execution,RAC,OLAP,Virtual OS,SPARC。