oracle 12c 列式儲存 ( In Memory 理論)

來源:互聯網
上載者:User

標籤:odi   部分   使用者   過程   修改   方式   支援   儲存   元素   

隨著Oracle 12c推出了in memory組件,使得Oracle資料庫具有了雙模式資料存放方式,從而能夠實現對混合類型應用的支援:傳統的以行形式儲存的資料滿足OLTP應用;列形式儲存的資料滿足以查詢為主的OLAP應用。in memory組件可以和其他資料庫組件功能使用,並不需要使用者單獨開發或者修改應用程式,就可以非常方便的實現基於即時資料庫分析的轉變。本文會介紹in memory組件的一些相關知識,包含了以下的內容:

-列式儲存的基本知識 
-訪問in memory area中的資料 
-In memory和RAC的融合

1.列式儲存的基本知識。

1.1記憶體結構

傳統的資料庫採用的是行式儲存,當一個事務發生時,oracle會對一行(或多行)資料進行操作,也就是說資料的操作單位是一行資料,即使可能需要被訪問的資料只是其中的幾個列,這種資料儲存方式對以DML為主的OLTP應用是非常適合,也是非常高效的。但是在OLAP系統當中,針對大量資料的查詢操作是占絕對地位的,而這些查詢往往只針對錶中一些特定的列。另外,資料的改變都是以資料裝載的方式發生的,也就是說資料被裝載到資料庫後是極少發生改變的,毫無疑問以列的方式組織資料無疑是更好的選擇。正是因為這兩種存放資料的方式各有利弊,無論以哪一種方式來儲存資料都無法很好的滿足混合式應用的資料庫系統的要求,Oracle推出了所謂的雙模式資料存放方式:在磁碟(也就是資料檔案)和database buffer cache中以行的形式存放資料;單獨開闢一塊記憶體空間(in memory area),其中以列的方式儲存資料,滿足OLAP類型的查詢需求。而Oracle之所以選擇單獨開闢一塊記憶體來儲存列模式資料的主要原因之一就是OLAP的應用是以查詢為主的,而且資料改變的發生方式絕大部分都是以資料載入的方式發生的,這意味著oracle完全也通過批量資料載入的方式來完成in memory area空間中的資料載入從而保證資料的即時性。接下來,從in memory area記憶體結構,資料載入過程兩個方面來介紹in memory組件的一些基本知識。

首先,in memory area是獨立於傳統的SGA和PGA的單獨的記憶體空間,由1Mpool和64Kpool兩部分構成。其中1M pool用於儲存列格式的資料,IMCU(in memoryCompressionUnit)是基本的儲存單位;64Kpool用於儲存和IMCU相對的中繼資料資訊,SMU(SnapshotMetadataUnit)是這部分記憶體的基本單位。讀者可以通過下面的查詢瞭解相關的資訊。 

IMCU是用於在記憶體中儲存列格式資料的基本存放裝置單位,oracle會盡量保證每個IMCU的大小為1M,每個IMCU由圖1所示的兩部分構成

圖1

 

 

SMU部分主要用於儲存IMCU的原資料資訊,例如:IMCU對應的指標,IMCU包含的extent範圍,DBA範圍,Journaltable的指標,Rowid位元影像等。

1.2資料載入(populate)

在瞭解了in memory如何在記憶體中儲存資料之後,再來看一下資料是如何被載入到記憶體中的。根據之前內容的介紹,資料在資料檔案中是以行格式來儲存的,那麼就需要一種機制來把資料載入到in memory area當中,並且在載入過程當中完成從行模式到列模式的轉變。

首先,oracle支援對錶,分區或資料表空間指定in memory屬性,也就是說in memory屬性是針對物理資料庫物件的,而不是邏輯資料庫物件的。例如:我們可以使用下面的語句來為資料庫物件指定in memory屬性:

SQL>alter table sales inmemory no memcompress priority critical; 
SQL>ALTER TABLESPACE ts_data INMEMORY; 
SQL>ALTER TABLE sales MODIFY PARTITION SALES_201501 INMEMORY;

需要說明的是,由於in memory組件主要是針對OLAP應用的,而這種應用絕大部分的操作都是查詢,而且很多時候只關心表中特定的一個或多個列,所以in memory特性還可以指定只把表中的特定的一個或多個列載入到in memory area當中。

