gpfdist性能優化介紹

gpfdist外部表,是Greenplum數據庫最重要的數據批量加載技術,有着極高的性能。

先講個故事,我們經歷過很多的POC測試,雖然gpfdist外部表的加載性能一直領先友商,但是,在文件服務器帶寬有限的情況下,我們往往很難取得碾壓性的優勢,尤其是文件服務器只有一根光纖的時候,測試的結果,往往是大家的性能幾乎相同,所以,我在很長一段時間,都在考慮,如何可以突破性能的上限,大概一年前,我就跟我們的技術大牛同事聊這些思考,得到了一個大牛的共鳴,後來我就做了他的產品經理,他開始着手寫一個可以在一定程度上代替gpfdist的命令,後來他的成品命名爲lotus,本文後續的一些測試中,包括文件名和數據庫的名稱都是使用的lotus,就是源於這裏,大牛的命令就叫lotus,我們討論了gpfdist是單進程的服務,所以,大神的第一次入手就開始幹多線程切分文件和分發文件的實現,我們進行了測試,但測試發現,網卡是個更大的性能瓶頸,然後我就給大牛提需求,上ZSTD壓縮,我們還對ZSTD的各個壓縮級別做了測試,最終,我們發現,ZSTD壓縮,可以極大的節省網絡帶寬的開銷,在大神上ZSTD需求期間,我就開始琢磨,我是不是可以改造一下gpfdist的代碼,加入ZSTD壓縮,經過兩三週的學習和努力,最終有了ZSTD改造版的gpfdist,本文不會深入講解如何改造gpfdist的過程,因爲過程崎嶇坎坷,只是介紹大概的優化思想。

關於大牛的命令,可以參見lotus文檔瞭解大牛的神作。 本文的測試場景,大牛的命令可以做到3182 ms完成數據掃描,加載性能爲3320 MB/s。

本文主要探討如何來進行性能的調優。


首先,我們準備了一個測試數據文件:

[gpadmin@smdw ~]$ ll --block-size M /dev/shm/lotus.txt
-rw-r--r--. 1 root root 10567M Jul 27 15:07 /dev/shm/lotus.txt

文件尺寸爲10567MB,爲了確保整個測試過程不受磁盤性能的影響,我們將測試用的數據文件放到內存中,即/dev/shm目錄下。


首先,我們在一個有72個Primary的集羣,創建一個常規的gpfdist外部表,由於GP集羣資源有限,設備比較老,這裏主要是爲了gpfdist的極限性能,所以,只對外部表執行count(*)的操作,不會真正的執行數據入庫的操作。

CREATE READABLE EXTERNAL TABLE ext_test
(
  a text
)
LOCATION ('gpfdist://172.28.8.251:8080/dev/shm/lotus.txt')
FORMAT 'TEXT' (DELIMITER 'OFF');

啓動gpfdist服務,使用簡潔模式,指定了路徑和端口,其他參數保持缺省值:

[root@smdw ~]# . /usr/local/greenplum-db-6.9.0/greenplum_path.sh
[root@smdw ~]# gpfdist -p 8080 -d /../ -s
2020-09-19 12:45:47 7512 INFO Before opening listening sockets - following listening sockets are available:
2020-09-19 12:45:47 7512 INFO IPV6 socket: [::]:8080
2020-09-19 12:45:47 7512 INFO IPV4 socket: 0.0.0.0:8080
2020-09-19 12:45:47 7512 INFO Trying to open listening socket:
2020-09-19 12:45:47 7512 INFO IPV6 socket: [::]:8080
2020-09-19 12:45:47 7512 INFO Opening listening socket succeeded
2020-09-19 12:45:47 7512 INFO Trying to open listening socket:
2020-09-19 12:45:47 7512 INFO IPV4 socket: 0.0.0.0:8080
Serving HTTP on port 8080, directory /

執行外部表的count(*)查詢,爲了準確的評估,我們進行連續3次查詢:

lotus=# SELECT count(*) FROM ext_test;
NOTICE:  External scan from gpfdist(s) server will utilize 64 out of 72 segment databases
  count
----------
 89000000
(1 row)

Time: 9655.308 ms
lotus=# SELECT count(*) FROM ext_test;
NOTICE:  External scan from gpfdist(s) server will utilize 64 out of 72 segment databases
  count
----------
 89000000
(1 row)

Time: 9635.492 ms
lotus=# SELECT count(*) FROM ext_test;
NOTICE:  External scan from gpfdist(s) server will utilize 64 out of 72 segment databases
  count
