Greenplum索引管理

Greenplum 索引

PostgreSQL 目前支持8種索引接口,包括B-Tree, hash, gin, gist, sp-gist, brin, rum, bloom。

Greenplum 目前支持B-Tree, GiST, bitmap三種索引接口。

用戶可以根據不同的數據類型,不同的請求類型,使用不同的索引接口建立相應的索引。例如對於數組,全文檢索類型,可以使用GIN索引,對於地理位置數據,範圍數據類型,圖像特徵值數據,幾何類數據等,可以選擇GiST索引。

1 概述

1.1 索引不是萬能的,無副作用的

在pg中,我們會經常使用索引來加速查詢,但是在Greenplum中對於索引的依賴卻比較低,應該合理的使用。因爲在gp中順序掃描會很快,而索引掃描則是一種隨即搜索的模式。Greenplum的數據分佈在Segment上,因此每個Segment會掃描全體數據的一小部分來得到結果。通過表分區,要掃描的數據量可能會更少,因此索引使用的場景可能會更少。
並且索引通常會增加一些數據庫負擔,它們使用存儲空間並且在表被更新時需要被維護。

首先在不加索引時嘗試用戶的查詢負載。索引更有可能爲OLTP負載改進性能,在那種場景中查詢會返回一個單一記錄或者數據的一個小的子集。 在被壓縮過的追加優化表上,索引也可以提高返回一個目標行集合的查詢的性能,因爲優化器在適當的時候可以使用一種索引訪問方法而不是全表掃描。 對於壓縮過的數據,使用一種索引訪問方法意味着只有必要的行會被解壓。

1.2 主鍵自動創建索引,分佈表索引見到主表

Greenplum數據庫會自動爲帶有主鍵的表創建PRIMARY KEY約束。要在一個被分區的表上創建索引,就在用戶創建的分區表上創建一個索引。該索引會被傳播到Greenplum數據庫所創建的所有子表上。不支持在Greenplum數據庫爲分區表創建的子表上創建索引。

注意一個UNIQUE CONSTRAINT(例如PRIMARY KEY CONSTRAINT)會隱式地創建一個UNIQUE INDEX,它必須包括分佈鍵中所有的列以及任何分區鍵。UNIQUE CONSTRAINT會在整個表上被強制要求,包括所有的表分區(如果有)。

2 索引的命名規範

索引命名規範

索引以IDX作爲前綴標識,不能與表同名。在長度允許的情況下,最好能標識出該索引對應的表名和字段名。

建立索引的名稱的原則是簡潔和易於理解,索引命名採用如下的規範:

  1. 普通索引:IDX_<簡要表名>_<索引首字段名稱>

例如在CS_REC_RECPTION表的INT_SERVERVER 字段上建立普通索引命名如下IDX_RECEPTION_SERVNUMBER

  1. 唯一索引:UID_<簡要表名>_<索引首字段名稱>

例如在CS_REC_RECPTION表的INT_SERVERVER 字段上建立唯一索引命名如下UID_RECEPTION_SERVNUMBER

  1. 主鍵:PK_<表名>

例如在CS_REC_RECPTION表的INT_SERVERVER 字段上建立主鍵索引命名如下PK_CS_REC_RECEPTION

在長度允許的情況下,最好能標識出該索引對應的表名和字段名。

3 索引使用規範

3.1 索引需要考慮的因素

  • 用戶的查詢負載。 索引能改進查詢返回單一記錄或者非常小的數據集的性能,例如OLTP負載。
  • 壓縮表。在被壓縮過的追加優化表上,索引也可以提高返回一個目標行集合的查詢的性能。對於壓縮過的數據,一種索引訪問方法意味着只有必要的行會被解壓。
  • **避免在頻繁更新的列上建立索引。**在一個被頻繁更新的列上建立索引會增加該列被更新時所要求的寫操作數據量。
  • **創建選擇性的B-樹索引。**索引選擇度是一個列中具有的可區分值的數量除以表中行數得到的比例。例如,如果一個表有1000行並且一個列中有800個可區分的值,則該索引的選擇度爲0.8,這還不錯。唯一索引的選擇度總是1.0,這是最好的選擇度。Greenplum數據庫只允許在分佈鍵列上的唯一索引。
  • 爲低選擇度的列使用位圖索引。 Greenplum數據庫的位圖索引類型在常規的PostgreSQL中不可用。
  • **索引在連接中用到的列。**在被用於頻繁連接的一個列(例如一個外鍵列)上的索引能夠提升連接性能,因爲這讓查詢優化器有更多的連接方法可以使用。
  • **索引在謂詞中頻繁使用的列。**頻繁地在WHERE子句中被引用的列是索引的首選。
  • **避免重疊的索引。**具有相同前導列的索引是冗餘的。
  • **批量載入前刪掉索引。**對於載入大量數據到一個表中,請考慮先刪掉索引並且在數據裝載完成後重建它們。這常常比更新索引更快。
  • 考慮一個聚簇索引。 聚簇一個索引意味着記錄會根據索引被物理排序後存儲在磁盤上。如果用戶需要的數據被隨機分佈在磁盤上,數據庫必須在磁盤上來回尋找以取得所需的記錄。如果這些記錄被存儲得彼此臨近,那麼取得它們的操作就會更高效。例如,一個在日期列上的聚簇索引中數據會按照日期順序存放。針對一個指定日期範圍的查詢將會導致對磁盤的一次有序地讀取,這會利用快速的順序訪問。
  • 重創建索引執行執行Analyze。

