作者:李敏,雲和恩墨交付工程師。
2019年度 ACOUG活動啟動啦!為了感恩和回饋一直支援社群工作的技術愛好者、會員、嘉賓和合作夥伴,2019年度,我們彙集了行業大咖最新的精彩主題跟大家分享,更有驚喜好禮等你拿,點選“我要報名”,立即參與!2019年,我們將探索更多可能。
本次活動我們邀請到了來自Oracle、雲和恩墨、Mellanox的專家,議題涵蓋故障解析、新架構、新功能。 有理論上的乾貨知識,更有動手實驗室,手把手教你使用Oracle APEX——快速開發應用。
Oracle Corp最先在11G R2中引入了EHCC(Exadata Hybrid Columnar
Compression),早先限制較多,體現的方式是這裡的E,指的是exadata一體機上才可以啟用這個特性。作為exadata上眾多優秀特性裡一個重要部分,和smart
scan或者說cell
offloading對比,雖然EHCC能帶來極大的空間壓縮,但是EHCC還是需要DBA額外做一些操作,甚至多個場景的評估來決定是否要採用。
EHCC(或者說後來因使用平臺更多,在除了exadata之外,在Oracle corp的zfssa、Pillar
Axiom、SuperCluster、ODA上都支援了之後改成了叫做HCC)本質上解決的問題是IO問題,也可以說,是為了在CPU及IO間平衡,拿算力換空間,目前看來在大部分場景下,這個交換是非常超值的,幾倍、十幾倍甚至幾十倍的壓縮率都很常見,如果這部分資料是冷資料,這個特性看起來是完美的。
但是有些時候不是這樣的。本文從HCC的多個方面選出一兩個點來簡述這個特性給DBA帶來的第一個直觀感受。
測試環境的DB版本
首先,準備環境
建立表空間,這裡選擇多個小檔案的方式。
CREATE SMALLFILE TABLESPACE EHCCTBS
DATAFILE
'/ehccfs/ORA19C/ora19pdb1/EHCCTBS_001.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240 ,
'/ehccfs/ORA19C/ora19pdb1/EHCCTBS_002.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240 ,
'/ehccfs/ORA19C/ora19pdb1/EHCCTBS_003.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240 ,
'/ehccfs/ORA19C/ora19pdb1/EHCCTBS_004.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240
BLOCKSIZE 8192
FORCE LOGGING
DEFAULT COLUMN STORE NO COMPRESS NO INMEMORY
ONLINE
SEGMENT SPACE MANAGEMENT AUTO
EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
(左右滑動,檢視完整程式碼,下同)
這裡選擇NO Compress方式建立表空間,不把壓縮作為表空間的屬性,而用CREATE TABLE的方式來指定壓縮屬性。
第一部分,這個部分看壓縮率。看OLAP的表現。(偏重SELECT)
繼續準備,測試使用者及源表。
[ora19c@dm01db06 ~]$ sqlplus / as sysdba
SQL*Plus: Release 19.0.0.0.0 - Production on Sun Mar 24 10:07:02 2019
Version 19.2.0.0.0
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0
SQL> create user hr identified by welcome1 default tablespace ehcctbs;
User created.
SQL> grant dba to hr;
Grant succeeded.
SQL> create table hr.big_table_no_ehcc as select * from dba_objects;
Table created.
為了體現壓縮率的差距,我建立了一個360M的未壓縮表,來對比8種壓縮方式下的壓縮率。
[ora19c@dm01db06 ~]$ sqlplus hr/welcome1@ora19pdb1
SQL*Plus: Release 19.0.0.0.0 - Production on Sun Mar 24 10:07:28 2019
Version 19.2.0.0.0
Copyright (c) 1982, 2018, Oracle. All rights reserved.
Last Successful login time: Sun Mar 24 2019 09:36:33 +08:00
Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.2.0.0.0
SQL>
SQL> insert into BIG_TABLE_NO_EHCC select * from BIG_TABLE_NO_EHCC;
72360 rows created.
SQL> /
144720 rows created.
SQL> /
289440 rows created.
SQL> /
578880 rows created.
SQL> insert into BIG_TABLE_NO_EHCC select * from BIG_TABLE_NO_EHCC;
1157760 rows created.
SQL> commit;
SQL> select count(*) from BIG_TABLE_NO_EHCC;
COUNT(*)
----------
2315520
SQL> col OWNER for a15
SQL> col SEGMENT_NAME for a40
SQL> select OWNER,SEGMENT_NAME,BYTES/1048576 SIZE_MB from dba_segments where SEGMENT_NAME like ('%EHCC%');
OWNER SEGMENT_NAME SIZE_MB
--------------- ---------------------------------------- ----------
HR BIG_TABLE_NO_EHCC 360
之後基於這個基礎表,建立8個不同HCC壓縮方式的表。這裡我timing on了,但是隻做參考,因為redo是200M的,導致CTAS的時候有一次歸檔行為,IO受影響,可能有一次的時間受影響。
SQL> create table EHCC_QUERY_HIGH compress for query high tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:10.61
SQL> create table EHCC_QUERY_LOW compress for query low tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:21.33
SQL> create table EHCC_ARCHIVE_HIGH compress for archive high tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:38.75
SQL> create table EHCC_ARCHIVE_LOW compress for archive low tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:11.07
SQL> create table EHCC_QUERY_HIGH_LOCKING compress for query high row level locking tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:09.46
SQL> create table EHCC_QUERY_LOW_LOCKING compress for query low row level locking tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:12.35
SQL> create table EHCC_ARCHIVE_HIGH_LOCKING compress for archive high row level locking tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:33.90
SQL> create table EHCC_ARCHIVE_LOW_LOCKING compress for archive low row level locking tablespace ehcctbs as select * from big_table_no_ehcc ;
Table created.
Elapsed: 00:00:17.50
然後檢視這些不同壓縮方式下的物件大小。註意這裡的LOCKING,指的是row level locking。
除了第一個基礎表之外,每兩個相鄰物件的壓縮區別是row level locking方式的區別。
hr.BIG_TABLE_NO_EHCC這個表是基於PDB的dba_objects來建立的一個28列的表,實話說,這個表做HCC跑分測試並不適合,但是依然能在archive high樣式下,達到驚人的360/15=24倍的壓縮率。
基本符合這個趨勢吧?
那麼,對未壓縮的基礎表強制全掃,再對最高壓縮的archive high的表做強制全掃的話,哪個快呢?
多次測試,結果出乎意料。16秒跟1秒下的差距,這是沒在exadata上的結果,如果集合exadata的cell offloading,可以詳見OLAP下,HCC的表現了。
Oracle對自家產品間的協同和最佳化令人目瞪狗獃。
第二部分,這個部分看DML。看OLTP的表現。(偏重DML測試)
既能壓縮幾十倍的空間,還能高速query,甚至還能高速DML,還想著讓鎖的範圍儘量小,如何實現呢?
這個測試起來要考慮的東西有點多,要考慮CU大小,CU內有多少行,CU內鎖的範圍,insert的位置,update的影響範圍,delete影響的範圍,以及delete之後的空間的重用和壓縮。
CU是HCC裡引入的新概念,叫做Compression Unit,壓縮單元。
上文構造的環境有點大,不適合接下來的OLTP的測試,以下dump出來幾個塊。
拿壓縮率最高的EHCC_ARCHIVE_HIGH來吧。
這裡插句話,看到有些檔案說,HCC下的ROWID不是指的block的ID號,而是指向CU的號,這個部分其實很好理解,不好理解的是,怎麼證明哪些block被壓在了同一個CU上?
我們檢視EHCC_ARCHIVE_HIGH表的extents分佈。
Oracle SQLdeveloper查詢的結果
按照Oracle
DB的分配原則,0區的前面塊為一級,二級點陣圖塊,eygle曾展示過三級點陣圖塊,但是我的環境裡沒有做這個構造,這裡把一級和二級點陣圖塊展示出來。就是0區,24號檔案的14336和14337塊。然後接著往後dump,14338
,14339,14340,14341,14342,14343,14344(1區第一個塊)。
來看一下這些塊是什麼。
14336,一級點陣圖塊
*** 2019-03-24T17:14:51.182266+08:00 (ORA19PDB1(3))
Start dump data blocks tsn: 6 file#:24 minblk 14336 maxblk 14336
............................
............................
............................
Dump of Second Level Bitmap Block
number: 9 nfree: 1 ffree: 8 pdba: 0x06003802
Inc #: 0 Objd: 72974 Flag: 3
opcode:0
這裡提示到:
Second Level Bitmap block DBAs
--------------------------------------------------------
DBA 1: 0x06003801
二級點陣圖塊,正好是一級14336的下一個塊:
下麵是這個二級點陣圖塊的資訊:
Dump of Second Level Bitmap Block
number: 9 nfree: 1 ffree: 8 pdba: 0x06003802
Inc #: 0 Objd: 72974 Flag: 3
opcode:0
xid:
L1 Ranges :
--------------------------------------------------------
0x06003800 Free: 1 Inst: 1
0x06003840 Free: 1 Inst: 1
0x05803400 Free: 1 Inst: 1
0x06003880 Free: 1 Inst: 1
0x05803480 Free: 1 Inst: 1
0x06003900 Free: 1 Inst: 1
0x05803500 Free: 1 Inst: 1
0x06003980 Free: 1 Inst: 1
0x05803580 Free: 7 Inst: 1
--------------------------------------------------------
End dump data blocks tsn: 6 file#: 24 minblk 14337 maxblk 14337
看樣子是沒什麼東西。似乎是表太小沒用到。
14338塊資訊不多。這裡看14339塊。
block_row_dump:
tab 0, row 0, @0x30
tl: 8016 fb: --H-F--N lb: 0x0 cc: 1
nrid: 0x06003804.0
col 0: [8004]
Compression level: 04 (Archive High)
Length of CU row: 8004
kdzhrh: ------PC- CBLK: 0 Start Slot: 00
NUMP: 22
PNUM: 00 POFF: 7774 PRID: 0x06003804.0
PNUM: 01 POFF: 15790 PRID: 0x06003805.0
PNUM: 02 POFF: 23806 PRID: 0x06003806.0
PNUM: 03 POFF: 31822 PRID: 0x06003807.0
PNUM: 04 POFF: 39838 PRID: 0x06003808.0
PNUM: 05 POFF: 47854 PRID: 0x06003809.0
PNUM: 06 POFF: 55870 PRID: 0x0600380a.0
PNUM: 07 POFF: 63886 PRID: 0x0600380b.0
PNUM: 08 POFF: 71902 PRID: 0x0600380c.0
PNUM: 09 POFF: 79918 PRID: 0x0600380d.0
PNUM: 10 POFF: 87934 PRID: 0x0600380e.0
PNUM: 11 POFF: 95950 PRID: 0x0600380f.0
PNUM: 12 POFF: 103966 PRID: 0x06003810.0
PNUM: 13 POFF: 111982 PRID: 0x06003811.0
PNUM: 14 POFF: 119998 PRID: 0x06003812.0
PNUM: 15 POFF: 128014 PRID: 0x06003813.0
PNUM: 16 POFF: 136030 PRID: 0x06003814.0
PNUM: 17 POFF: 144046 PRID: 0x06003815.0
PNUM: 18 POFF: 152062 PRID: 0x06003816.0
PNUM: 19 POFF: 160078 PRID: 0x06003817.0
PNUM: 20 POFF: 168094 PRID: 0x06003818.0
PNUM: 21 POFF: 176110 PRID: 0x06003819.0
*---------
CU essay-header:
CU version: 0 CU magic number: 0x4b445a30
CU checksum: 0xbdbe82d3
CU total length: 180160
CU flags: NC-U-CRD-OP
ncols: 26
nrows: 32759
algo: 0
CU decomp length: 175939 len/value length: 4332401
row pieces per row: 1
num deleted rows: 0
START_CU:
這部分資訊較多,我按照個人的理解來說說。
tl: 8016 fb: –H-F–N這裡的H是CUhead的意思。fb是flag byte,F是first的意思,P是previous,N是next。此外我沒有dump最後一個row
piece,按道理來說,最後一個0x06003819塊上的fb會顯示L的,代表last。(事實上我事後dump了,顯示的LP)
nrid:
0x06003804.0這裡nrid是next row piece id的意思,這裡的資料是nrid:
0x06003804.0,換成10進位制是rdba: 0x6003804(100677636) file: 24 ,block :
14340,24號檔案14340塊。
按照道理來說,14340塊上顯示的是類似PN,沒有H的tag。
Compression level: 04 (Archive High)是HCC壓縮格式。
NUMP: 22是代表這個CU裡有多少個row piece,這裡顯示的是22個row piece,而根據這個地址看,一個row piece就是一個block,我理解是代表,這個CU裡有22個block。
CU checksum: 0xbdbe82d3是這個CU的校驗值。
nrows: 32759,代表這個CU裡存了32759行,這是一個非常大的數值。
接下來,我們dump那個第二個CU塊,14340塊。
Start dump data blocks tsn: 6 file#:24 minblk 14340 maxblk 14340
..........................
..........................
..........................
block_row_dump:
tab 0, row 0, @0x1f
tl: 8033 fb: ------PN lb: 0x0 cc: 1
nrid: 0x06003805.0
col 0: [8021]
Compression level: 04 (Archive High)
Length of CU row: 8021
kdzhrh: ---------START_CU:
如上文標識的一樣,這是PN。
這裡將分別按照insert,update,delete這三個DML來測試在HCC情況下相關的可能的壓縮轉換情況,ROWID變化情況,鎖範圍情況來闡述。
在DML場景中,對比兩張表,非壓縮表和壓縮表。壓縮表的所有行,都在一個CU的一個塊裡。
如下是建立的表,有一張普通表,一張archive high的表,以及一張row level locking的archive high表。他們分配的大小是一樣的,這不代表在extents內佔的空間是一樣大,而是因為表初始分配的extents是8個block,每個block是8192 bytes。這個是ASSM的分配規律。
SQL> create table dml_test_no_ehcc as select * from dba_objects where rownum 100;
Table created.
SQL> update dml_test_no_ehcc set OBJECT_ID=rownum;
99 rows updated.
SQL> commit;
Commit complete.
SQL> create table DML_TEST_ARCHIVE_HIGH compress for archive high tablespace ehcctbs as select * from dml_test_no_ehcc ;
Table created.
SQL> create table DML_TEST_ARCHIVE_HIGH_LOCKING compress for archive high row level locking tablespace ehcctbs as select * from dml_test_no_ehcc ;
Table created.
col OWNER for a15
col SEGMENT_NAME for a40
SQL> select s.OWNER,s.SEGMENT_NAME,s.BYTES/1024 SIZE_MB,t.COMPRESS_FOR from dba_segments s,dba_tables t where s.SEGMENT_NAME like ('DML_TEST_%') and s.owner=t.owner and s.segment_name = t.table_name order by 2;
OWNER SEGMENT_NAME SIZE_MB COMPRESS_FOR
--------------- ---------------------------------------- ---------- ----------------------------------
SYS DML_TEST_ARCHIVE_HIGH 64 ARCHIVE HIGH
SYS DML_TEST_ARCHIVE_HIGH_LOCKING 64 ARCHIVE HIGH ROW LEVEL LOCKING
SYS DML_TEST_NO_EHCC
接下來,需要證明這兩個HCC的表的所有行都在同一個CU裡。
DML_TEST_ARCHIVE_HIGH表的所有8個塊
DML_TEST_ARCHIVE_HIGH_LOCKING表的所有8個塊
這個時候,除去一級和二級點陣圖塊,dump每個表的第四個塊,就是說DML_TEST_ARCHIVE_HIGH在24號檔案的19203塊,和DML_TEST_ARCHIVE_HIGH_LOCKING在24號檔案的19211塊,從dump資訊中檢視是否所有行在一個CU內。
19203塊,資訊如下,可以看到fb標識為Head,有F,有L,代表這個CU既是first也是last的CU,並且這個CU裡的nrows 是99行。這都跟構造的環境一致。
data_block_dump,data essay-header at 0x9b95a07c
===============
tsiz: 0x1f80
hsiz: 0x1c
pbl: 0x9b95a07c
76543210
flag=-0------
ntab=1
nrow=1
frre=-1
fsbo=0x1c
fseo=0x1830
avsp=0x1814
tosp=0x1814
r0_9ir2=0x0
mec_kdbh9ir2=0x0
76543210
shcf_kdbh9ir2=----------
76543210
flag_9ir2=--R----- Archive compression: Y
fcls_9ir2[0]={ }
0x16:pti[0] nrow=1 offs=0
0x1a:pri[0] offs=0x1830
block_row_dump:
tab 0, row 0, @0x1830
tl: 1872 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [1866]
Compression level: 04 (Archive High)
Length of CU row: 1866
kdzhrh: --------- Start Slot: 00
*---------
CU essay-header:
CU version: 0 CU magic number: 0x4b445a30
CU checksum: 0x24a713c2
CU total length: 1854
CU flags: NC-U-CRD-OP
ncols: 26
nrows: 99
algo: 0
CU decomp length: 1715 len/value length: 10614
row pieces per row: 1
num deleted rows: 0
START_CU:
同樣,另外一個表的19211塊也是得到一樣的構造資訊。
data_block_dump,data essay-header at 0x7fda7a65e07c
===============
tsiz: 0x1f80
hsiz: 0x1c
pbl: 0x7fda7a65e07c
76543210
flag=-0------
ntab=1
nrow=1
frre=-1
fsbo=0x1c
fseo=0x17c9
avsp=0x17ad
tosp=0x17ad
r0_9ir2=0x0
mec_kdbh9ir2=0x0
76543210
shcf_kdbh9ir2=----------
76543210
flag_9ir2=--R----- Archive compression: Y
fcls_9ir2[0]={ }
0x16:pti[0] nrow=1 offs=0
0x1a:pri[0] offs=0x17c9
block_row_dump:
tab 0, row 0, @0x17c9
tl: 1975 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [1969]
Compression level: 04 (Archive High)
Length of CU row: 1969
kdzhrh: --------L Start Slot: 00
num lock bits: 8
locked rows:
*---------
CU essay-header:
CU version: 0 CU magic number: 0x4b445a30
CU checksum: 0x24a713c2
CU total length: 1854
CU flags: NC-U-CRD-OP
ncols: 26
nrows: 99
algo: 0
CU decomp length: 1715 len/value length: 10614
row pieces per row: 1
num deleted rows: 0
START_CU:
OLTP下的第一個場景測試,我們暫定為insert測試,這裡只針對HCC的表做測試,分別測試append方式和常規插入方式在HCC表及row level locking的HCC表下的表現。
根據檔案顯示,對已經HCC壓縮的表的插入,如果是常規插入,新插入的資料將不會被壓縮,只有以append等直接路徑的方式插入,才會繼續壓縮。這裡除了需要驗證這個事情之外,還需要驗證下其他會話的併發插入會不會受影響,如果被阻塞,需要測試row level locking方式的HCC表是否受影響。
SQL> select distinct(sid) from v$mystat;
SID
----------
147
SQL> insert into DML_TEST_ARCHIVE_HIGH select * from DML_TEST_NO_EHCC;
99 rows created.
SQL>
SQL> select distinct(sid) from v$mystat;
SID
----------
269
SQL> insert into DML_TEST_ARCHIVE_HIGH select * from DML_TEST_NO_EHCC;
99 rows created.
SQL>
這個測試為了證明沒有row level locking屬性的HCC表的插入,不會鎖定單個CU。
但是,這個測試測下來,有一個問題,就是對於沒有使用append方式的插入,如果插入的資料,當前已經壓縮的CU可以容下,那麼插入的資料是會被壓縮的,如果以沒有append方式插入的資料,當前CU放置不下,那麼在接下來的分配中,超出當前CU的資料是特麼的不會被壓縮的。
這個又一次出乎意料。
COUNT(*) COMPRESSION_TYPE
---------- ---------------------------------------------------------------
10 COMP_NOCOMPRESS
323126 COMP_FOR_ARCHIVE_HIGH
SQL>
OLTP下的第二個場景,我們測試DELETE,這個我也不知道測試什麼,我暫且對HCC的表,做兩個會話的刪除測試。
我測試了兩次,如果這個表沒有被壓縮,我分別在兩個會話中,刪除object_id=1及2的資料,不提交,是互相不會阻塞的。
但是,如果這個表是HCC壓縮,並且沒有開啟row level locking的話,如果在會話1刪除object_id=1的條目,在會話2中刪除object_id=2的條目,會話2的刪除,是會被會話1阻塞的。
這也側面驗證了,普通HCC表,鎖的最小單元是CU,而不是像普通表那樣,受影響的是被其他會話已經影響到的行。不過仔細一想,道理似乎是一樣的。
那麼,我前面鋪墊了那麼多row level
locking的HCC特性這個時候就發揮作用了。這個特性是在12c的HCC中引入了。Oracle
corp可能發現對整個CU加鎖影響的範圍太大了,為了對OLTP友好,引入了row level
locking的HCC的特性,雖然這可能帶來一點點的壓縮損耗,在前文能看到壓縮損耗的情況。
接下來,對那張建立好的row level locking的表做不同會話的object_id=1和object_id=2的記錄的刪除。
可以看到添加了row level locking屬性的HCC表的同個CU內的刪除是互不影響的。
OLTP中,第三個場景測試,我們將測試update,據前文DELETE測試,可以顯然的知道,HCC中不帶row level locking的壓縮是會被其他update阻塞的。帶了的話,如果針對同一個CU內不同記錄操作,是不會影響的。如果是同一個CU內的相同記錄操作,那會是怎麼樣呢:)。
UPDATE部分,這裡重點測試的是rowid變化情況。
重新生成環境:
SQL> drop table DML_TEST_ARCHIVE_HIGH purge;
Table dropped.
SQL> drop table DML_TEST_ARCHIVE_HIGH_LOCKING purge;
Table dropped.
SQL> drop table DML_TEST_NO_EHCC purge;
Table dropped.
這次表建立的更小。
SQL> create table dml_test_no_ehcc as select * from dba_objects where rownum 10;
Table created.
SQL> create table DML_TEST_ARCHIVE_HIGH compress for archive high tablespace ehcctbs as select * from dml_test_no_ehcc ;
Table created.
SQL> create table DML_TEST_ARCHIVE_HIGH_LOCKING compress for archive high row level locking tablespace ehcctbs as select * from dml_test_no_ehcc ;
Table created.
SQL>
SQL> col OWNER for a15
SQL> col SEGMENT_NAME for a40
SQL> select s.OWNER,s.SEGMENT_NAME,s.BYTES/1024 SIZE_MB,t.COMPRESS_FOR from dba_segments s,dba_tables t where s.SEGMENT_NAME like ('DML_TEST_%') and s.owner=t.owner and s.segment_name = t.table_name order by 2;
OWNER SEGMENT_NAME SIZE_MB COMPRESS_FOR
--------------- ---------------------------------------- ---------- ------------------------------------------------------------------------------------------
HR DML_TEST_ARCHIVE_HIGH 64 ARCHIVE HIGH
HR DML_TEST_ARCHIVE_HIGH_LOCKING 64 ARCHIVE HIGH ROW LEVEL LOCKING
HR DML_TEST_NO_EHCC 64
SQL>
檢視其中HCC表的rowid及塊號分佈情況。
SQL> select rowid,object_name,dbms_rowid.rowid_block_number(rowid) from DML_TEST_ARCHIVE_HIGH;
ROWID OBJECT_NAME DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------ ---------------------------------------- ------------------------------------
AAAR0vAAWAAAEWLAAA I_FILE#_BLOCK# 17803
AAAR0vAAWAAAEWLAAB I_OBJ3 17803
AAAR0vAAWAAAEWLAAC I_TS1 17803
AAAR0vAAWAAAEWLAAD I_CON1 17803
AAAR0vAAWAAAEWLAAE IND$ 17803
AAAR0vAAWAAAEWLAAF CDEF$ 17803
AAAR0vAAWAAAEWLAAG C_TS# 17803
AAAR0vAAWAAAEWLAAH I_CCOL2 17803
AAAR0vAAWAAAEWLAAI I_PROXY_DATA$ 17803
9 rows selected.
這裡可以透過DBMS_COMPRESSION.GET_COMPRESSION_TYPE來確認某行資料的壓縮方式:
SQL> select DBMS_COMPRESSION.GET_COMPRESSION_TYPE('HR','DML_TEST_ARCHIVE_HIGH','AAAR0vAAWAAAEWLAAA') from dual;
DBMS_COMPRESSION.GET_COMPRESSION_TYPE('HR','DML_TEST_ARCHIVE_HIGH','AAAR0VAAWAAAEWLAAA')
----------------------------------------------------------------------------------------
16
參考如下:
COMP_NOCOMPRESS CONSTANT NUMBER := 1;
COMP_FOR_OLTP CONSTANT NUMBER := 2;
COMP_FOR_QUERY_HIGH CONSTANT NUMBER := 4;
COMP_FOR_QUERY_LOW CONSTANT NUMBER := 8;
COMP_FOR_ARCHIVE_HIGH CONSTANT NUMBER := 16;
COMP_FOR_ARCHIVE_LOW CONSTANT NUMBER := 32;
COMP_RATIO_MINROWS CONSTANT NUMBER := 1000000;
COMP_RATIO_ALLROWS CONSTANT NUMBER := -1;
可以得知,16就是建立時候的ARCHIVE_HIGH壓縮方式。
之後,對這個表,進行更新操作。
SQL> update DML_TEST_ARCHIVE_HIGH set OBJECT_NAME=OBJECT_NAME||'MINOR';
9 rows updated.
再次檢視這個表的rowid及塊號:
SQL> select rowid,object_name,dbms_rowid.rowid_block_number(rowid) from DML_TEST_ARCHIVE_HIGH;
ROWID OBJECT_NAME DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------ ---------------------------------------- ------------------------------------
AAAR0vAAWAAAEWOAAA I_FILE#_BLOCK#MINOR 17806
AAAR0vAAWAAAEWOAAB I_OBJ3MINOR 17806
AAAR0vAAWAAAEWOAAC I_TS1MINOR 17806
AAAR0vAAWAAAEWOAAD I_CON1MINOR 17806
AAAR0vAAWAAAEWOAAE IND$MINOR 17806
AAAR0vAAWAAAEWOAAF CDEF$MINOR 17806
AAAR0vAAWAAAEWOAAG C_TS#MINOR 17806
AAAR0vAAWAAAEWOAAH I_CCOL2MINOR 17806
AAAR0vAAWAAAEWOAAI I_PROXY_DATA$MINOR 17806
9 rows selected.
可以看到,rowid,block id,都發生了變化,所以證明對CU內的資料更新,這裡有解壓,移動到別的block更新的操作。
那麼更新後的資料還是壓縮的嗎?顯然,不是了。
SQL> select DBMS_COMPRESSION.GET_COMPRESSION_TYPE('HR','DML_TEST_ARCHIVE_HIGH',rowid) from DML_TEST_ARCHIVE_HIGH;
DBMS_COMPRESSION.GET_COMPRESSION_TYPE('HR','DML_TEST_ARCHIVE_HIGH',ROWID)
-------------------------------------------------------------------------
1
1
1
1
1
1
1
1
1
9 rows selected.
壓縮為1,1代表的是COMP_NOCOMPRESS CONSTANT NUMBER := 1,不壓縮。所以,除了insert,update也會帶來解壓不壓縮的情況。在執行update操作時,db會將列壓縮的資料,轉換為行來操作,並且在操作完成之後,並不會再次壓縮。
如果需要重新讓這些複蘇的資料重新壓縮,需要顯式的move這些表。
剛才註意到,更新會導致壓縮資料的rowid發生變化,那麼,能不能不變化?答案是可以的。
隱含引數:
標亮的部分
這居然是一個動態引數
然後我們復現上面的更新操作:
rowid,block id均保持不變
第三部分,上面OLAP及OLTP的這麼多測試均是單個場景的測試,那麼HCC在實際場景下使用起來跟不帶HCC的環境對比起來怎麼樣?這裡想起了swingbench。
swingbench不多介紹。但是有個問題,swingbench的物件是自己程式生成的,不能人工幹預建立物件用的引數,除非你逐個去改那些指令碼。
其實有個簡單的辦法,就是建立測試表空間的時候,給表空間加上HCC引數。這裡只做query high場景下不帶row level locking及帶row level locking跟非HCC場景下的壓力測試。考慮到客戶環境不是會序列的,所以我使用4個會話來測試。測試基準資料量為0.5GB,要測三場。
首先生成三個承載表空間,一個是帶了HCC屬性,一個是帶了HCC的row level locking屬性,一個是不帶HCC屬性。
SQL> CREATE SMALLFILE TABLESPACE SOE_EHCC_TBS
2 DATAFILE
3 '/ehccfs/ORA19C/ora19pdb1/SOE_EHCC_TBS_001.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240
4 BLOCKSIZE 8192
5 FORCE LOGGING
6 DEFAULT COLUMN STORE COMPRESS FOR query HIGH NO INMEMORY
7 ONLINE
8 SEGMENT SPACE MANAGEMENT AUTO
9 EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
Tablespace created.
SQL> CREATE SMALLFILE TABLESPACE SOE_NO_EHCC_TBS
2 DATAFILE
3 '/ehccfs/ORA19C/ora19pdb1/SOE_NO_EHCC_TBS_001.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240
4 BLOCKSIZE 8192
5 FORCE LOGGING
6 DEFAULT COLUMN STORE COMPRESS FOR query HIGH NO INMEMORY
7 ONLINE
8 SEGMENT SPACE MANAGEMENT AUTO
9 EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
Tablespace created.
SQL> CREATE SMALLFILE TABLESPACE SOE_EHCC_ROW_LOCKING_TBS
2 DATAFILE
3 '/ehccfs/ORA19C/ora19pdb1/SOE_EHCC_ROW_LOCKING_TBS_001.DBF' SIZE 10485760 AUTOEXTEND ON NEXT 1048576 MAXSIZE 10737418240
4 BLOCKSIZE 8192
5 FORCE LOGGING
6 DEFAULT COLUMN STORE COMPRESS FOR query HIGH ROW LEVEL LOCKING NO INMEMORY
7 ONLINE
8 SEGMENT SPACE MANAGEMENT AUTO
9 EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
Tablespace created.
生成資料
最終能看到生成的資料如下:
均已為query high的HCC的壓縮方式
待資料生成完成之後,開始swingbench的測試。這裡停止了測試。因為在swingbench的預設場景中,有大量的DML操作,而跟我上文測試的結果,隨著業務時間的推移,大部分表都會因DML而變成非壓縮表。所以DML測試的意義不大。唯一可能有測試意義的就是OLAP了。這個修改swingbench配置此處省略。