Bitmap Index作為一種全新的索引類型,支援在重複度高的列上建立索引,能夠提供高效的點值查詢和範圍查詢的能力。本文為您介紹在MaxCompute中如何使用Bitmap Index索引類型。
背景資訊
MaxCompute當前共提供四種索引類型:Hash Clustering、Range Clustering、Bloomfilter Index和Bitmap Index。這四種索引都能夠提供點查詢過濾的能力。相比於Range Clustering在滿足最左匹配原則的情況下才能夠提供範圍過濾的能力,Bloomfilter Index能很好地應對點查情境,而Bitmap Index更多面向於範圍查詢情境,在範圍過濾情境下可過濾掉超過60%以上的資料,從而起到查詢加速的效果。
Bitmap Index具有以下優勢:
每個Bitmap Index的查詢都是獨立的,沒有最左匹配原則限制。
支援多列。可以對錶的一列或者多列建立Bitmap Index,並且能夠與其他索引搭配共同加速查詢。
過濾效果好。Bitmap Index通過對每一個值建立一個位元影像的方式,使得過濾結果能夠精確到行,在重複度高且資料分布緊湊的情境下有很好的過濾效果。
適用於交並集運算(OR和AND運算),可以最佳化多維查詢。
適用情境
適用於重複度高的列,且僅包含有限幾種取值,比如性別、城市等。
適合執行邏輯運算,例如AND、OR等,能夠高效地對Bitmap進行位元運算。
在基數過大或查詢過濾效果不佳的情況下,可能會出現佔用較多的儲存空間以及讀取效能變差的情況,因此不建議對類似以下的列建立Bitmap Index索引:
值重複度低的列,如:社會安全號碼、手機號碼等。
經常需要更新修改的列。
計費說明
儲存部分:索引構建後會佔用額外儲存空間,會根據索引實際儲存大小統計,與專案資料的儲存用量合并計費,定價與標準儲存費用相同。
計算部分:索引的構建會觸發額外的計算任務,增加計算資源消耗。預付費情況下會直接使用專案的預付費資源,後付費情況下,索引相關計算任務的費用=
SQL後付費單價*複雜度1*索引相關任務輸入資料量。
使用限制
當前僅支援在非嵌套的STRING、CHAR、VARCHAR、TINYINT、SMALLINT、INT、BIGINT和DOUBLE類型上建立。
支援加速以下查詢:
<=、<、=、>、>=、IN、BETWEEN和IS NULL。
注意事項
建立Bitmap Index前請執行
setproject odps.schema.evolution.enable=true;命令,設定允許表結構變更(Schema Evolution)。目前僅支援1次對1列建立Bitmap Index,若您需要為表的多個列建立Bitmap Index,則需要多次執行建立Bitmap Index語句。
建立索引之後,插入資料時系統會自動對錶產生Bitmap索引。
Bitmap Index若要對存量資料生效,需要重建Bitmap Index。
樣本資料
Bitmap Index相關文法樣本均基於emp表和sale_detail表中的資料。
非分區表
建立
emp表。CREATE TABLE IF NOT EXISTS emp( empno BIGINT, ename STRING, job STRING, mgr BIGINT, sex STRING );插入資料。
INSERT INTO emp(empno,ename,job,mgr,sex) VALUES (7369,'smith','clerk',7902,'Male'), (7499,'allen','salesman',7698,'Female'), (7521,'ward','salesman',7698,'Male'), (7654,'martin','salesman',7698,'Male'), (7698,'blake','manager',7839,'Male'), (7782,'clark','manager',7839,'Male'), (7788,'scott','analyst',7566,'Male'), (7839,'king','president',NULL,'Male'), (7844,'turner','salesman',7698,'Female'), (7876,'adams','clerk',7788,'Female'), (7900,'james','clerk',7698,'Male'), (7902,'ford','analyst',7566,'Male'), (7934,'miller','clerk',7782,'Female');
分區表
建立
sale_detail分區表。CREATE TABLE IF NOT EXISTS sale_detail( shop_name STRING, customer_id STRING, total_price DOUBLE) PARTITIONED BY (sale_date STRING, region STRING);建立分區。
ALTER TABLE sale_detail ADD PARTITION (sale_date='2023', region='china') PARTITION (sale_date='2024', region='shanghai');
建立Bitmap Index
文法
CREATE BITMAP INDEX <index_name> ON TABLE <table_name> FOR COLUMNS(<col_name>) [COMMENT 'indexcomment'];參數說明
index_name:必填,索引名稱。
table_name:必填,表名。
col_name:必填,列名。針對此列建立的索引。
樣本
為
emp表中的empno列建立索引,名稱為empno_index。CREATE BITMAP INDEX empno_index ON TABLE emp FOR COLUMNS(empno) COMMENT 'idxcomment';為
emp表中的job職位列建立索引,名稱為job_index。CREATE BITMAP INDEX job_index ON TABLE emp FOR COLUMNS(job) COMMENT 'idxcomment';為
sale_detail表的shop_name列建立索引,名稱為shop_name_index。CREATE BITMAP INDEX shop_name_index ON TABLE sale_detail FOR COLUMNS(shop_name) COMMENT 'indexcomment';
重建Bitmap Index
文法
使用如下命令對存量資料重建Bitmap Index。
非分區表重建。
ALTER TABLE <table_name> REBUILD BITMAP INDEX;分區表重建。
ALTER TABLE <table_name> PARTITION (<partition_name1=value1>[, partition_name2=value2, ...]) REBUILD BITMAP INDEX;說明分區表一次只能對一個分區進行重建。
參數說明
非分區表
table_name:必填,表名。
分區表
table_name:必填,表名。
partition_name:必填,分區名稱。
value:必填,分區值。
樣本
樣本1:非分區表。
ALTER TABLE emp REBUILD BITMAP INDEX;樣本2:分區表。
ALTER TABLE sale_detail PARTITION (sale_date='2023', region='china') REBUILD BITMAP INDEX;
查詢Bitmap Index
文法
SHOW INDEXES ON <table_name>;參數說明
table_name: 必填,表名。
樣本
--查看emp表上的索引
SHOW INDEXES ON emp;返回結果如下。
{"Indexes": [{
"id": "00c84b0e9e6e4097bdfe3a01b91848ac",
"indexColumns": [{"name": "job"}],
"name": "job_index",
"properties": {"comment": "jobidx"},
"type": "BITMAP"},
{
"id": "18a9755c7a8a4182a6b51165e786aa62",
"indexColumns": [{"name": "empno"}],
"name": "empno_index",
"properties": {"comment": "idxcomment"},
"type": "BITMAP"}]}查詢資料並查看Bitmap Index效果
樣本
樣本1:對
job職位列進行點查。SELECT * FROM emp WHERE job = 'clerk';返回結果如下。
+------------+-------+-----+------------+------------+-----+ | empno | ename | job | mgr | hiredate | sex | +------------+-------+-----+------------+------------+-----+ | 7369 | smith | clerk | 7902 | NULL | Male | | 7876 | adams | clerk | 7788 | NULL | Female | | 7900 | james | clerk | 7698 | NULL | Male | | 7934 | miller | clerk | 7782 | NULL | Female | +------------+-------+-----+------------+------------+-----+樣本2:對
empno列進行範圍查詢。SELECT * FROM emp WHERE empno BETWEEN 7300 AND 7800;返回結果如下。
+------------+------------+------------+------------+------------+ | empno | ename | job | mgr | sex | +------------+------------+------------+------------+------------+ | 7369 | smith | clerk | 7902 | Male | | 7499 | allen | salesman | 7698 | Female | | 7521 | ward | salesman | 7698 | Male | | 7654 | martin | salesman | 7698 | Male | | 7698 | blake | manager | 7839 | Male | | 7782 | clark | manager | 7839 | Male | | 7788 | scott | analyst | 7566 | Male | +------------+------------+------------+------------+------------+
查詢索引效果。
在控制台作業記錄中,單擊Log view連結,進入LogView頁面。

在LogView頁面的Json Summary一欄中搜尋Bitmap關鍵字,可以看到通過Bitmap Index帶來的過濾效果以及構造Bitmap Index所帶來的額外耗時(不包含IO的耗時)。

刪除Bitmap Index
文法
DROP INDEX [IF EXISTS] <index_name> ON TABLE <table_name>;參數說明
index_name:必填,索引名稱。
table_name:必填,表名。
樣本
DROP INDEX IF EXISTS job_index ON TABLE emp;