4 Greenplum 支持的索引類型

PostgreSQL 目前支持8種索引接口,包括B-Tree, hash, gin, gist, sp-gist, brin, rum, bloom。

Greenplum 目前支持B-Tree, GiST, bitmap和GIN四種索引接口。可以分區索引和組合索引。

用戶可以根據不同的數據類型,不同的請求類型,使用不同的索引接口建立相應的索引。例如對於數組,全文檢索類型,可以使用GIN索引,對於地理位置數據,範圍數據類型,圖像特徵值數據,幾何類數據等,可以選擇GiST索引。

Note: 只有索引鍵的列與Greenplum分佈鍵相同(或者是其超集)時,Greenplum數據庫才允許唯一索引。在追加優化表上不支持唯一索引。在分區表上,唯一索引無法在一個分區表的所有子表分區之間被實施。唯一索引只能在一個分區內實施。

5 Greenplum索引分類及適用場景

(1)btree索引

適合於擁有重複值較少的字段。數據重複值越少,查詢數據選擇性越 ,使 索引查詢數據的效率越 ,反之則越低。
適於對字段所在數據有少 修改的場合,如字段有較少 的插 、修改、刪除等情況, 新索引字段鍵值的代價適中。適於數據變化相對頻繁的系統需要佔較的存儲空間
(2)bitmap索引

擁有較 重複值的字段,數據重複值對索引的查詢效率影響 對字段所有數據只讀或者極少修改的場合數據變化很少的數據分析系統需要較 的存儲空間。

Greenplum數據庫提供位圖索引類型。位圖索引最適合於擁有大量數據、很多臨時查詢以及少量數據修改(DML)事務的數據倉庫應用和決策支持系統。

一個索引提供了指向表中包含一個給定鍵值的行的指針。常規索引存儲了每個鍵存儲了一個元組ID的列表,列表中的元組ID對應於具有那個鍵值的行。 位圖索引爲每一個鍵值都存儲一個位圖。常規索引可能會比表中的數據大幾倍,但位圖索引提供了和常規索引相同的功能並且只需要被索引數據尺寸的一小部分。

位圖中的每一個位對應於一個可能的元組ID。 如果該位被設置,則具有相應元組ID的行包含該鍵值。 一個映射函數負責將這個位的位置轉換成一個元組ID。位圖被壓縮存儲。如果可區分鍵值的數量很小,位圖索引會小很多同時也會被壓縮得更好,並且比常規索引節省可觀的空間。 一個位圖索引的大小與該表中行數乘以被索引列中不同值數量的結果成比例。

位圖索引對於在WHERE子句中包含多個條件的查詢最有效。 滿足某些但不是全部條件的行在訪問表之前就會被過濾掉。這通常會極大地改善響應時間。

(3)hash索引

索引的 涉及到經常使 =操作時候, 不推薦使用

6 索引測試

6.1 bitmap索引

bitmap索引類似GIN倒排,只是bitmap的KEY是列的值,VALUE是BIT(每個BIT對應一行),而不是行號list或tree。
bitmap與btree一樣,都支持 等於,大於,小於,大於等於,小於等於的查詢。但是要注意:bitmap索引適用於只查詢數據而不更新數據的數據倉庫應用。

例子:—建表

