點陣圖索引的工作原理 - 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; } } |
相關文章
- 點陣圖索引(轉載)索引
- Python點陣圖索引學習Python索引
- oracle點陣圖索引對DML操作的影響Oracle索引
- 資料庫索引的工作原理資料庫索引
- 點陣圖(bitmap)原理以及實現
- 一文總結分析聚集索引、非聚集索引、覆蓋索引的工作原理!索引
- 點陣圖
- MySQL點陣圖索引解決使用者畫像問題MySql索引
- ClickHouse 留存、路徑、漏斗、session 點陣圖 roaringbitmap 點陣圖最佳化Session
- MySQL點陣圖索引解決使用者畫像問題(簡化建立流程)MySql索引
- Struts2工作原理(圖解)圖解
- 點陣圖字型匯入
- PHP 文字生成點陣圖PHP
- Redis 應用-點陣圖Redis
- 可寫點陣圖(WriteableBitmap)
- 跳槽必看MySQL索引:B+樹原理揭秘與索引優缺點分析MySql索引
- 剖析 Elasticsearch 的索引原理Elasticsearch索引
- TDengine 3.0.2.5 查詢再最佳化!揭秘索引檔案的工作原理索引
- VC 點陣圖按鈕CBitmapButton的使用
- hash join構建點陣圖的理解
- 淺析InnoDB引擎的索引和索引原理索引
- 洗掃車工作原理,效能特點
- PHP掃描圖片轉點陣 二維碼轉點陣PHP
- 圖文詳解 HDFS 的工作機制及其原理
- 用三張圖理解深度學習的工作原理深度學習
- 點陣圖與ERP場景
- Android Bitmap(點陣圖)詳解Android
- 演算法-點陣圖排序演算法排序
- MySQL索引原理MySql索引
- elasticsearch索引原理Elasticsearch索引
- MySQL的索引原理及使用MySql索引
- mysql 索引的原理(超細)MySql索引
- 簡單易懂的索引原理索引
- 尋找陣列的中心索引陣列索引
- 代理模式+react+ 圖片佔點陣圖模式React
- 圖解WebGL和Three.js工作原理圖解WebJS
- Keepalived高可用叢集工作原理示意圖
- MySql 三大知識點,索引、鎖、事務,原理分析MySql索引