901
技術社區[雲棲]
100TB級, 日增量1TB, OLTP OLAP混合場景數據庫設計方向
標簽
PostgreSQL , LLVM , JIT , 並行 , 列存儲 , GPU
背景
總量100TB,日增量1TB左右。這樣的體量應該可以覆蓋目前絕大多數企業的數據庫體量。
提到100TB級別,OLTP和OLAP的混合場景,大家可能會想到Oracle的一體機extradata,沒錯Oracle在這方麵做得確實是非常棒的,但是價格也是很漂亮的。
Oracle主要通過幾個方麵來提升它在這個級別的性能:
共享存儲+RAC架構,同時提升OLTP和OLAP的擴展能力,(OLTP:多個業務可以分配到多個主機上,但是需要注意數據庫維護緩存一致性帶來的性能下降問題,所以通常不同的主機訪問不同的數據塊是較好的設計),(OLAP:同一條SQL可以使用單機CPU多核甚至多個主機的CPU計算能力)。
列存儲,提升OLAP的性能。
內部使用IB互聯,解決了網絡瓶頸的問題。
在單純的OLAP數據庫方麵,代表作有Greenplum, TeraData, AsterData等MPP數據庫,比如GPDB就可以利用廉價的x86達到及其好的AP性能,我記得很多年前用6台4萬左右的x86搭建的GPDB集群,以性能逾10倍多的差異幹掉了2台IBM p570頂配的Oracle RAC。
回到主題,開源界有沒有應對OLTP+OLAP場景的數據庫呢?
大多數開源數據庫選擇了分而治之(sharding)的路線,因為大多數開源數據庫單機做不到像Oracle那麼好的性能。
然而,sharding要做到體驗和單機一樣是非常困難的,包括分布式事務,全局一致性,全局時間點恢複,跨節點JOIN,節點間數據交換,數據重分布,擴容,窗口查詢,聚合下推等都是巨大的調整。目前還沒有哪個sharding技術敢說體驗和單機一樣,(通常sharding為了實現的便利,會閹割掉大量單機下麵的功能)。
其二,要支持OLAP其實僅僅sharding是不夠的,還有大量的SQL兼容性的工作(例如多維分析、多表JOIN、窗口查詢、遞歸查詢、科學計算等等)。
個人認為目前體驗做得最好的sharding應該屬Greenplum了,但是也僅僅局限在純OLAP方麵。
開源數據庫如果不走sharding路線,能穩定的扛住100TB+, 日增量1TB的OLTP OLAP混合場景嗎?
PostgreSQL 100TB+, 日增量1TB的OLTP OLAP混合場景數據庫設計
從單機聊起
以10萬左右的 32Core + SSD 單機為例,聊一下單機能做到什麼樣的性能。
單機OLTP性能如何? TPC-C
tpc-c是OLTP的工業測試標準之一,商業數據庫,硬件廠商大都會用TPC-C的測試結果來彰顯自己的性能。
PostgreSQL TPC-C在單機的一組測試數據(warehouses=3000, terminals=256)。
08:54:57,345 [main] INFO jTPCC : Term-00,
08:54:57,348 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
08:54:57,348 [main] INFO jTPCC : Term-00, BenchmarkSQL v5.0
08:54:57,348 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
08:54:57,348 [main] INFO jTPCC : Term-00, (c) 2003, Raul Barbosa
08:54:57,349 [main] INFO jTPCC : Term-00, (c) 2004-2016, Denis Lussier
08:54:57,350 [main] INFO jTPCC : Term-00, (c) 2016, Jan Wieck
08:54:57,351 [main] INFO jTPCC : Term-00, +-------------------------------------------------------------+
08:54:57,351 [main] INFO jTPCC : Term-00,
08:54:57,351 [main] INFO jTPCC : Term-00, db=postgres
08:54:57,351 [main] INFO jTPCC : Term-00, driver=org.postgresql.Driver
08:54:57,351 [main] INFO jTPCC : Term-00, conn=jdbc:postgresql://xxx.xxx.xxx.xxx:1921/db0
08:54:57,351 [main] INFO jTPCC : Term-00, user=benchmarksql
08:54:57,351 [main] INFO jTPCC : Term-00,
08:54:57,351 [main] INFO jTPCC : Term-00, warehouses=3000
08:54:57,351 [main] INFO jTPCC : Term-00, terminals=256
08:54:57,353 [main] INFO jTPCC : Term-00, runMins=30
08:54:57,353 [main] INFO jTPCC : Term-00, limitTxnsPerMin=0
08:54:57,353 [main] INFO jTPCC : Term-00, terminalWarehouseFixed=false
08:54:57,354 [main] INFO jTPCC : Term-00,
08:54:57,354 [main] INFO jTPCC : Term-00, newOrderWeight=45
08:54:57,354 [main] INFO jTPCC : Term-00, paymentWeight=43
08:54:57,354 [main] INFO jTPCC : Term-00, orderStatusWeight=4
08:54:57,354 [main] INFO jTPCC : Term-00, deliveryWeight=4
08:54:57,354 [main] INFO jTPCC : Term-00, stockLevelWeight=4
08:54:57,354 [main] INFO jTPCC : Term-00,
08:54:57,354 [main] INFO jTPCC : Term-00, resultDirectory=null
08:54:57,354 [main] INFO jTPCC : Term-00, osCollectorScript=null
08:54:57,355 [main] INFO jTPCC : Term-00,
08:54:57,439 [main] INFO jTPCC : Term-00, C value for C_LAST during load: 223
08:54:57,440 [main] INFO jTPCC : Term-00, C value for C_LAST this run: 138
08:54:57,440 [main] INFO jTPCC : Term-00,
09:24:58,011 [Thread-46] INFO jTPCC : Term-00,
09:24:58,012 [Thread-46] INFO jTPCC : Term-00,
09:24:58,012 [Thread-46] INFO jTPCC : Term-00, Measured tpmC (NewOrders) = 380234.68
09:24:58,012 [Thread-46] INFO jTPCC : Term-00, Measured tpmTOTAL = 844858.82
09:24:58,012 [Thread-46] INFO jTPCC : Term-00, Session Start = 2017-01-27 08:54:57
09:24:58,012 [Thread-46] INFO jTPCC : Term-00, Session End = 2017-01-27 09:24:58
09:24:58,012 [Thread-46] INFO jTPCC : Term-00, Transaction Count = 25346862
PostgreSQL的優化器完備(例如成熟的CBO體係,豐富的NODE運算方法等),在線事務處理能力方麵,性能卓越。
AGG_HASHED:
AGG_MIXED:
AGG_PLAIN:
AGG_SORTED:
JOIN_ANTI:
JOIN_FULL:
JOIN_INNER:
JOIN_LEFT:
JOIN_RIGHT:
JOIN_SEMI:
T_Agg:
T_Append:
T_BitmapAnd:
T_BitmapHeapScan:
T_BitmapIndexScan:
T_BitmapOr:
T_CteScan:
T_CustomScan:
T_ForeignScan:
T_FunctionScan:
T_Gather:
T_GatherMerge:
T_Group:
T_Hash:
T_HashJoin:
T_IndexOnlyScan:
T_IndexScan:
T_Limit:
T_LockRows:
T_Material:
T_MergeAppend:
T_MergeJoin:
T_ModifyTable:
T_NamedTuplestoreScan:
T_NestLoop:
T_ProjectSet:
T_RecursiveUnion:
T_Result:
T_SampleScan:
T_SeqScan:
T_SetOp:
T_Sort:
T_SubqueryScan:
T_TableFuncScan:
T_TidScan:
T_Unique:
T_ValuesScan:
T_WindowAgg:
T_WorkTableScan:
單機OLAP性能如何? TPC-H
tpc-h是OLA的工業測試標準之一,有大量的JOIN,GROUP等大運算量的操作。大多數的商業AP數據庫會以tpc-h測試結果來彰顯自己的性能。
測試使用這個github: https://github.com/digoal/gp_tpch
1、PostgreSQL 10 1TB TPC-H在單機的一組測試數據(SF=1000,即1TB的量)。
這組測試非常具有代表意義,例如用戶每天新增1TB的數據增量,對增量進行統計,生成報表。
從這組數據來看,日增量1TB的場景中,僅僅使用現有特性,PG已可以應付其OLAP需求。
2、另外,在相同主機上,測了一組deepgreen的性能,1TB TPC-H跑完約1小時。(deepgreen是一個完全兼容Greenplum的MPP數據庫,在列存儲、SQL優化器、JIT、向量計算方麵有大幅增強)。
為什麼要測deepgreen?前麵說了在OLAP性能方麵,Greenplum已經遠超Oracle。而Deepgreen的性能已在Greenplum之上。我們可以將deepgreen作為一個標杆(DP實際上也是基於PG開發的MPP版本),PostgreSQL將來在經過增強後OLAP方麵有可能達到甚至超過DP的性能。
如果PostgreSQL能達到DP的水平,超過Oracle自然沒問題(沒有對比就沒有傷害,讀者可以試試同樣數據量的Oracle性能)。
(PostgreSQL 10目前僅使用了JIT、多核並行、OP複用、分區表、哈希聚合、哈希分組 等若幹對OLAP場景有較大性能提升的技術手段,還有列存儲、向量計算、appendscan並行等手段可以使用,預計至少還有10倍左右的性能提升空間。)
100TB+, 日增量超過1TB後 - PostgreSQL 黑科技
除了PG 10已經具備的 JIT,多核並行、OP複用、分區表、哈希聚合、哈希分組,等OLAP場景黑科技,PostgreSQL還有哪些黑科技可用來大幅提升單機OLAP場景的性能?
1、JIT
LLVM增強,目前PG 10已整合了JIT框架,但是要支持更多的算子。
2、向量化
目前有一個PG插件,可以實現PG的向量計算。
已支持的向量計算類型如下
下麵是一組使用向量化技術後的性能提升數據。
postgres=# \d customer
Unlogged table "public.customer"
Column | Type | Collation | Nullable | Default
--------------+------------------------+-----------+----------+---------------------------------------------
c_custkey | bigint | | not null | nextval('customer_c_custkey_seq'::regclass)
c_name | character varying(25) | | |
c_address | character varying(40) | | |
c_nationkey | bigint | | not null |
c_phone | character(15) | | |
c_acctbal | double precision | | |
c_mktsegment | character(10) | | |
c_comment | character varying(117) | | |
postgres=# create unlogged table vops_customer (c_custkey vops_int8, c_nationkey vops_int8, c_acctbal vops_float8);
CREATE TABLE
postgres=# select populate(destination := 'vops_customer', source := 'customer');
populate
-----------
150000000
(1 row)
postgres=# create unlogged table c as select c_custkey,c_nationkey,c_acctbal from customer;
SELECT 150000000
測試時確保數據均在shared buffer中.
使用向量化前,56秒。
postgres=# select sum(c_custkey),avg(c_custkey),min(c_custkey),max(c_custkey),sum(c_nationkey),avg(c_nationkey),min(c_nationkey),max(c_nationkey),sum(c_acctbal),min(c_acctbal),max(c_acctbal),avg(c_acctbal),count(*) from c;
sum | avg | min | max | sum | avg | min | max | sum | min | max | avg | count
-------------------+-----------------------+-----+-----------+------------+---------------------+-----+-----+-----------------+---------+---------+------------------+-----------
11250000075000000 | 75000000.500000000000 | 1 | 150000000 | 1800117761 | 12.0007850733333333 | 0 | 24 | 675048124067.72 | -999.99 | 9999.99 | 4500.32082711813 | 150000000
(1 row)
Time: 55972.494 ms (00:55.972)
postgres=# explain (analyze,verbose,timing,costs,buffers) select sum(c_custkey),avg(c_custkey),min(c_custkey),max(c_custkey),sum(c_nationkey),avg(c_nationkey),min(c_nationkey),max(c_nationkey),sum(c_acctbal),min(c_acctbal),max(c_acctbal),avg(c_acctbal),count(*) from c;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=7330421.81..7330421.82 rows=1 width=200) (actual time=57319.855..57319.855 rows=1 loops=1)
Output: sum(c_custkey), avg(c_custkey), min(c_custkey), max(c_custkey), sum(c_nationkey), avg(c_nationkey), min(c_nationkey), max(c_nationkey), sum(c_acctbal), min(c_acctbal), max(c_acctbal), avg(c_acctbal), count(*)
Buffers: shared hit=955415
-> Seq Scan on public.c (cost=0.00..2455416.60 rows=150000160 width=24) (actual time=0.012..14185.622 rows=150000000 loops=1)
Output: c_custkey, c_nationkey, c_acctbal
Buffers: shared hit=955415
Planning time: 0.068 ms
Execution time: 57319.926 ms
(8 rows)
Time: 57320.443 ms (00:57.320)
使用向量化後,10秒。
postgres=# select sum(c_custkey),avg(c_custkey),min(c_custkey),max(c_custkey),sum(c_nationkey),avg(c_nationkey),min(c_nationkey),max(c_nationkey),sum(c_acctbal),min(c_acctbal),max(c_acctbal),avg(c_acctbal),countall(*) from vops_customer;
sum | avg | min | max | sum | avg | min | max | sum | min | max | avg | countall
-------------------+------------------+-----+-----------+------------+------------------+-----+-----+-----------------+---------+---------+------------------+-----------
11250000075000000 | 75000000.4473924 | 1 | 150000000 | 1800117761 | 12.0007850733333 | 0 | 24 | 675048124067.72 | -999.99 | 9999.99 | 4500.32082711813 | 150000000
(1 row)
Time: 9785.634 ms (00:09.786)
postgres=# explain (analyze,verbose,timing,costs,buffers) select sum(c_custkey),avg(c_custkey),min(c_custkey),max(c_custkey),sum(c_nationkey),avg(c_nationkey),min(c_nationkey),max(c_nationkey),sum(c_acctbal),min(c_acctbal),max(c_acctbal),avg(c_acctbal),countall(*) from vops_customer;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=568359.38..568359.39 rows=1 width=104) (actual time=9707.393..9707.393 rows=1 loops=1)
Output: sum(c_custkey), avg(c_custkey), min(c_custkey), max(c_custkey), sum(c_nationkey), avg(c_nationkey), min(c_nationkey), max(c_nationkey), sum(c_acctbal), min(c_acctbal), max(c_acctbal), avg(c_acctbal), countall(*)
Buffers: shared hit=468750
-> Seq Scan on public.vops_customer (cost=0.00..492187.50 rows=2343750 width=1584) (actual time=0.008..842.816 rows=2343750 loops=1)
Output: c_custkey, c_nationkey, c_acctbal
Buffers: shared hit=468750
Planning time: 0.073 ms
Execution time: 9707.461 ms
(8 rows)
Time: 9709.400 ms (00:09.709)
提升了N倍性能。
使用向量化除了性能本身的提升,還可以更好的壓縮數據。
非向量化存儲
postgres=# \dt+ c
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+----------+---------+-------------
public | c | table | postgres | 7464 MB |
(1 row)
向量化存儲
postgres=# \dt+ vops_customer
List of relations
Schema | Name | Type | Owner | Size | Description
--------+---------------+-------+----------+---------+-------------
public | vops_customer | table | postgres | 3663 MB |
(1 row)
3、多核並行
目前PG已支持大多數NODE的多核並行,例如SEQ SCAN,INDEX SCAN,HASH AGG,SORT等。將來會支持更多的NODE。
比如將要支持 APPEND 並行,那麼多個分區表可以並行掃描,理論上這個FEATURE加上後,性能和開源版本Greenplum應該可以對齊。
4、列存儲
目前PG內置的是行存儲,要支持列存儲,可以安裝列存儲插件,例如IMCS插件,CSTORE插件。
使用列存儲,可以提升數據壓縮比,同時降低列統計時的數據掃描量和deform開銷,提升列統計性能,以及更好的支持向量計算(目前VOPS向量計算通過新增數據類型,批量瓦片式存儲來實現,比較別扭)等。
列存插件如下:
https://github.com/knizhnik/imcs
https://github.com/citusdata/cstore_fdw
期待未來的PG版本可以支持列存儲。
5、hll
通過hhl插件,可以支持一些估值統計的問題,在用戶允許一些誤差的情況下,高效率的實現實時的PV,UV等查詢需求。例如實時查詢APP的uv TOP 10。
hll的插件如下:
https://github.com/citusdata/cstore_fdw
6、GPU
CPU的計算能力有限,通過GPU可以大幅提升OLAP的性能。pg-strom是一個利用PostgreSQL scan api和GPU實現的OLAP加速插件。
https://github.com/pg-strom/devel
JOIN幾十張大表毫無壓力。
7、讀寫分離
通過流複製,可以創建PostgreSQL的備庫,WAL延遲接近於0。提升數據庫集群整體的處理能力。
8、流計算
pipelinedb是基於PostgreSQL開發的一個流計算數據庫,正在進行插件化,將來可以作為插件安裝到PostgreSQL數據庫中。
使用流計算,可以將大量的計算任務分攤到全天,從而減少集中計算的運力需求。集中計算就好像春節放假,大量的人群流動。而流計算就好比城鎮化崛起,大家都不外出打工,都在家附近發展,杜絕了節假日的大遷徙。
《流計算風雲再起 - PostgreSQL攜PipelineDB力挺IoT》
9、冷熱存儲分離
阿裏雲的RDS PG與雲對象存儲OSS無縫結合,實現了數據的分層存儲。
https://help.aliyun.com/document_detail/44461.html
存放於OSS的數據,通過OSS_FDW插件,使用外部表進行訪問,用戶訪問PG外部表和訪問本地表的SQL語法完全一樣,無需修改應用。
存放於OSS的數據,用戶不需要對其進行備份因為OSS本身就是多副本存儲。從而減輕了數據庫備份的開銷和成本。
使用OSS,PG實際上相當於實現了無限容量的存儲,拓展了單個數據庫的存儲邊界。
存放於OSS的數據,不僅可以給一個PG實例使用,同時還可以給多個實例同時使用,例如可以創建一個RDS實例,對接OSS上的數據,分析師就可以在上麵進行分析而不需要消耗在線數據庫的資源。
10、類rac架構
這個架構最早由亞馬遜Aurora提出,目前已經推出了PG的Aurora版本。
和Oracle RAC一樣,都使用共享存儲的架構,差別僅僅在於一寫多讀,Oracle是多寫多讀。
存儲為多副本的設計,可以實現跨可用區的多副本一致性,從而解決了HA、容災層麵的問題,使用一寫多讀,還解決了讀性能擴展的問題。
結合PostgreSQL本身的功能、性能等特性,aurora架構讓PG可以覆蓋更多的企業場景。
相信會有更多的公司會跟進這樣的架構。
11、mpp或sharding
不推薦sharding,因為要犧牲一些功能層麵的特性。但是不妨礙社區為了某些特定場景而推出的一些sharding插件。
例如citus插件,自帶節點間數據傳輸,JOIN,透明的數據重分布功能。可以很好的支撐OLAP的橫向擴展能力。
https://github.com/citusdata/citus
例如TP方麵的sharding,基於fdw的sharding,可以解決TP的橫向擴展需求。
《PostgreSQL 10.0 preview sharding增強 - 支持分布式事務》
《PostgreSQL 10.0 preview sharding增強 - pushdown 增強》
《PostgreSQL 10.0 preview sharding增強 - 支持Append節點並行》
《PostgreSQL 10.0 preview sharding增強 - postgres_fdw 多節點異步並行執行》
《PostgreSQL 9.6 sharding based on FDW & pg_pathman》
《PostgreSQL 9.6 sharding + 單元化 (based on postgres_fdw) 最佳實踐 - 通用水平分庫場景設計與實踐》
《PostgreSQL 9.6 單元化,sharding (based on postgres_fdw) - 內核層支持前傳》
12、OLAP SQL兼容性
PostgreSQL在OLAP SQL兼容性方麵的支持是非常完備的,包括多維分析(grouping sets,cube,rollup,grouping等),遞歸查詢,窗口查詢,多表JOIN,科學計算,機器學習函數 等等。
PostgreSQL vs Oracle 架構對比
比Oracle強的點
開源軟件強大之處在於發展非常的迅速,非常的開放。同時PostgreSQL這個產品本身的開源許可、設計很契合開發者,開放了大量的可擴展接口,因此我們可以看到PostgreSQL生態中有特別多的插件,滿足各種場景的需求。
相比Oracle,PG有哪些優勢?
1、雲生態融合,例如OSS_FDW,就是一個數據庫和對象存儲融合的例子。
2、軟件生態融合,例如PL語言,用戶可以通過plpython, plR, plCUDA等語言開發存儲過程,融合開發者的軟件生態。
3、硬件生態融合,例如與GPU結合,讓PG擁有更加強大的計算能力。
4、可擴展,通過開放的數據、索引、掃描、操作符、UDF等接口,可以支持更多的用戶場景。
比如圖像特征值的存儲和搜索,通過擴展就能支持,imgsmlr這個插件就是一個代表。
比如基因數據的存儲和搜索,通過擴展就能支持,PostBIS這個插件就是一個代表。
比如化學數據的存儲和搜索,rdkit。
機器學習插件,madlib。
GIS插件,PostGIS。
時序數據插件,timescaledb。
hll估值插件。
5、流計算,通過pipelineDB,可以實現流式計算。
6、MPP,通過citus插件,可以實現MPP,多機並行計算。
7、llvm, 向量計算等優化手段,在OLAP方麵有非常大的性能提升。
需要向Oracle學習的點
類RAC架構。
未來的發展方向
小結
現在已經不是商業數據庫的天下,越來越多的開源產品在崛起,正在從穩定性、性能、功能各個方麵包圍商業產品,PG 10是一個非常典型的代表。
PG 10 會扛起100TB,日增量1TB 級別這個市場的OLTP+OLAP混合場景HTAP的大旗,值得期待。
而在雲上,用戶不需要擔心運維、高可用、備份、擴容、遷移、診斷、監控等問題,用戶隻管用,雲為用戶提供貼身服務。雲上的PG提供了更多的擴展(包括 與對象存儲的無縫結合,內核的優化,增值服務,類RAC架構(越來越多的廠商會跟進aurora形態)等)。
如果你不想用雲服務,沒有關係,在不改內核的情況下,你依舊可以使用目前社區版本提供的這些特性,來滿足你的需求(包括流計算、HLL、讀寫分離、JIT、向量計算、列存儲等)。
參考
最後更新:2017-07-03 21:32:28