PostgreSQL向量計算插件——vops

在主流的OLTP數據庫中,PostgreSQL可以說是十分優秀了。同時在OLAP領域,pg的表現也是越來越好,例如支持並行計算,JIT編譯等等。同時pg還有許多優秀的插件,例如列存插件、LLVM插件。這些使得pg具備了一定的OLAP能力,在OLAP領域,最常用的加速手段可以說就是列存儲了,雖然目前原生的pg尚不支持列存,但是我們仍然有其它方法來加速OLAP查詢,例如向量化計算。
vops插件中新增了瓦片式數據類型,而瓦片本身支持向量計算。向量計算的本質是一次計算多個值,減少函數調用,上下文切換,儘量的利用CPU的緩存以及向量化執行指令提高性能。
新增的瓦片式類型,對應的還新增了對應的向量化執行操作符,所以使用VOPS和正常的使用SQL語法是一樣的。

使用VOPS,總共分三步:

  1. 創建基礎表的VOPS表(使用對應的瓦片類型)。
  2. 調用VOPS提供的轉換函數,將基礎表的數據轉移到VOPS表(即轉換、規整爲瓦片存儲的過程)。
  3. 使用正常的SQL,訪問VOPS表即可,但是需要注意,使用VOPS提供的操作符哦。

例子:
–創建普通表

bill=# create table t(c1 int,c2 int);
CREATE TABLE

–創建vops表

bill=# create table t_vops(c1 vops_int4,c2 vops_int4);
CREATE TABLE

–向表t中插入數據

bill=# insert into t select random()*100,random()*1000 from generate_series(1,10000000);
INSERT 0 10000000

–將普通表中的數據轉換到vops表中

bill=# select populate('t_vops'::regclass, 't'::regclass);      
 populate 
----------
 10000000
(1 row)

這裏我們用到了VOPS提供的populate函數,完成普通表數據轉換的動作。

populate(destination regclass,  
         source regclass,  
         predicate cstring default null,  
         sort cstring default null);  

populate函數中前兩個參數是強制參數,第一個表示VOPS表的regclass,第二個是原始表的regclass。
predicate參數用於合併數據,將最近接收的數據合併到已有數據的VOPS表。
sort是告訴populate,按什麼字段排序,前面講索引時有講到爲什麼需要排序,就是要線性相關性,好創建first, last的brin索引。

查詢測試:
做個簡單的全表掃描測試:
可以看到使用向量化的數據查詢性能大幅度提升!

bill=# explain analyze select * from t;
                                                   QUERY PLAN                                                   
----------------------------------------------------------------------------------------------------------------
 Seq Scan on t  (cost=0.00..144248.48 rows=10000048 width=8) (actual time=0.012..849.135 rows=10000000 loops=1)
 Planning Time: 0.043 ms
 Execution Time: 1329.869 ms
(3 rows)

bill=# explain analyze select * from t_vops;
                                                   QUERY PLAN                                                    
-----------------------------------------------------------------------------------------------------------------
 Seq Scan on t_vops  (cost=0.00..12723.50 rows=156250 width=544) (actual time=0.005..19.654 rows=156250 loops=1)
 Planning Time: 0.099 ms
 Execution Time: 27.175 ms
(3 rows)

不過這種向量化數據不好的地方就是,我們在表中查詢的數據都是向量化的,例如下面這樣:

bill=# select * from t_vops limit 1;
                                                                                              c1                                                                                              |         
                                                                                                                 c2                                                                                     
                                      
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------
 {98,100,75,53,27,60,15,50,41,96,50,84,75,14,50,83,77,7,92,91,14,86,14,17,48,42,59,36,73,18,56,55,98,16,25,27,0,72,73,7,94,72,86,48,89,41,32,45,48,11,24,71,1,8,99,25,87,27,18,74,72,48,7,59} | {706,420
,44,574,443,522,323,977,276,420,540,486,731,996,128,576,137,499,362,785,553,69,642,718,518,546,658,406,482,481,307,21,156,342,906,508,211,209,310,917,2,643,65,79,972,8,598,815,444,230,744,25,317,907,6
57,882,41,686,198,816,862,40,491,145}
(1 row)

所以我們如果想要看到正常的記錄,需要使用unnest函數來轉換。

bill=# select unnest(l.*) from t_vops l limit 5;
  unnest   
-----------
 (98,706)
 (100,420)
 (75,44)
 (53,574)
 (27,443)
(5 rows)

參考鏈接:
https://github.com/postgrespro/vops

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章