由於in memory area地區的大小是有限的,主機的記憶體資源也是有限的,而資料庫的容量往往會超過已有的記憶體資源,所以Oracle建議將效能要求很高的表裝載到in memory area當中,而將效能要求比較低的表儲存到快閃記憶體或者磁碟上。當然,如果記憶體資源充足,而且資料庫不大,大部分的應用是以查詢為主,也可以考慮將所有的表都裝載到in memory地區中。另外,也正是由於資源的限制,Oracle允許使用者為不同的表設定in memory載入優先順序,基本的原則是優先順序高的對象被首先載入到in memory地區當中,優先順序低的對象需要等到高優先順序的對象載入完畢之後才能夠被載入。Oracle提供了5種in memory載入優先順序,表1包含了每種優先順序的詳細資料。 

表1

 

另外,由於in memory主要是面向查詢為主的OLAP或者決策支援系統,也就是說絕大部分的資料再被裝載(Load)到資料庫之後就不會再改變了,那麼在載入資料的同時對資料進行壓縮無疑可以節省記憶體空間,而且還能夠提高查詢的效率(主要的原因是很多被查詢的列會包含大量的重複值)。所以in memory組件提供了豐富的壓縮選項,允許使用者在為對象指定in memory選項的同時指定壓縮方法。表2列出了支援的壓縮層級:

上表中的壓縮比率由上至下,越來越高。以下的sql語句說明在將表salse載入到in memory area時的優先順序最高,而且需要使用“memcompress for query”方式進行壓縮:SQL>alter table sales inmemory memcompress for query low priority critical; 
如果需要在指定壓縮選項之前瞭解每種壓縮選項能夠獲得的壓縮比,可以使用Oracle Compression Advisor(DBMS_COMPRESSION包)來進行估算。

最後,載入過程是通過後台進程IMCO和背景工作處理序(W00)進程來協同實現的,在資料庫啟動後或者一些對象的in memory選項被啟用後,IMCO進程會建立出一些載入任務,並根據需要分配給若干個背景工作處理序,每個背景工作處理序負責一部分資料的載入工作,當所有背景工作處理序完成了對應部分資料的載入之後,通知IMCO進程載入完成。

2.In memory的資料一致性

如果我們的資料庫是唯讀,那麼事情就變得簡單多了,因為資料就不會存在一致性問題,但是事實並非如此,對於大部分的資料庫,交易處理是一直都會發生的,那麼資料的一致性就需要得到保證。對於in memory組件也不例外,如果DML語句修改的資料並沒有被載入到in memory地區當中,那麼DML語句的修改就僅限於SGA當中;反之如果修改的資料已經被載入到了in memory地區中,那麼就需要一種機制來確保資料的一致性。例如:沒有被提交的資料不能被看到,而執行改變的會話應該能看到最新的資料。

Oracle 是通過journal table 的方式來確保資料的一致性的。每個IMCU都會對應一個自己的journal table, 如果DML語句修改的資料包含在IMCU當中,就在journal table 當中把修改後的資料記錄下來,我們稱之為private journal;當事務提交之後,再把journal table當中對應的記錄標識成為shared journal。這樣就可以保證查詢在訪問IMCU時能夠獲得一致的資料,而如果查詢需要的資料在journal table 中也無法找到時,oracle 會自動根據IMCU中記錄的Rowid 位元影像中的資訊映射到buffer cache 當中相應的位置來找到滿足查詢要求的資料。圖2描述了journal table和IMCU的基本關係。

圖2

 

然而,如果DML 語句不斷髮生的話,就會使journal table 中的資料越來越多,甚至出現IMCU中大部分的資料都是舊資料,而新資料都儲存在journal table中的情況,這對於in memory查詢的效能傷害是很大的。所以,Oracle定義了一個閥值(threshold),當IMCU中舊資料的比例達到這個閥值時就會觸發重新載入的過程,也就是說,IMCO後台進程會每隔一段時間(預設2分鐘)檢查一次是否有IMCU 滿足重新載入的條件,如果發現了滿足條件的IMCU,就會通知W00背景工作處理序對相應的IMCU進行重新載入,但是由於重新載入的成本是比較高的,而且可能會影響一些正在啟動並執行語句,所以Oracle 會採用漸進的方式來對IMCU進行重新載入的操作,也就是每次只選擇一部分滿足重新載入條件的IMCU進行處理,而具體的程度可以通過INMEMORY_TRICKLE_REPOPULATE_SERVERS_PERCENT參數來進行調整。

