點陣圖索引的工作原理 - Richard
點陣圖索引用於各種資料技術以實現高效的查詢處理。在高層次上,點陣圖索引可以被認為是一組謂詞在資料集上的物理具體化,它自然是列式的,特別適合多維布林查詢處理。 當有多個屬性受查詢約束時(例如在複合 where 子句中),PostgreSQL 會根據查詢謂詞動態實現點陣圖索引。ElasticSearch 和 Solr 中的過濾器快取 被實現為文件 ID 上過濾器謂詞的點陣圖索引。Pilosa是一個用 Go 構建的分散式點陣圖索引查詢引擎,帶有一個 Java 客戶端庫。
點陣圖索引不是一刀切的資料結構,在退化的情況下,它會佔用比資料本身更多的空間;在主鍵上使用點陣圖索引來支援 B 樹變體應該被視為濫用。存在各種風格的點陣圖實現,但新興的事實上的標準是 由Daniel Lemire領導的RoaringBitmap。
樸素點陣圖索引
讓我們構建一個簡單的未壓縮點陣圖索引。假設您有一個資料集和某種從現在開始為每條記錄分配整數索引或記錄索引的方法(最簡單的例子是 CSV 檔案中的行號),並且已經選擇了一些要索引的屬性。對於資料的每個索引屬性的每個不同值,計算與謂詞匹配的記錄索引集。對於每個屬性,建立從屬性值到相應記錄索引集的對映。
用於集合的格式尚不重要,但要麼是int[] 要麼BitSet 根據資料和謂詞的屬性(例如,資料集的基數、資料集的排序順序、與謂詞匹配的記錄的基數)都將是合適的。
下表展示了資料結構。第一個表代表一個簡單的資料集。
Record Indices |
Country Sector 0 GB Financials 1 DE Manufacturing 2 FR Agriculturals 3 FR Financials 4 GB Energies |
第二個和第三個表代表資料集上的點陣圖索引,索引Country 和Sector屬性。
Country :
Record Indices Bitmap GB 0,4 0b10001 DE 1 0b10 FR 2,3 0b1100 |
Sector:
Record Indices Bitmap Financials 0,3 0b1001 Manufacturing 1 0b10 Agriculturals 2 0b100 Energies 4 0b10000 |
值得注意的是上表中的三種模式。
- 一個屬性的點陣圖數量是該屬性的不同計數。
- 通常有零或一的執行,這些執行的長度取決於記錄索引屬性的排序順序。
- 記錄索引屬性本身上的點陣圖索引將與資料本身一樣大,並且表示形式要少得多。點陣圖索引不與 B 樹索引競爭主鍵屬性。
這種簡單的方案有效地將謂詞對資料的結果具體化,並且特別有吸引力,因為可以通過對點陣圖執行有效的邏輯操作來組合這些謂詞。當點陣圖的數量和每個點陣圖的大小都儘可能小時,查詢評估是最有效的。無論點陣圖大小如何,高效的查詢計劃都會盡可能少地接觸點陣圖。
無論點陣圖大小如何,高效的查詢計劃都會盡可能少地接觸點陣圖。以下是一些查詢示例及其評估計劃。
- 單屬性聯合
select * from records where country = "GB" or country = "FR" |
- 訪問國家索引,讀取值“FR”和“GB”的點陣圖。
- 應用按位邏輯 OR 以獲取新點陣圖。
- 使用檢索到的索引訪問由記錄 id 儲存的資料。
- 多屬性交集
select * from records where country = "GB" and sector = "Energies" |
- 訪問國家索引,並讀取值“GB”的點陣圖。
- 訪問扇區索引,並讀取值“能源”的點陣圖。
- 應用按位邏輯 AND 以獲取新點陣圖。
- 使用檢索到的索引訪問由記錄 id 儲存的資料。
....
壓縮
到目前為止提出的方案可作為玩具模型使用,但點陣圖太大而無法實用。單個屬性上的點陣圖索引在m由n記錄組成的資料集上具有不同的值,使用 一個BitSet將消耗mn位,使用 一個int[]將消耗32mn位。因此,需要某種壓縮才能使該方法可行。
RoaringBitmap 是一種動態資料結構,旨在成為適用於所有場景的通用解決方案。
RoaringBitmap 應該被認為是一組無符號整數,由覆蓋不相交子集的容器組成。每個子集可以包含大小範圍為 2^16 的值,並且該子集由 16 位鍵索引。這意味著在最壞的情況下,它只需要 16 位來表示一個 32 位值,因此無符號 32 位整數可以儲存為 Java shorts。容器大小的選擇也意味著在最壞的情況下,容器仍將適合現代處理器的 L1 快取。
下面是範圍編碼位片索引的實現,作為如何使用 RoaringBitmaps 的示例。
public class RangeEncodedOptBitSliceIndex implements RoaringIndex { private final int[] basis; private final int[] cumulativeBasis; private final RoaringBitmap[][] bitslice; public RangeEncodedOptBitSliceIndex(ProjectionIndex projectionIndex, int[] basis) { this.basis = basis; this.cumulativeBasis = accumulateBasis(basis); this.bitslice = BitSlices.createRangeEncodedBitSlice(projectionIndex, basis); } @Override public RoaringBitmap whereEqual(int code, RoaringBitmap existence) { RoaringBitmap result = existence.clone(); int[] expansion = expand(code, cumulativeBasis); for(int i = 0; i < cumulativeBasis.length; ++i) { int component = expansion[i]; if(component == 0) { result.and(bitslice[i][0]); } else if(component == basis[i] - 1) { result.andNot(bitslice[i][basis[i] - 2]); } else { result.and(FastAggregation.xor(bitslice[i][component], bitslice[i][component - 1])); } } return result; } @Override public RoaringBitmap whereNotEqual(int code, RoaringBitmap existence) { RoaringBitmap inequality = existence.clone(); inequality.andNot(whereEqual(code, existence)); return inequality; } @Override public RoaringBitmap whereLessThan(int code, RoaringBitmap existence) { return whereLessThanOrEqual(code - 1, existence); } @Override public RoaringBitmap whereLessThanOrEqual(int code, RoaringBitmap existence) { final int[] expansion = expand(code, cumulativeBasis); final int firstIndex = cumulativeBasis.length - 1; int component = expansion[firstIndex]; int threshold = basis[firstIndex] - 1; RoaringBitmap result = component < threshold ? bitslice[firstIndex][component].clone() : existence.clone(); for(int i = firstIndex - 1; i >= 0; --i) { component = expansion[i]; threshold = basis[i] - 1; if(component != threshold) { result.and(bitslice[i][component]); } if(component != 0) { result.or(bitslice[i][component - 1]); } } return result; } @Override public RoaringBitmap whereGreaterThan(int code, RoaringBitmap existence) { RoaringBitmap result = existence.clone(); result.andNot(whereLessThanOrEqual(code, existence)); return result; } @Override public RoaringBitmap whereGreaterThanOrEqual(int code, RoaringBitmap existence) { RoaringBitmap result = existence.clone(); result.andNot(whereLessThan(code, existence)); return result; } } |
相關文章
- 點陣圖索引:原理(BitMap index)索引Index
- Oracle索引——點陣圖索引Oracle索引
- 點陣圖索引(Bitmap Index)——從B*樹索引到點陣圖索引索引Index
- 點陣圖索引.sql索引SQL
- 點陣圖索引(Bitmap Index)——索引共用索引Index
- 點陣圖索引(Bitmap Index)——點陣圖索引與資料DML鎖定索引Index
- Oracle-點陣圖索引Oracle索引
- 【點陣圖索引】在點陣圖索引列上進行更新操作的鎖代價研究索引
- 【基礎知識】索引--點陣圖索引索引
- oracle 點陣圖索引(bitmap index)Oracle索引Index
- 點陣圖索引(bitmap-index)索引Index
- B樹索引和點陣圖索引的結構介紹索引
- Python點陣圖索引學習Python索引
- bitmap index點陣圖索引系列(一)Index索引
- 【索引】Bitmap點陣圖索引與普通的B-Tree索引鎖的比較索引
- MySQL:索引工作原理MySql索引
- oracle點陣圖索引對DML操作的影響Oracle索引
- 點陣圖(bitmap)原理以及實現
- ORACLE 索引專家:Richard FooteOracle索引
- 資料庫索引的工作原理資料庫索引
- B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究索引
- 關於ORACLE點陣圖索引內部淺論Oracle索引
- zt_深入理解bitmap index點陣圖索引Index索引
- 使用點陣圖連線索引優化OLAP查詢索引優化
- 【Bitmap Index】B-Tree索引與Bitmap點陣圖索引的鎖代價比較研究Index索引
- 點陣圖索引導致的會話阻塞問題(p7)索引會話
- 使用點陣圖連線索引最佳化OLAP查詢索引
- 點陣圖
- 你知道資料庫索引的工作原理嗎?資料庫索引
- 關於點陣圖索引的split及bitmap to rowid實現問題索引
- MySQL點陣圖索引解決使用者畫像問題MySql索引
- 使用點陣圖索引和星形轉換優化OLAP查詢索引優化
- 使用點陣圖選單項——建立點陣圖 (轉)
- 一文總結分析聚集索引、非聚集索引、覆蓋索引的工作原理!索引
- 點陣圖排序排序
- 【筆記】Oracle B-tree、點陣圖、全文索引三大索引效能比較及優缺點彙總筆記Oracle索引
- 使用點陣圖選單項——點陣圖選單項例項 (轉)
- Struts2工作原理(圖解)圖解