----------
 89000000
(1 row)

Time: 9633.638 ms

平均耗時爲9641 ms。

┌nmon─16g──────[H for help]───Hostname=smdw─────────Refresh= 2secs ───12:49.07────────────────────────────────────────────────────────────────────────────────────────┐
│ CPU Utilisation ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────               │
│---------------------------+-------------------------------------------------+                                                                                       │
│CPU User%  Sys% Wait%  Idle|0          |25         |50          |75       100|                                                                                       │
│  1   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│  2   0.0   0.6   0.0  99.4| >                                               |                                                                                       │
│  3   0.0   1.0   0.0  99.0|>                                                |                                                                                       │
│  4   0.5   3.6   0.0  95.9|s>                                               |                                                                                       │
│  5   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│  6   0.0   0.5   0.0  99.5|>                                                |                                                                                       │
│  7   0.5   0.5   0.5  98.5|>                                                |                                                                                       │
│  8   1.0  12.1   0.0  86.9|ssssss>                                          |                                                                                       │
│  9   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│ 10   1.0   6.1   0.0  92.9|sss>                                             |                                                                                       │
│ 11   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│ 12   1.0   9.5   0.0  89.4|ssss>                                            |                                                                                       │
│ 13   0.5   3.5   0.0  96.0|s>                                               |                                                                                       │
│ 14   0.5   4.5   0.0  94.9|ss  >                                            |                                                                                       │
│ 15   1.0  12.1   0.0  86.9|ssssss>                                          |                                                                                       │
│ 16   1.0  14.1   0.0  84.9|sssssss >                                        |                                                                                       │
│ 17   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│ 18   0.0   3.5   0.0  96.5|s>                                               |                                                                                       │
│ 19   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│ 20   0.0   0.0   0.0 100.0|>                                                |                                                                                       │
│ 21   0.5   5.5   0.5  93.5|ss>                                              |                                                                                       │
│ 22   1.5  12.6   0.0  85.9|ssssss>                                          |                                                                                       │
│ 23   0.5   4.1   0.0  95.3|ss >                                             |                                                                                       │
│ 24   1.0  14.6   0.0  84.4|sssssss>                                         |                                                                                       │
│---------------------------+-------------------------------------------------+                                                                                       │
│Avg   0.4   4.6   0.0  95.0|ss>                                              |                                                                                       │
│---------------------------+-------------------------------------------------+                                                                                       │
│ Network I/O ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────               │
│I/F Name Recv=KB/s Trans=KB/s packin packout insize outsize Peak->Recv Trans                                                                                         │
│      lo      1.2       1.2       4.0    4.0   307.5  307.5       16.1     16.1                                                                                      │
│virbr0-ni     0.0       0.0       0.0    0.0     0.0    0.0        0.0      0.0                                                                                      │
│  virbr0      0.0       0.0       0.0    0.0     0.0    0.0        0.0      0.0                                                                                      │
│     em3      0.0       0.0       0.0    0.0     0.0    0.0        0.0      0.0                                                                                      │
│     em1      0.0       0.0       0.0    0.0     0.0    0.0        0.1      0.0                                                                                      │
│     em2      0.0       0.2       0.5    1.0    64.0  230.0        0.4      0.9                                                                                      │
│     em4      0.0       0.0       0.0    0.0     0.0    0.0        0.0      0.0                                                                                      │
│    p1p1   1792.2  1130760.9  27804.925717.6    66.045023.6     1832.9 1130760.9                                                                                     │
│    p1p2      0.0       0.0       0.0    0.0     0.0    0.0        0.0      0.0                                                                                      │
│──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

從nmon的輸出來看,網卡的性能已經達到極限了。接下來,我們使用兩個網口進行數據獲取操作:

DROP EXTERNAL TABLE ext_test;
CREATE READABLE EXTERNAL TABLE ext_test
(
  a text
)
LOCATION (
    'gpfdist://172.28.8.251:8080/dev/shm/lotus.txt',
    'gpfdist://172.28.12.251:8080/dev/shm/lotus.txt'
 )
FORMAT 'TEXT' (DELIMITER 'OFF');

接下來,進行連續3次查詢:

lotus=# SELECT count(*) FROM ext_test;
  count
----------
 89000000
(1 row)

Time: 6529.515 ms
lotus=# SELECT count(*) FROM ext_test;
  count
----------
 89000000
(1 row)

Time: 6631.681 ms
lotus=# SELECT count(*) FROM ext_test;
  count
----------
 89000000
(1 row)