對於事務所產生的journal table對系統產生的額外負載到底有多大,這個是很難進行量化的,因為有太多的因素會對它產生影響,例如載入時採用的壓縮方法,改變的方式,應用程式訪問資料的行為。但是,仍然有一些基本的原則是可以盡量減少資料改變對in memory 產生的影響的。由於資料再被載入到in memory area時是以extent 為單位的,如果對資料的改變是隨機分布到表的各個extent的話,重新載入的成本就會很高,因為這意味著大量的IMCU需要被重新構建;而如果資料的改變能夠集中到特定範圍的extent中,或者大部分的改變都是資料插入而且使用直接路徑載入的話,那麼重新載入的成本就會被大大降低。另外的建議就是對盡量使用分區表來儲存資料,這樣有利於將資料的改變限定到特定的分區當中,而且針對這些分區不使用或者盡量使用 DML,MEMORYCOMPRESS FOR DML這些輕量級的壓縮方式。

3.訪問in memory area中的資料

3.1單表訪問

在資料被載入到in memory地區之後就可以通過sql語句對它們進行訪問了。分析型查詢的一個很大的特點就是它只關心表當中特定的一些列而不是全部的列,而且這些列的值很多時候會有大量的重複值,並且作為條件的列很多時候都是常見的資料類型(例如:數值,字串,日期),基於這些特點,Oracle的in memory組件也做了相應的設計來提高這些分析型查詢語句的效能。

首先,在IMCU當中每一個列都會包含對應的字典資訊和儲存索引資訊。在載入過程當中,背景工作處理序會將對應的IMCU中每個列所擁有的不同值編寫成一個字典,之後為該列的每一行資料指定一個keyvalue,用這個keyvalue來代替具體的值,這樣做既可以節省空間的也為將來查詢時能夠使用CPU的SIMD技術做準備。而儲存索引(StorageIndex)實際上是資料倉儲中常見的一種技術,他通過記錄某一個列的最大值和最小值的方式能夠避免訪問大量不滿足條件的資料。在IMCU中每個列的頭資訊當中都會儲存這個列在對應的IMCU當中的最大值和最小值,以及他們所對應的位移量。通過這種方法就可以在查詢資料時通過對比最大和最小值的方式快速過濾掉不滿足條件的資料,而且一旦資料改變影響到了儲存索引中的資訊,可以快速定位到對應的位置。但是需要指出的是,儲存索引並不見得適用於所有的where條件(謂詞)。

另外,由於資料已經被載入到了記憶體當中,所以絕大部分的操作都是需要通過cpu來實現的,I/O相關的操作基本不會出現了(除非被查詢的表有一部分資料還沒有被載入到in memory地區中來)。如何能夠更加高效的利用CPU資源就成為了決定效能的一個重要因素,所以Oracle採用了SIMD技術(Single Instruction processing Multiple Data values)使CPU能在一個指令當中訪問多個資料,但是由於SIMD所支援的指令是有限的,所以這也解釋了為什麼Oracle在構建IMCU時會為每個列都建立字典資訊。圖3描述了SIMD訪問資料的基本概念.

圖3

 

在中,sales表被載入到了in memory area當中,而且IMCU中PROMO_ID列的頭資訊當中也包含了該列的字典資訊,該列當中的每一行的值都已經被轉換成為了keyvalue,當查詢條件為PROMO_ID=9999是,就可以利用SIMD技術使CPU每次比較多行資料,從而極大地提升了查詢的效能。

最後,我們可以通過在執行計畫中尋找“TABLE ACCESS INMEMORY FULL TEST”資訊來確認是否使用了in memory選項訪問表。例如: 

3.2多表串連

除了針對訪問表的最佳化,in memory組件針對錶串連也進行了改進,主要的特性有:布隆過濾器和in memory彙總。

