閱讀901 返回首頁    go 技術社區[雲棲]


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那麼好的性能。

pic

然而,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)。

《數據庫界的華山論劍 tpc.org》

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的數據增量,對增量進行統計,生成報表。

pic

從這組數據來看,日增量1TB的場景中,僅僅使用現有特性,PG已可以應付其OLAP需求。

2、另外,在相同主機上,測了一組deepgreen的性能,1TB TPC-H跑完約1小時。(deepgreen是一個完全兼容Greenplum的MPP數據庫,在列存儲、SQL優化器、JIT、向量計算方麵有大幅增強)。

pic

deepgreen tpch explain result

為什麼要測deepgreen?前麵說了在OLAP性能方麵,Greenplum已經遠超Oracle。而Deepgreen的性能已在Greenplum之上。我們可以將deepgreen作為一個標杆(DP實際上也是基於PG開發的MPP版本),PostgreSQL將來在經過增強後OLAP方麵有可能達到甚至超過DP的性能。

如果PostgreSQL能達到DP的水平,超過Oracle自然沒問題(沒有對比就沒有傷害,讀者可以試試同樣數據量的Oracle性能)。

pic

(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的向量計算。

已支持的向量計算類型如下

pic

下麵是一組使用向量化技術後的性能提升數據。

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)  

VOPS guide

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

pic

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架構。

未來的發展方向

《數據庫的未來 - HTAP,軟件、硬件、雲生態的融合》

小結

現在已經不是商業數據庫的天下,越來越多的開源產品在崛起,正在從穩定性、性能、功能各個方麵包圍商業產品,PG 10是一個非常典型的代表。

PG 10 會扛起100TB,日增量1TB 級別這個市場的OLTP+OLAP混合場景HTAP的大旗,值得期待。

而在雲上,用戶不需要擔心運維、高可用、備份、擴容、遷移、診斷、監控等問題,用戶隻管用,雲為用戶提供貼身服務。雲上的PG提供了更多的擴展(包括 與對象存儲的無縫結合,內核的優化,增值服務,類RAC架構(越來越多的廠商會跟進aurora形態)等)。

pic

如果你不想用雲服務,沒有關係,在不改內核的情況下,你依舊可以使用目前社區版本提供的這些特性,來滿足你的需求(包括流計算、HLL、讀寫分離、JIT、向量計算、列存儲等)。

參考

《數據庫界的華山論劍 tpc.org》

《數據庫的未來 - HTAP,軟件、硬件、雲生態的融合》

最後更新:2017-07-03 21:32:28

  上一篇:go  優惠券!阿裏雲幸運券免費領取,幫助站長降低建站服務器成本
  下一篇:go  偽列應用 - 數據轉存和下推