Time: 6335.189 ms

平均耗時爲6498 ms。 我們通過觀察nmon的輸出發現,有一個CPU Core已經100%繁忙了,根據我們的經驗,我們嘗試調整gpfdist的-m參數來增加gpfdist分割數據的效率:

[root@smdw ~]# gpfdist -p 8080 -d /../ -s -m 128000
2020-09-19 12:58:06 11018 INFO Before opening listening sockets - following listening sockets are available:
2020-09-19 12:58:06 11018 INFO IPV6 socket: [::]:8080
2020-09-19 12:58:06 11018 INFO IPV4 socket: 0.0.0.0:8080
2020-09-19 12:58:06 11018 INFO Trying to open listening socket:
2020-09-19 12:58:06 11018 INFO IPV6 socket: [::]:8080
2020-09-19 12:58:06 11018 INFO Opening listening socket succeeded
2020-09-19 12:58:06 11018 INFO Trying to open listening socket:
2020-09-19 12:58:06 11018 INFO IPV4 socket: 0.0.0.0:8080
Serving HTTP on port 8080, directory /

再次測試,平均耗時爲5475 ms。性能已經到了極限。


接下來,我們介紹gpfdist的深入優化,首先,我們嘗試修改gpfdist源碼,加入了異步數據傳輸和ZSTD壓縮傳輸特性,並使用execute外部表來進行數據獲取,我們並沒有修改Greenplum的Server端的代碼,所以,需要藉助execute外部表來完成這個優化測試。測試如下:

[root@smdw tmp]# ./gpfdist -p 8080 -d /../ -s -m 440000
2020-09-19 13:03:47 12544 INFO Before opening listening sockets - following listening sockets are available:
2020-09-19 13:03:47 12544 INFO IPV6 socket: [::]:8080
2020-09-19 13:03:47 12544 INFO IPV4 socket: 0.0.0.0:8080
2020-09-19 13:03:47 12544 INFO Trying to open listening socket:
2020-09-19 13:03:47 12544 INFO IPV6 socket: [::]:8080
2020-09-19 13:03:47 12544 INFO Opening listening socket succeeded
2020-09-19 13:03:47 12544 INFO Trying to open listening socket:
2020-09-19 13:03:47 12544 INFO IPV4 socket: 0.0.0.0:8080
Serving HTTP on port 8080, directory /

創建新的外部表:

CREATE READABLE EXTERNAL WEB TABLE ext_testexcu
(
  a text
)
 EXECUTE E'sh /tmp/gcurl.sh smdw:8080/dev/shm/lotus.txt' 
 FORMAT 'text' (delimiter 'off' null E'\\N' escape E'\\');

進行連續3次測試:

lotus=# SELECT count(*) FROM ext_testexcu;
  count
----------
 89000000
(1 row)

Time: 4189.400 ms
lotus=# SELECT count(*) FROM ext_testexcu;
  count
----------
 89000000
(1 row)

Time: 4213.136 ms
lotus=# SELECT count(*) FROM ext_testexcu;
  count
----------
 89000000
(1 row)

Time: 4179.077 ms

平均耗時爲4193 ms。


總結

gpfdist優化情況 平均耗時 平均加載性能 瓶頸點 gpfdist服務器帶寬消耗
無優化 9641 ms 1096 MB/s 網絡帶寬 1096 MB/s
增加網絡帶寬 6498 ms 1626 MB/s CPU主頻 1626 MB/s
-m爲128000 5475 ms 1930 MB/s 網絡帶寬/CPU主頻 1930 MB/s
修改源碼加入ZSTD壓縮傳輸和異步數據傳輸 4193 ms 2520 MB/s CPU主頻 大約380 MB/s

對gpfdist進行ZSTD壓縮傳輸和異步數據傳輸的優化,主要目的是,降低網絡帶寬的消耗,充分利用多CPU Core的計算能力。尤其是在網絡帶寬有限的環境,可以發揮極大的性能優勢。

 

from : https://github.com/water32/gpfaq/blob/master/2020/gpfdist.md#gpfdist%E5%A4%96%E9%83%A8%E8%A1%A8%E6%98%AFgreenplum%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9C%80%E9%87%8D%E8%A6%81%E7%9A%84%E6%95%B0%E6%8D%AE%E6%89%B9%E9%87%8F%E5%8A%A0%E8%BD%BD%E6%8A%80%E6%9C%AF%E6%9C%89%E7%9D%80%E6%9E%81%E9%AB%98%E7%9A%84%E6%80%A7%E8%83%BD

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