對於布隆過濾器(Bloom Filters),相信大家並不陌生。它的主要作用就是判斷某一個資料是否出現在另一個集合當中,或者用於比較大資料集合之間的共同元素。Oracle從10g開始就在處理一些SQL語句中的表串連時使用布隆過濾器。如果表串連中涉及到的表都已經指定了in memory屬性,並且已經載入到了in memory area當中,那麼最佳化器會首先選擇串連中的一個表(通常是較小的表),對作為連結條件的列進行一系列的hash函數,併產生一個結果位元影像(bitmap),之後再對另一個表的資料分批進行同樣的hash函數,並和之前的結果位元影像進行比較,在整個過程中並不會產生I/O而且SIMD技術在比較過程中也可以被使用,所以布隆過濾器的引入使in memory在處理表串連時變得更加高效。

CBO會在制定執行計畫時自動判斷是否使用布隆過濾器,使用者不需要手動指定。如果在執行計畫中看到了以下的資訊,說明布隆過濾器被使用了。

在上面的執行計畫說明:

1.首先在in memory area中訪問了表“TEST_SMALL”,就是執行計畫中的第5步,之後構建了連結使用的過濾器(BF0000),也就是執行計畫中的第4步。 
2.之後在in memory area中訪問了表“TEST_BIG”,就是執行計畫中的第7步,之後使用了之前構建的過濾器。

3.3多表串連

在以分析型的查詢語句為主的資料倉儲應用當中,除了簡單的表串連,還經常出現多表的連結,而且經常會包含一些彙總和分組操作,例如資料倉儲應用當中的星型查詢。針對這種查詢,oracle提出了向量分組(VectorGroupBY)特性來提高select語句的效能。向量分組是一個兩階段的過程:

階段1:CBO會找到查詢中資料量較小的維度資料表(Dimension table),將滿足條件的作為和龐大的事實表(Fact table)進行串連的列找出來並產生向量組(Vector Group)。之後將向量組和需要進行分組或者彙總的事實表中的列組合,形成一個多維陣列和若干個暫存資料表。

階段2:在事實表上應用上一階段產生的向量分組,之後向暫存資料表當中添加需要計算分組或彙總結果的列的值。最後將這些暫存資料表的資料應用到多維陣列中,計算出最後的分組或者彙總結果。

在整個過程中向量分組的構建和向量於事實表的比較都是在記憶體中完成的,而且SIMD也會被使用,所以可以極大的提升這種查詢的效能。當然,由於這種操作都是在記憶體中完成的,所以對系統的記憶體資源要求也是比較大的,要求運行這種查詢的進程擁有足夠的PGA空間。下面的執行計畫說明了分組向量在查詢中的應用:

根據上面的執行計畫:

-首先,表”TEST_SMALL_1”和”TEST_SMALL_2”被訪問,當然它們都已經被載入到了in memory area 
當中。之後分組向量被構建,他們是”KV0000”和”KV0001”,而且在和需要分組的表進行結合後,暫存資料表也被建立了出來,它們是“SYS_TEMP_0FD9D6604_116B7C6”和“SYS_TEMP_0FD9D6604_116B7C6”。 
-表“TEST_BIG”被訪問,之後向量分組被應用到了這個表上。然後開始向暫存資料表當中添加分組結果。 
-多維陣列中的結果被產生,它是“VW_VT_F486F43F”。最後通過“HASH GROUPBY”的方式完成最後的分組。

4.in memory和RAC的融合

延續Oracle新特性的一貫特點,in memory特性也可以和已經存在的其它資料庫組件相容,例如RAC,從而實現系統的高可用性和可擴充性。由於RAC屬於典型的share everything結構,它可以同時在多個節點開啟相同的資料庫,所以對於同一個資料庫物件,它可以被載入(populate)到多個節點上去。當然,前提條件是這些節點的資料庫執行個體都設定了in memory area(參數in memory_size不等於0)。既然資料可以被載入到多個節點,那麼就意味著我們需要思考兩個問題:

-問題1:如何將資料分布到多個節點。 
-問題2:資料是否有必要在in memory area當中儲存冗餘來確保高可用性。