postgres=# CREATE table t2 (id int,info text)
postgres-# with(appendonly=true,orientation=column)
postgres-# distributed by(id);
CREATE TABLE
postgres=# insert into t2 select generate_series(1,100000),md5(random()::text);
INSERT 0 100000

—不使用索引

postgres=# EXPLAIN select * from t2 where id <10;
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Gather Motion 2:1  (slice1; segments: 2)  (cost=0.00..1364.00 rows=10 width=37)
   ->  Append-only Columnar Scan on t2  (cost=0.00..1364.00 rows=5 width=37)
         Filter: id < 10
 Optimizer status: legacy query optimizer
(4 rows)

—創建bitmap索引

postgres=# CREATE INDEX idx_t2 on t2 using bitmap(id);
CREATE INDEX

—再次查看執行計劃發現走bitmap索引掃描了。

postgres=# EXPLAIN select * from t2 where id <10;     
                                         QUERY PLAN                                         
--------------------------------------------------------------------------------------------
 Gather Motion 2:1  (slice1; segments: 2)  (cost=101.98..808.90 rows=10 width=37)
   ->  Bitmap Append-Only Column-Oriented Scan on t2  (cost=101.98..808.90 rows=5 width=37)
         Recheck Cond: id < 10
         ->  Bitmap Index Scan on idx_t2  (cost=0.00..101.98 rows=5 width=0)
               Index Cond: id < 10
 Optimizer status: legacy query optimizer
(6 rows)

重建索引:
—重建指定索引

postgres=# REINDEX INDEX idx_t2;
REINDEX

—重建一張表上所有索引

postgres=# REINDEX TABLE t2;
REINDEX

6.3 B-tree索引

​ CREATE INDEX命令在一個表上定義一個索引。 例如,要在表employeegender列上創建一個B-樹索引:

CREATE INDEX gender_idx ON employee (gender);

6.3 表達式索引

索引列不必只是表的一列,而是可以是從表的一列或多列計算的函數或標量表達式。 此功能對於根據計算結果快速訪問表非常有用。

索引表達式的維護成本相對較高,因爲必須在插入和每次更新時爲每一行計算派生表達式。

第一個示例是使用lower函數進行不區分大小寫的比較的常用方法:

SELECT * FROM test1 WHERE lower(col1) = 'value';

如果一個索引已經在lower(col1)函數的結果上被定義,該查詢可以使用索引:

CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

7 檢查索引使用

Greenplum數據庫的索引並不要求維護和調優。 用戶可以檢查實際的查詢負載使用了哪些索引。 使用EXPLAIN命令可以檢查一個查詢的索引使用。

查詢計劃展示了數據庫將用來回答一個查詢的步驟或者計劃節點以及每一個計劃節點的時間估計。要檢查索引的使用,請在用戶的EXPLAIN輸出中尋找以下查詢計劃節點類型:

  • 索引掃描 - 一次索引的掃描。
  • 位圖堆掃描 - 檢索所有由BitmapAnd、BitmapOr或者BitmapIndexScan生成的位圖並且訪問堆以檢索相關的行。
  • 位圖索引掃描 - 計算一個由所有來自底層索引的滿足查詢謂詞的位圖通過OR操作形成的位圖。
  • BitmapAndBitmapOr - 取得從多個BitmapIndexScan節點生成的位圖,把它們AND或者OR在一起,並且生成一個新的位圖作爲其輸出。

用戶必須做實驗來確定要創建哪些索引。請考慮以下幾點。

  • 在創建或者更新一個索引後運行ANALYZE。ANALYZE會收集表統計信息。 查詢優化器使用表統計信息來估算一個查詢所返回的行數並且爲每一種可能的查詢計劃賦予實際開銷。
  • 實驗中使用真實數據。使用測試數據建立索引會告訴用戶該測試數據需要什麼樣的索引,但也僅此而已。
  • 不要使用非常小的測試數據集,因爲它們的結果很可能是不真實的或者傾斜的。
  • 在開發測試數據時要小心。相似的、完全隨機的或者排序後插入的值都將使統計信息偏離真實數據的分佈。
  • 通過使用運行時參數來關閉特定的計劃類型,用戶可以強制使用索引來進行測試。 例如,關閉順序掃描(enable_seqscan)以及嵌套循環連接(enable_nestloop)兩種最基本的計劃來強制系統使用一種不同的計劃。 對用戶的查詢使用索引和不用索引的執行進行計時,並且使用EXPLAIN ANALYZE命令來比較結果。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章