转 https://blog.csdn.net/stevensxiao/article/details/51437274html
参考文献算法
https://www.zhihu.com/question/19883454sql
https://blog.csdn.net/zhangzheng0413/article/details/8271322/数据库
Database In-Memory是Oracle数据库的选项,相似于RAC,ADG,发布于12.0.1.2。
它的主要目的是利用内存的速度和优化的列格式来加速分析。如下咱们用DBIM或IM做为Database In-Memory的缩写。后端
传统的数据库概念中,行式数据库适合于OLTP的DML操做,如Oracle, Mysql;而列式数据库适合于分析,如Sybase IQ, SAP HANA。
而在一个混合负载的环境中,就会面临两难的选择。
DBIM在Oracle传统的行式存储以外提供了内存中的列式存储,而后自动的为用户访问选择后端的行式或列式存储,从而解决了此难题。缓存
换句话说,在磁盘上只有一份数据,而在内存中则存在行式的Cache和列式的IM内存数据。
新的IM存储不会增长双倍的内存需求,首先由于咱们无需将全部的列式数据都载入内容,其次内存中列式数据能够压缩,并且因为重复值较多,压缩的比率也较高。
增长了DBIM,一般内存需求会增长20%,具体可使用In-Memory Advisor计算。oracle
虽然列式数据适合于只读的情形,但并不意味数据不可修改,数据修改后,DBIM自动维护数据的一致性,自动在后台刷新列式存储,这一切对于应用都是透明的。app
再次强调,列式数据不是Cache,所以也就没有Cache中Aging的概念。加载时须要将指定列的全部行数据加载,而不能选择某些行。性能
DBIM在内存中须要预留空间,属于SGA中的静态池分,是纯列式存储。列存储不会取代缓冲区缓存,而是做为一种补充,以便数据如今可同时以行格式和列格式存储在内存中。
经过INMEMORY_SIZE控制DBIM内存的大小,至少为100M,当其大于0时,启用DBIM功能。
做为静态池,对 INMEMORY_SIZE 参数所作的任何更改在重启数据库实例后才会生效。优化
内存中区域可分为两个池:一个 1MB 池,用于存储填充到内存中的实际列格式数据,称为In Memory Compression Units (IMCUs);一个 64K 池,用于存储填充到 IM 列存储的对象的元数据以及交易的状态, 称为 Snapshot Metadata Units (SMUs)。当数据被修改是,SCU能够记录哪些列式数据是过时的,须要修改。
填充内存中列存储又称为populate。DBIM为表和物化视图添加了一个新的 INMEMORY 属性,具备 INMEMORY 属性的对象能够加载到 IM 列存储。
能够在表空间、表、(子)分区或物化视图上指定 INMEMORY 属性。能够经过排除法的方式选择部分列和部分分区,但不能选择部分行。
ALTER TABLESPACE ts_data INMEMORY; -- 全部表空间中的表 ALTER TABLE sales INMEMORY; -- 表的全部列 ALTER TABLE sales INMEMORY NO INMEMORY(prod_id); -- 表的全部列,除去prod_id ALTER TABLE sales MODIFY PARTITION SALES_Q1_1998 NO INMEMORY; -- 表的全部分区,除去SALES_Q1_1998分区
IM 列存储经过一组称为工做进程 (ora_w001_orcl) 的后台进程进行填充。填充时,数据库可彻底访问。
而其它厂商的纯内存中数据库,须要等到全部数据都填充到内存中后,才可访问数据库,但这会引发严重的可用性问题。
填充是一种流式机制,填充的同时对数据采用列格式并进行压缩。
与磁盘上的表空间由多个区段构成同样,IM 列存储由多个内存中压缩单元 (IMCU) 构成。
每一个工做进程分配本身的IMCU,并在其中填充部分数据库块。在填充过程当中,数据不以任何特定的方式进行排序或排列。以在行格式中的显示顺序读取数据。
在数据库打开后当即以按优先级顺序将对象填充到 IM 列存储,或首次扫描(查询)对象后将其填充到 IM 列存储。对象的加载顺序经过关键字 PRIORITY 进行控制,关键字 PRIORITY 有五个级别。默认 PRIORITY 为 NONE,这表示只在首次扫描对象后才将其填充。
对于索引组织表 (IOT)和集群表,因为其特性是面向OLTP的,DBIM不支持,另外如LONG何out-of-line LOB也不支持。
目前DBIM还没法再ADG的standby实例中使用,将来会支持,这样能够利用灾备站点作分析,提高其ROI。
一般只将压缩视为节省空间的一种机制。可是,填充到 IM 列存储的数据是使用一组新压缩算法进行压缩的,这谢新压缩算法不只有助于节省空间,并且还能提升查询性能。这种新的 Oracle 内存中压缩格式容许直接对压缩的列执行查询。这意味着,将对很是少许的数据执行全部扫描和筛选操做。仅当结果集须要数据时才解压缩数据。 使用关键字 MEMCOMPRESS(INMEMORY 属性的分子句)指定内存中压缩。有六个级别,每一个级别提供不一样的压缩级别和性能。
默认状况下,使用 FOR QUERY LOW 选项压缩数据,该选项提供最佳的查询性能。这种方式的压缩对于性能影响不大的缘由是其使用的是字典压缩,其实就是重复数据删除。
能够对一个表内的各个列或各个分区使用不一样的压缩技术,例如:
CREATE TABLE employees ( c1 NUMBER, c2 NUMBER, c3 VARCHAR2(10), c4 CLOB ) INMEMORY MEMCOMPRESS FOR QUERY NO INMEMORY(c4) INMEMORY MEMCOMPRESS FOR CAPCITY HIGH(c2);
使用何种压缩可使用Oracle Compression Advisor (DBMS_COMPRESSION)来评估。
内存中扫描速度快取决于如下因素。
这时最根本的,分析只访问部分列,这样避免了大量I/O,好处相似于分区,只不过是垂直分区。
在Exadata中已经出现过此技术,在DBIM中原理是同样的。内存中存储索引跟踪 IMCU 中各列的最小值和最大值,好处相似于分区修剪。
存储索引自动的维护在内存中,不过每次重启不知道是否须要从新算。
SIMD又称为single instruction processing multiple data。SIMD并不是Oracle的技术,最初用于计算机生成动画和高性能计算。
好处是SIMD 向量处理容许发出一条 CPU 指令来估算一组列值,而不是一次估算列中的一个条目
除了内存速度外, Join的快取决于Bloom Filter,Bloom Filter于Oracle Database 10g引入。
bloom filter的原理须要解释一下:
A bloom filter transforms a join to a filter that can be applied as part of the scan of the fact table. Bloom filters were originally introduced in Oracle Database 10g to enhance hash join performance and are not specific to Oracle Database In-Memory. However, they are very efficiently applied to columnar data via SIMD vector processing.
Here is a brief description of how they work: When two tables are joined via a hash join, the first table (typically the smaller table) is scanned and the rows that satisfy the ‘where’ clause predicates (for that table) are used to create a hash table. During the hash table creation a bit vector or bloom filter is also created based on the join column. The bit vector is then sent as an additional predicate to the second table scan. After the where clause predicates have been applied to the second table scan, the resulting rows will have their join column hashed and it will be compared to values in the bit vector. If a match is found in the bit vector that row will be sent to the hash join. If no match is found then the row will be discarded. On Exadata the bloom filter or bit vector is passed as an additional predicate so it will be offloaded to the storage cells making bloom filtering even more efficient.
这里的关键是vector table是根据join的column计算的,若是有多个join则有多个vector table。能够参考Bloom Filters by Example
分析式查询一般须要的不只仅是简单筛选和联接。它们须要复杂的聚合和汇总。Oracle Database 12.1.0.2 中引入了一个新优化器转换(称为 Vector Group By),可以确保可以使用有效利用 CPU 的新算法处理更复杂的分析查询。
典型的Aggregation指相似于Group By之类的语句,其它还包括SUM, AVG, MIN, MAX等。
分析的数据不多会改动,但在混合负载的环境下,若是数据修改了,对于DBIM会有何影响?
对于批量数据加载,DBIM建议和分区之前使用,从而能够提供最佳性能。
对于DML修改,数据变化在行式缓存中修改,这和之前同样,而后在SCU(前面提到过)中会标记DBIM中的哪些数据是陈旧的,当访问到这些数据时就会结合日志返回最新的数据,后续在合适的时候会更新DBIM中的数据。
IMCU 中的陈旧条目越多,IMCU 的扫描速度就越慢。所以,当 IMCU 中的陈旧条目数达到陈旧程度阈值时,Oracle 数据库将从新填充 IMCU。
IMCO (内存中协调器)每隔两分钟就唤醒一次,检查是否有任何填充任务须要完成。
IM 列存储保持事务一致性带来的开销随应用程序而异,具体取决于多种因素,其中包括:更改速度、为表选择的内存中压缩级别、更改行的位置以及执行的操做类型。具备较高压缩级别的表将比具备较低压缩级别的表产生的开销要多。
对于具备高 DML 速率的表,建议使用 MEMCOMPRESS FOR DML,此外,若是可能,还建议使用分区在表内定位更改。
总之对应用是透明的,数据也是一致的。原理看如下两张图就足够了。
RAC 环境中的每一个节点均可以有其本身独立的 IM 列存储。对于不须要 IM 列存储的任何 RAC 节点,应将 INMEMORY_SIZE 参数设为 0。
强烈建议将每一个 RAC 节点的 IM 列存储设置为相同的大小。
能够在每一个节点上填充彻底不一样的对象,也能够在集群的全部 IM 列存储间分布(DISTRIBUTE)较大的对象。
还能够在每一个节点的 IM 列存储中存储相同的对象(DUPLICATE,仅限工程化系统)。
对象在集群中各个 IM 列存储间的分布经过 INMEMORY 属性的两个附加分子句进行控制:DISTRIBUTE 和 DUPLICATE。
默认状况下,Oracle 基于使用的分区类型(若是有)决定在集群中分布对象的最佳方式。或者,能够指定 DISTRIBUTE BY ROWID RANGE 按 rowid 范围分布,指定 DISTRIBUTE BY PARTITION 将分区分布给不一样的节点,或指定 DISTRIBUTE BY SUBPARTITION 将子分区分布给不一样的节点。
RAC可使用DISTRIBUTE来实现分布和并行处理,Exadata上的RAC能够再加上DUPLICATE实现容错和增长并行度。
DUPLICATE能够只复制到另外一个RAC节点,或经过DUPLICATE ALL复制到全部的节点,不过复制和为维护一致性带来的开销应较大。
Oracle Multitenant 是一个新的数据库整合模型,在该模型中,多个可插拔数据库 (PDB) 整合在一个容器数据库 (CDB) 中。在保持单一数据库的多个隔离特性的同时,它还支持多个 PDB 共享一个通用 CDB 的系统全局区域 (SGA) 和后台进程。所以,多个 PDB 也共享一个 IM 列存储。
IM 列存储的总大小经过在 CDB 中设置 INMEMORY_SIZE 参数进行控制。经过设置每一个 PDB 的 INMEMORY_SIZE 参数,来指定其可以使用的共享 IM 列存储的大小。并不是给定 CDB 中的全部 PDB 都须要使用内存中列存储。一些 PDB 能够将 INMEMORY_SIZE 参数设为 0,这意味着它们根本不使用内存中列存储。
PDB 的 INMEMORY_SIZE 参数的总和无需小于或等于 CDB 的 INMEMORY_SIZE 参数的大小。PDB 能够过分使用 IM 列存储。容许过分使用可确保某个可插拔数据库关闭或拔出的状况下不浪费 IM 列存储的宝贵空间。因为 INMEMORY_SIZE 参数是静态的(须要数据库实例重启才能反映更改),最好容许 PDB 过分使用,以即可以使用 IM 列存储的全部空间。
可是,因为这种过分使用,一个 PDB 可能会抢占另外一个 PDB 在 IM 列存储中的空间。若是不但愿任何 PDB 长时间关闭或拔出,建议不采用过分使用。
如 SELECT /+ NO_INMEMORY /
存在两个新的 v视图—v
IM_SEGMENTS 和 v$IM_USER_SEGMENTS,这两个视图可指示目前填充到 IM 列存储的对象。
SQL> SELECT v.owner, v.segment_name name, v.populate_status status, v.bytes_not_populated FROM v$im_segments v; OWNER NAME STATUS BYTES_NOT_POPULATED ---------- --------------- --------- ------------------- SSB DATE_DIM COMPLETED 0 SSB PART COMPLETED 0 SSB SUPPLIER COMPLETED 0 SSB LINEORDER STARTED 835780608 SSB CUSTOMER COMPLETED 0
向 *_TABLES 字典表中添加了一个新的布尔型列(称为 INMEMORY),以指示对哪些表指定了 INMEMORY 属性。
SQL> SELECT table_name, cache, inmemory, inmemory_priority, inmemory_distribute,inmemory_compression FROM user_tables; TABLE_NAME CACHE INMEMORY INMEMORY INMEMORY_DISTRI INMEMORY_COMPRESS ---------- -------------------- -------- -------- --------------- ----------------- DATE_DIM Y ENABLED NONE AUTO FOR QUERY LOW LINEORDER Y ENABLED NONE AUTO FOR QUERY LOW SUPPLIER Y ENABLED NONE AUTO FOR QUERY LOW CUSTOMER Y ENABLED NONE AUTO FOR QUERY LOW PART Y ENABLED NONE AUTO FOR QUERY LOW
IM 列存储的初始填充是 CPU 密集型操做,可能会影响同时运行的其余负载的性能。可使用 Resource Manager2 控制 IM 列存储填充操做的 CPU 使用,并根据须要更改操做的优先级。