對於資料的分布方式,oracle提供了根據資料的ROWID範圍或根據表的分區(或子分區)兩種方式來將資料分布到多個節點上。第一種方法是指將表的資料按照rowid的範圍劃分成若干份,之後將每份資料均勻的載入到不同的節點當中去,這種分布方式比較適用於資料分布不均勻的表,而且應用程式對錶的訪問在每個執行個體上都是比較均勻的情境。例如: 
ALTER TABLE test INMEMORY DISTRIBUTE BY ROWID RANGE; 
第二種方式適用於分區表,oracle會根據分區的定義將每個分區載入到不同節點的in memory area當中去,這種分布方式比較適合資料分布均勻的表。如果應用程式對錶的訪問在每個執行個體上都是比較均勻的,尤其適合hash分區表。例如:ALTER TABLE lineorder INMEMORY DISTRIBUTE BY PARTITION;

對於資料是否應該在in memory area中儲存冗餘,如果是普通的RAC資料庫,那麼資料並不會在in memory area中儲存冗餘;而對於Exadata一體機,in memory area中的資料是可以設定冗餘的。之所以選擇這樣做的原因在於,非Exadata一體機的RAC系統的私網配置千差萬別,如果選擇儲存冗餘的話,一旦當某一個執行個體down掉之後,意味著會有大量的資料需要在節點的私網之間進行傳輸,以便確保資料的冗餘,如果私網的效能不能得到保證的時候,這種資料的傳輸可能消耗大量的時間和網路資源,並導致嚴重的後果。而Exadata一體機的私網採用光纖網路,而且使用了先進的RDS協議,資料轉送可以達到幾十G每秒,所以在處理由於節點故障導致的大量私網資料轉送時,仍然可以保證叢集的私網正常工作。

另外,由於目前硬體層面的高可用技術已經非常成熟,一個資料庫執行個體或者節點down掉的事故大部分都是一次性的,很快就能恢複。所以Oracle在發現某一個執行個體或者節點fail之後並不會馬上觸發資料的重新分配,而是會等待一段時間以便讓問題節點或執行個體能夠重新啟動並載入自己的資料,只有當等待時間逾時之後,其他節點才會觸發資料重新分配的過程,將失敗節點的in memory area中的資料重新分配到正常節點。基於這種設計模式,建議在使用RAC系統上的in memory選項時應該為每個節點的in memory area預留出一部分空間,以便確保資料重新分配時仍然有足夠的空間。 
下面的圖4和圖5描述了Exadata環境和非Exadata環境in memory area儲存資料的區別

圖4-Exadata環境

 

圖5-非Exadata環境

 

根據上面的圖形不難發現,在RAC環境下的,每個節點都不會包含表當中的所有資料。所以在RAC環境下,需要啟用oracle的自動並行查詢(AutoDOP)才能夠使用in memory的方式訪問載入到in memory area中的表。另外還要說明的是在多執行個體的並發查詢中執行個體之間傳輸的並不是IMCU,而是每個節點都會對本節點的資料運行相同的sql語句,之後把自己的結果集發送給發起sql語句的執行個體,組成最終的結果返回給使用者。例如:一個4節點的RAC資料庫,表sales已經被載入到了in memory area當中。運行下面的查詢: 
select sum(stock) from sales where store_id in (100,200,300) and order_date=to_date(‘2016-01-01’, ‘yyyy-mm-dd’);

CBO首先會計算使用in memory scan的成本,如果成本最低,CBO就會選擇使用在in memory area中訪問sales表。接下來,oracle會訪問資料字典中的資訊,找到這個表被載入到了哪些執行個體,並在對應的節點啟動相應的並發進程(parallelslave),把這個查詢語句發送給並發進程運行。每個執行個體的並發進程運行完對應的sql語句之後,把產生的匯總值發送給發起查詢的執行個體,產生最終的匯總值並返回給客戶。在整個過程中,並不是IMCU在執行個體之間傳遞,而是匯總值在傳遞,所以能夠避免大量的私網資料通訊。

以上就是作者對oracle 12c in memory組件一些粗淺的介紹,希望對各位使用Oracle資料庫進行開發的人員有所協助,能夠在使用了in memoery組件的oracle資料庫上開發應用程式時有些借鑒作用。

轉:http://blog.sina.com.cn/s/blog_74a7d3390102wegl.html

oracle 12c 列式儲存 ( In Memory 理論)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.