轉 https://blog.csdn.net/stevensxiao/article/details/51437274
參考文獻
https://www.zhihu.com/question/19883454
https://blog.csdn.net/zhangzheng0413/article/details/8271322/
Database In-Memory是Oracle數據庫的選項,類似於RAC,ADG,發布於12.0.1.2。
它的主要目的是利用內存的速度和優化的列格式來加速分析。以下我們用DBIM或IM作為Database In-Memory的縮寫。
Oracle Database In-Memory 選件
行格式與列格式
傳統的數據庫概念中,行式數據庫適合於OLTP的DML操作,如Oracle, Mysql;而列式數據庫適合於分析,如Sybase IQ, SAP HANA。
而在一個混合負載的環境中,就會面臨兩難的選擇。
DBIM在Oracle傳統的行式存儲之外提供了內存中的列式存儲,然后自動的為用戶訪問選擇后端的行式或列式存儲,從而解決了此難題。
換句話說,在磁盤上只有一份數據,而在內存中則存在行式的Cache和列式的IM內存數據。
新的IM存儲不會增加雙倍的內存需求,首先因為我們無需將所有的列式數據都載入內容,其次內存中列式數據可以壓縮,而且由於重復值較多,壓縮的比率也較高。
增加了DBIM,通常內存需求會增加20%,具體可以使用In-Memory Advisor計算。
雖然列式數據適合於只讀的情形,但並不意味數據不可修改,數據修改后,DBIM自動維護數據的一致性,自動在后台刷新列式存儲,這一切對於應用都是透明的。
再次強調,列式數據不是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分區
- 1
- 2
- 3
- 4
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);
- 1
- 2
- 3
- 4
- 5
- 6
使用何種壓縮可以使用Oracle Compression Advisor (DBMS_COMPRESSION)來評估。
內存中掃描
內存中掃描速度快取決於以下因素。
列式存儲
這時最根本的,分析只訪問部分列,這樣避免了大量I/O,好處類似於分區,只不過是垂直分區。
Storage Index
在Exadata中已經出現過此技術,在DBIM中原理是一樣的。內存中存儲索引跟蹤 IMCU 中各列的最小值和最大值,好處類似於分區修剪。
存儲索引自動的維護在內存中,不過每次重啟不知道是否需要重新算。
SIMD 向量處理
SIMD又稱為single instruction processing multiple data。SIMD並非Oracle的技術,最初用於計算機生成動畫和高性能計算。
好處是SIMD 向量處理允許發出一條 CPU 指令來估算一組列值,而不是一次估算列中的一個條目
內存中 Join
除了內存速度外, 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
內存中 Aggregation
分析式查詢通常需要的不僅僅是簡單篩選和聯接。它們需要復雜的聚合和匯總。Oracle Database 12.1.0.2 中引入了一個新優化器轉換(稱為 Vector Group By),能夠確保可使用有效利用 CPU 的新算法處理更復雜的分析查詢。
典型的Aggregation指類似於Group By之類的語句,其它還包括SUM, AVG, MIN, MAX等。
DML 和內存中列存儲
分析的數據很少會改動,但在混合負載的環境下,如果數據修改了,對於DBIM會有何影響?
對於批量數據加載,DBIM建議和分區以前使用,從而可以提供最佳性能。
對於DML修改,數據變化在行式緩存中修改,這和以前一樣,然后在SCU(前面提到過)中會標記DBIM中的哪些數據是陳舊的,當訪問到這些數據時就會結合日志返回最新的數據,后續在合適的時候會更新DBIM中的數據。
IMCU 中的陳舊條目越多,IMCU 的掃描速度就越慢。因此,當 IMCU 中的陳舊條目數達到陳舊程度閾值時,Oracle 數據庫將重新填充 IMCU。
IMCO (內存中協調器)每隔兩分鍾就喚醒一次,檢查是否有任何填充任務需要完成。
IM 列存儲保持事務一致性帶來的開銷隨應用程序而異,具體取決於多種因素,其中包括:更改速度、為表選擇的內存中壓縮級別、更改行的位置以及執行的操作類型。具有較高壓縮級別的表將比具有較低壓縮級別的表產生的開銷要多。
對於具有高 DML 速率的表,建議使用 MEMCOMPRESS FOR DML,此外,如果可能,還建議使用分區在表內定位更改。
總之對應用是透明的,數據也是一致的。原理看以下兩張圖就足夠了。
RAC 上的內存中列存儲
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 長時間關閉或拔出,建議不采用過度使用。
控制 Oracle Database In-Memory 的使用
核心初始化參數
- INMEMORY_SIZE - 大於0時啟用DBIM.該參數只能在系統級進行修改,且需要數據庫重啟才能生效
- INMEMORY_QUERY - 可以在會話級或系統級將 INMEMORY_QUERY 設置為 DISABLE,來禁用 IM 列存儲。默認值為 ENABLE。
- INMEMORY_MAX_POPULATE_SERVERS - 可以啟動的最大工作進程數通過 INMEMORY_MAX_POPULATE_SERVERS 進行控制,該參數默認設置為 0.5 X CPU_COUNT。減少工作進程數將減少填充過程中占用的 CPU 資源,但可能會延長填充 IM 列存儲所花費的時間。
優化器提示
如 SELECT /+ NO_INMEMORY /
監視和管理 Oracle Database In-Memory
哪些對象位於內存中列存儲中
存在兩個新的 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
USER_TABLES
向 *_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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
管理 IM 列存儲填充的 CPU 占用
IM 列存儲的初始填充是 CPU 密集型操作,可能會影響同時運行的其他負載的性能。可以使用 Resource Manager2 控制 IM 列存儲填充操作的 CPU 使用,並根據需要更改操作的優先級。