索引組織表上建立BITMAP索引(二)
Oracle的索引組織表也支援BITMAP索引型別,不過需要對映表的支援。
描述一下對映表的結構的特點。
索引組織表上建立BITMAP索引(一):http://yangtingkun.itpub.net/post/468/503513
上一篇文章介紹了索引組織表的對映表,下面簡單描述一下對映表的結構,以及為什麼Oracle需要這個對映表。
SQL> DROP TABLE T_INDEX_ORG;
表已刪除。
SQL> CREATE TABLE T_INDEX_ORG
2 (ID NUMBER PRIMARY KEY,
3 NAME VARCHAR2(30),
4 TYPE VARCHAR2(30))
5 ORGANIZATION INDEX
6 MAPPING TABLE;
表已建立。
SQL> CREATE BITMAP INDEX IND_B_INDEX_TYPE
2 ON T_INDEX_ORG (TYPE);
索引已建立。
SQL> SELECT TABLE_NAME, IOT_NAME, IOT_TYPE
2 FROM USER_TABLES
3 WHERE IOT_TYPE IS NOT NULL;
TABLE_NAME IOT_NAME IOT_TYPE
------------------------------ ------------------------------ ------------
SYS_IOT_MAP_32399 T_INDEX_ORG IOT_MAPPING
T_INDEX_ORG IOT
SQL> SELECT TABLE_NAME, INDEX_NAME, INDEX_TYPE
2 FROM USER_INDEXES
3 WHERE TABLE_NAME = 'T_INDEX_ORG';
TABLE_NAME INDEX_NAME INDEX_TYPE
------------------------------ ------------------------------ -------------
T_INDEX_ORG SYS_IOT_TOP_32399 IOT - TOP
T_INDEX_ORG IND_B_INDEX_TYPE BITMAP
現在已經建立好索引組織表、對映表和BITMAP索引,首先來看看對映表的結構:
SQL> DESC SYS_IOT_MAP_32399
名稱 是否為空? 型別
----------------------------------------------------------------- -------- --------------
SYS_NC_01 ROWID
對映表的結構很簡單,只有一個ROWID欄位。
下面在表中插入一條記錄:
SQL> INSERT INTO T_INDEX_ORG VALUES (1, 'T_INDEX_ORG', 'IOT');
已建立 1 行。
可以看到,對映表中自動包含了ROWID資訊。
SQL> SELECT * FROM SYS_IOT_MAP_32399;
SYS_NC_01
--------------------------------------------------
*BAAAAAACwQL+
根據這個ROWID,就可以從索引組織表找到對應的記錄:
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BAAAAAACwQL+';
ID NAME TYPE
---------- ------------------------------ ------------
1 T_INDEX_ORG IOT
但是仔細觀察一下,就會發現對映表中的ROWID與從索引組織表中查詢得到的ROWID並不相同:
SQL> SELECT ROWID FROM T_INDEX_ORG;
ROWID
-------------------------------------
*BAJAADQCwQL+
透過DUMP看看二者的差別:
SQL> COL D_ROWID FORMAT A50
SQL> SELECT ROWID, DUMP(ROWID, 16) D_ROWID
2 FROM T_INDEX_ORG;
ROWID D_ROWID
------------------------------- ------------------------------------------------
*BAJAADQCwQL+ Typ=208 Len=10: 2,4,2,40,0,34,2,c1,2,fe
SQL> COL SYS_NC_01 FORMAT A30
SQL> SELECT SYS_NC_01, DUMP(SYS_NC_01, 16) D_ROWID
2 FROM SYS_IOT_MAP_32399;
SYS_NC_01 D_ROWID
------------------------------ --------------------------------------------------
*BAAAAAACwQL+ Typ=208 Len=10: 2,4,0,0,0,0,2,c1,2,fe
原來索引組織表的ROWID包括物理猜資訊,而對映表儲存的ROWID,沒有記錄實體地址資訊,而只包括了索引組織表的主鍵。
那麼索引組織表就有一個有趣的特性,可以透過多個ROWID訪問相同的一條記錄:
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BAJAADQCwQL+';
ID NAME TYPE
---------- ------------------------------ ------------------------------
1 T_INDEX_ORG IOT
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BAAAAAACwQL+';
ID NAME TYPE
---------- ------------------------------ ------------------------------
1 T_INDEX_ORG IOT
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BABCDAACwQL+';
ID NAME TYPE
---------- ------------------------------ ------------------------------
1 T_INDEX_ORG IOT
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BADDDDACwQL+';
ID NAME TYPE
---------- ------------------------------ ------------------------------
1 T_INDEX_ORG IOT
換句話說,只要ROWID包含的主鍵資訊是正確的,就可以訪問到對應的記錄,而與邏輯ROWID中的實體地址是否存在、是否準確無關。
可以看到,前面兩個ROWID分別是索引組織表真實的ROWID,以及對映表中儲存的ROWID,但是後面兩個ROWID,完全是根據ROWID的規則仿寫的,而且居然也可以得到記錄。
扯遠一點,這一點就是邏輯ROWID和物理ROWID的一個重要區別。一條記錄只有一個物理ROWID,而一個物理ROWID是在資料庫中唯一的,它表示唯一一個實體地址,它可能對應到一條記錄,也可能不對應任何一條記錄。
而根據上面的結果也可以看到,多個邏輯ROWID可以指向同一條記錄,也就是說1條記錄對應多個邏輯ROWID。
而一個邏輯ROWID也可以指向多條記錄,看一個簡單的例子:
SQL> CREATE TABLE T_INDEX_ORG1
2 (ID NUMBER PRIMARY KEY)
3 ORGANIZATION INDEX;
表已建立。
SQL> INSERT INTO T_INDEX_ORG1 VALUES (1);
已建立 1 行。
SQL> SELECT ROWID FROM T_INDEX_ORG1;
ROWID
-----------------------------------------
*BAJABSwCwQL+
SQL> ALTER TABLE T_INDEX_ORG1 MOVE MAPPING TABLE;
表已更改。
SQL> SELECT TABLE_NAME, IOT_NAME, IOT_TYPE
2 FROM USER_TABLES
3 WHERE IOT_TYPE IS NOT NULL;
TABLE_NAME IOT_NAME IOT_TYPE
------------------------------ ------------------------------ ------------
SYS_IOT_MAP_32399 T_INDEX_ORG IOT_MAPPING
SYS_IOT_MAP_32427 T_INDEX_ORG1 IOT_MAPPING
T_INDEX_ORG IOT
T_INDEX_ORG1 IOT
SQL> SELECT * FROM SYS_IOT_MAP_32427;
SYS_NC_01
------------------------------
*BAAAAAACwQL+
SQL> SELECT * FROM T_INDEX_ORG
2 WHERE ROWID = '*BAAAAAACwQL+';
ID NAME TYPE
---------- ------------------------------ ------------------------------
1 T_INDEX_ORG IOT
SQL> SELECT * FROM T_INDEX_ORG1
2 WHERE ROWID = '*BAAAAAACwQL+';
ID
----------
1
同一個邏輯ROWID可以指向不同表中的不同記錄,只要它們的主鍵資訊是相同的。
於是可以看到一個十分有趣的SQL:
SQL> SELECT A.ROWID, B.ROWID
2 FROM T_INDEX_ORG A, T_INDEX_ORG1 B
3 WHERE A.ROWID = B.ROWID;
ROWID ROWID
----------------------------------------- ------------------------------------
*BAJAADQCwQL+ *BAJABUwCwQL+
兩個ROWID明明不等,但是居然可以查詢出結果。這就是邏輯ROWID特點所造成的。
這次扯的真是有點遠了,還是回到最初的話題。
可以看到,對於建立了對映表的索引組織表,在做任何修改的時候,都會同步修改對映表中的ROWID資訊。而如果是透過ALTER TABLE MOVE MAPPING TABLE新增的對映表,會自動將目前索引組織表中所有記錄的ROWID,新增到對映表中。
SQL> SELECT * FROM T_INDEX_ORG;
ID NAME TYPE
---------- ------------------------------ --------------------
1 T_INDEX_ORG IOT
SQL> SELECT * FROM SYS_IOT_MAP_32399;
SYS_NC_01
------------------------------
*BAAAAAACwQL+
SQL> UPDATE T_INDEX_ORG SET ID = 2;
已更新 1 行。
SQL> SELECT * FROM SYS_IOT_MAP_32399;
SYS_NC_01
------------------------------
*BAJAADQCwQP+
當記錄的主鍵發生變化的時候,Oracle也會更新對映表中儲存的邏輯ROWID資訊。
在Oracle確保對映表和索引組織表的同步的情況下,就可以利用對映表來建立BITMAP索引了。
Oracle之所以無法直接在索引組織表上建立BITMAP索引,是因為BITMAP索引儲存的是一個個ROWID範圍,在這些範圍內透過BITMAP來對應表的ROWID資訊。而索引組織表的實際儲存格式是索引,而索引的根節點、分支節點和葉節點都儲存在一起,因此實際儲存表資料的葉節點在一個EXTENT中是不連續的。
建立了對映表後,BITMAP索引實際是建立在對映表這個堆表上,透過對映表中儲存的邏輯ROWID資訊,對應到索引組織表中。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-670807/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 索引與null(二):組合索引索引Null
- Oracle大表快速建立索引Oracle索引
- mongodb建立索引和刪除索引和背景索引backgroundMongoDB索引
- Hive建立索引Hive索引
- DocumentDB 建立索引索引
- mysql組合索引,abc索引命中MySql索引
- [20200108]線上建立索引失敗分析.txt索引
- MySQL建立表的時候建立聯合索引的方法MySql索引
- mysql建立字首索引MySql索引
- ElasticSearch分片互動過程(建立索引、刪除索引、查詢索引)Elasticsearch索引
- magento2 建立資料表及新增索引索引
- ORA-01658建立表或索引報錯分析索引
- MySQL 二 索引MySql索引
- MySQL索引(二):建索引的原則MySql索引
- 【Mysql】InnoDB 中的聚簇索引、二級索引、聯合索引MySql索引
- 理解索引(上)索引
- 從InnoDB 索引執行簡述 聚集索引和非聚集索引、覆蓋索引、回表、索引下推索引
- MySQL索引建立原則MySql索引
- Lucene建立索引流程索引
- postgresql怎麼建立索引SQL索引
- 【Mongo】MongoDB索引管理-索引的建立、檢視、刪除MongoDB索引
- 61_索引管理_快速上機動手實戰建立、修改以及刪除索引索引
- 一個文章表的 MySQL 索引怎麼建立合理MySql索引
- 索引設計(組合索引適用場景)索引
- 聯合索引和多個單列索引使用中的索引命中情況及索引建立原則索引
- oracle重建索引(二)Oracle索引
- Phoenix 二級索引索引
- Phoenix二級索引索引
- 建立索引後,速度變快原因?以及索引失效總結索引
- MySQL學習筆記:組合索引-索引下推MySql筆記索引
- mysql的組合索引MySql索引
- 【STAT】Oracle 表統計資訊被鎖,如何建立索引Oracle索引
- mysql建立索引和檢視MySql索引
- Oracle如何建立B樹索引Oracle索引
- 資料庫之建立索引資料庫索引
- 建立索引的優劣勢索引
- MySQL如何建立一個好索引?建立索引的5條建議【宇哥帶你玩轉MySQL 索引篇(三)】MySql索引
- MySQL管理表和索引MySql索引
- MySql如何使用索引(二)MySql索引