vertica 最佳實踐之 ROS Bundling

在Vertica 7.2之前,每列有兩個文件-數據文件和索引文件。從Vertica 7.2開始,此格式不再存在。現在,這兩個部分都存儲在一個文件中。此外,多個數據文件和索引文件也可以存儲在一個文件中。

Vertica file architecture

下圖說明了Vertica文件體系結構,以及如何將表和投影簡化爲文件:

在這裏插入圖片描述

New storage format

Vertica旨在處理大型數據集。磁盤上的文件大小從數百兆字節到數百千兆字節不等。Tuple Mover有助於管理數據存儲。內存中的緩衝區吸收trickle 流負載,並且當內存緩衝區已滿時,Tuple Mover mergeout 操作會將數據寫入ROS容器。爲了管理磁盤上的文件數,Tuple Mover mergeout 操作會合並大小相似的ROS容器以創建更大的容器。有關更多信息,請參見 Tuple Mover最佳實踐。

儘管此方法適用於大多數表,但它可能會在包含大量小文件的表上出現問題。如果您的數據集滿足以下任一條件,則可能會發生這種情況:

  1. 寬表包含NULL值列
  2. 分區範圍很小,例如按分鐘分區。不建議這樣做。
  3. 啓用了Local segmentation,並且將因子設置爲更高的數字。不建議這樣做。

這些因素會在磁盤上創建小文件,從而導致很多碎片,從而影響節點的恢復和備份操作。爲解決此問題,Vertica工程師開發了新的磁盤存儲格式和設計,從而減少了磁盤上存儲的文件數量。

How is the new format different?

現在,數據文件及其索引文件存儲在一個文件中。例如,在Vertica 7.2之前,一個具有兩列的投影,一個存儲容器存儲了六個文件。在Vertica 7.2和更高版本中,該容器存儲三個文件。如果這些文件小於1MB,則Vertica會將它們捆綁在一起,並將它們存儲爲一個文件。

Does the new functionality bundle all projection files?

不,捆綁僅發生在一個存儲容器內和一個存儲位置內。小於MaxBundleableROSSizeKB的列文件捆綁在一起;其他列文件則作爲獨立的列文件保存在存儲容器中。

Why is ROS bundling useful?

捆綁減少了存儲容器中文件的數量,從而減輕了對底層文件系統的壓力,並促進了更快的備份和還原操作以及恢復。捆綁不會減少目錄的大小,也不會消除ROS pushback error。Bundling 不會更改讀取列文件時使用的文件句柄數。

What configuration parameters are associated with the bundling functionality?

哪些配置參數與捆綁功能相關聯?

參數 數據類型/默認值 描述
啓用存儲捆綁 Boolean/True 啓用或禁用存儲捆綁。
MaxBundleableROSSizeKB Integer/1024 可以設置爲1024 KB。如果有多個數據文件低於此大小限制,則在同一容器和存儲位置中,文件將捆綁在一起。
CompactStorageJobSizeMB Integer/ 2048 控制函數COMPACT_STORAGE()的作業大小。

What is the upgrade impact from Vertica 7.1 to Vertica 7.2?

從Vertica 7.1升級到Vertica 7.2有什麼影響?
升級不會自動將現有文件從舊格式轉換爲新格式。升級後,可以使用函數COMPACT_STORAGE()轉換現有文件的文件格式。如果EnableStorageBundling設置爲true,則將發生以下行爲:

  1. 所有新的裝入和插入均以新的存儲格式寫入。
  2. 合併後的現有存儲將以新的存儲格式寫入。

Are the old and new formats compatible?

新舊格式兼容嗎?
是。如果您升級數據庫,並且表中同時包含大文件和小文件,則可以有選擇地將小文件移至新格式,而將大文件保留爲舊格式。

如何將數據從舊的存儲格式移動到新的格式?

使用COMPACT_STORAGE(),如以下示例所示:

=> SELECT COMPACT_STORAGE(object-name,
object-name,
min-ros-filesize-kb,
small-or-all-files,
simulate);

該函數的示例輸出如下所示:

compact_storage
---------------------------------------------------------------------------------------------------------------
Task: compact_storage
On node node01:
Projection Name :public.foo_super | selected_storage_containers :2 | selected_files_to_compact :12 | files_after_compact : 2 | modified_storage_KB :0
On node node02:
Projection Name :public.foo_super | selected_storage_containers :2 | selected_files_to_compact :12 | files_after_compact : 2 | modified_storage_KB :0
On node node03:
Projection Name :public.foo_super | selected_storage_containers :2 | selected_files_to_compact :12 | files_after_compact : 2 | modified_storage_KB :0

Success

如果我爲min_ros_filesize_kb指定的值與當前MaxBundleableROSSizeKB不同,該怎麼辦?

COMPACT_STORAGE()函數參數min_ros_filesize_kb獨立於MaxBundleableROSSizeKB配置參數。該函數使用您爲min_ros_filesize_kb指定的值。這對MaxBundleableROSSizeKB的值沒有影響。如果要在新的合併和加載中捆綁較大文件,則必須更改MaxBundleableROSSizeKB的值。

什麼時候是轉換爲新存儲格式的最佳時間?

爲了獲得最佳結果,請在將Vertica數據庫升級到7.2之後,但在執行第一次備份之前,轉換現有文件。這有助於備份和還原,原因有兩個:

  1. 減少文件數量,從而加快備份速度。
  2. 傳輸新存儲,因此後續備份可以更快地運行。

您可以在運行compact_storage時使用數據庫。

COMPACT_STORAGE()是否會影響查詢性能?

COMPACT_STORAGE()在存儲容器級別讀取和寫入文件。與合併操作相比,它使用較少的內存,但會搶佔 磁盤I / O。

COMPACT_STORAGE()需要運行多長時間?

由於此功能會重寫文件,因此執行時間取決於更改的數據量。通過將COMPACT_STORAGE()函數參數Simulation設置爲TRUE來運行模擬,以確定將更改多少存儲空間。

您可以通過在表或投影級別上迭代運行COMPACT_STORAGE()來增量地重寫存儲格式。

我如何知道我的數據庫是否將從此功能中受益?

如果備份和還原操作很慢,則可能是因爲許多大文件沒有合併。您可以運行以下查詢來查找節點上投影的中位數文件大小:

=> SELECT MEDIAN(size) OVER() AS median_fsize
FROM vs_ros AS ros, storage_containers AS cont
WHERE ros.delid=cont.storage_oid
AND cont.node_name=‘node'
AND cont.projection_name=‘proj_name' limit 1;

You can also run COMPACT_STORAGE() in simulation mode to see how many files it can reduce:

=> SELECT COMPACT_STORAGE(‘table_or_proj_name’, 1024, ‘small’,true);

我可以使用哪個系統表查看捆綁的存儲容器?

查詢系統表VS_BUNDLED_ROS以查看捆綁了哪些列文件:

node_name|   projection_id   |                  sal_storage_id                  |      ros_id       | size_bytes |    storage_id
---------+-------------------+--------------------------------------------------+-------------------+------------+-------------------

initiator| 45035996273721386 | 0262c017f1fb9eb26b8d8e6266a7005e00a0000000004041 | 45035996273721409 |       5    | 45035996273721409

initiator| 45035996273721386 | 0262c017f1fb9eb26b8d8e6266a7005e00a0000000004041 | 45035996273721413 |       5    | 45035996273721409

initiator| 45035996273721386 | 0262c017f1fb9eb26b8d8e6266a7005e00a0000000004041 | 45035996273721417 |       48   | 45035996273721409

(3 rows)

如果我有大的存儲容器,是否可以使用100MB作爲min_ros_filesize_kb的值?

要確定min_ros_filesize_kb的值,請在模擬模式下運行COMPACT_STORAGE()以確定資源使用情況。例如,如果您有一個包含100個數據文件的存儲容器,每個文件小於1MB,COMPACT_STORAGE()會將它們從200個文件更改爲1個文件。在這種情況下,將min_ros_filesize_kb的值指定爲100MB或1MB沒什麼區別。

如果您有另一個包含100個數據文件的容器,每個文件大約40MB,COMPACT_STORAGE()會將它們從200個文件更改爲1個文件。在這種情況下,指定100MB會產生積極的影響。如果我們指定1MB,則容器將從200個文件變爲100個文件。

要確定爲min_ros_filesize_kb設置什麼值,請按照以下步驟操作:

選擇一個投影。
確定文件數量和投影的中值文件大小。
在模擬模式下運行COMPACT_STORAGE(),其值的範圍從中位數到100MB。
根據模擬產生的值,確定數據庫的最佳位置。
以下示例顯示瞭如何分析compact_storage對更新的Vertica數據庫的需求和影響,以及如何確定min_ros_filesize_kb的最佳值:

檢查文件計數是否未捆綁:

=> SELECT COUNT(distinct (salstorageid))
* 2 /* one fdb and one pidx */
FROM v_internal.vs_ros
WHERE bundleindex < 0;  -- older versions dont have bundleindex
count
---------
1379533
(1 row)

查找未捆綁的文件的大小和數量,按投影和節點分組:

=> SELECT CASE WHEN segment_lower_bound is not null  THEN 'SEGMENTED' ELSE 'REPLICATED' END AS type,
schema_name,
projection_name,
max(used_bytes) max_used_bytes,
min(used_bytes) min_used_bytes,
CASE  WHEN segment_lower_bound is not null THEN count (distinct colid) ELSE count (distinct colid), count(distinct rosid) AS nFiles
FROM storage_containers join v_internal.vs_ros ON (delid = storage_oid)
WHERE bundleindex < 0 -- older versions dont have bundleindex
GROUP BY 1,2,3 ,segment_lower_bound
ORDER BY 7 desc
;
type      | schema_name | projection_name | max_used_bytes | min_used_bytes | nCols | nFiles
----------+-------------+-----------------+----------------+----------------+-------+--------
SEGMENTED | schema      | clients_b1      |       92368520 |          14778 |    13 |    650
SEGMENTED | schema      | clients_b0      |       47906279 |          14728 |    13 |    611
SEGMENTED | schema      | clients_b0      |      100868741 |          18776 |    13 |    572
SEGMENTED | schema      | clients_b0      |       59835832 |          15173 |    13 |    572
SEGMENTED | schema      | clients_b1      |       58541167 |          15441 |    13 |    507
SEGMENTED | schema      | clients_b1      |       61792636 |          14728 |    13 |    507

在不同的桶中分配文件大小以查看分佈情況`

=> SELECT
WIDTH_BUCKET (used_bytes, 0, 1024*1024*1024, 999) AS bucket, -- 1GB size of max bucket, 1000 buckets, (i.e. 1MB each bucket)
count(rosid) fileCnt
FROM
storage_containers JOIN v_internal.vs_ros ON (delid = storage_oid)
WHERE
schema_name = 'schema'
AND projection_name='clients_b1'
AND bundleindex < 0 -- older versions dont have bundleindex
GROUP BY 1
ORDER BY 1
;

bucket | fileCnt
-------+---------
1      |     715           <=== so many small 1 MB or less files
4      |      13
5      |      26
10     |      26
14     |      39
15     |      52
16     |      65
17     |      26
18     |      52
19     |      39
20     |     299
21     |      39
23     |      13
24     |      13
25     |      13
29     |      13
31     |      13
32     |      39
40     |      26
41     |      13
42     |      13
44     |      13
45     |      39
48     |      13
49     |      13
55     |      13
58     |      13
86     |      13
(28 rows)

在本例中,我們選擇5MB作爲壓縮存儲的大小。首先,進行預演,看看效果如何

=> SELECT COMPACT_STORAGE('schema.clients_b1', 5*1024, 'SMALL', true);  - 
                                 compact_storage
----------------------------------------------------------------------------------------------------------------

Task: compact_storage
On node v_scrutinload_node0001:
Projection Name :schema.clients_b1 | selected_storage_containers :50 | selected_files_to_compact :1012 | files_after_compact : 50 | modified_storage_KB :35584
On node v_scrutinload_node0002:
Projection Name :schema.clients_b1 | selected_storage_containers :39 | selected_files_to_compact :730 | files_after_compact : 39 | modified_storage_KB :16566
On node v_scrutinload_node0003:
Projection Name :schema.clients_b1 | selected_storage_containers :39 | selected_files_to_compact :728 | files_after_compact : 39 | modified_storage_KB :23126
Success

執行COMPACT_STORAGE ()。這將使用IO和資源。通過投影執行此操作可以在執行時進行更多的控制:

=> SELECT COMPACT_STORAGE('schema.clients_b1', 5*1024, 'SMALL', false);
                                    compact_storage

----------------------------------------------------------------------------------------------------------------

Task: compact_storage
On node v_scrutinload_node0001:
Projection Name :schema.clients_b1 | selected_storage_containers :50 | selected_files_to_compact :1212 | files_after_compact : 50 | modified_storage_KB :230564
On node v_scrutinload_node0002:
Projection Name :schema.clients_b1 | selected_storage_containers :39 | selected_files_to_compact :928 | files_after_compact : 39 | modified_storage_KB :221211
On node v_scrutinload_node0003:
Projection Name :schema.clients_b1 | selected_storage_containers :39 | selected_files_to_compact :926 | files_after_compact : 39 | modified_storage_KB :227449
Success

查看文件的新分發版

=> SELECT
WIDTH_BUCKET (used_bytes, 0, 1024*1024*1024, 999) AS bucket, -- 1GB size OF max bucket, 1000 buckets, (i.e. 1MB each bucket)
count(rosid) fileCnt
FROM
storage_containers JOIN v_internal.vs_ros ON (delid = storage_oid)
WHERE
schema_name = 'schema'
AND projection_name='clients_b1'
AND bundleindex < 0 -- older versions dont have bundleindex
GROUP BY 1
ORDER BY 1
;

bucket | fileCnt
-------+---------
14     |       1    <== small files are gone, largest one is 14MB ....
15     |       3
16     |       7
17     |       4
18     |       6
19     |       6
20     |      46
21     |       4
23     |       2
24     |       2
25     |       2
29     |       2
31     |       2
32     |       6
40     |       4
41     |       2
42     |       2
44     |       2
45     |       9
48     |       3
49     |       3
55     |       3
58     |       3
86     |       7
(24 rows)

比較buddy投影(b1)以查看影響

=> SELECT
CASE WHEN segment_lower_bound is not null  THEN 'SEGMENTED' ELSE 'REPLICATED' END AS type,
schema_name,
projection_name,
max(used_bytes) max_used_bytes,
min(used_bytes) min_used_bytes,
CASE  WHEN segment_lower_bound is not null THEN count (distinct colid) ELSE count (distinct colid) END as nCols,
count(distinct rosid) as nFiles
FROM storage_containers JOIN v_internal.vs_ros ON (delid = storage_oid)
WHERE bundleindex < 0 -- older versions dont have bundleindex
GROUP BY 1,2,3 ,segment_lower_bound
ORDER BY 7 desc;

type      | schema_ | projection_| max_used_bytes | min_used_bytes | nCols | nFiles
----------+---------+------------+----------------+----------------+-------+--------
SEGMENTED | schema  | clients_b0 |    47906279    |    14728       |    13 |    611
SEGMENTED | schema  | clients_b0 |   100868741    |    18776       |    13 |    572
SEGMENTED | schema  | clients_b0 |    59835832    |    15173       |    13 |    572
SEGMENTED | schema  | clients_b1 |    61792636    | 16300430       |     3 |     44     <=== better !
SEGMENTED | schema  | clients_b1 |    92368520    | 14086909       |     7 |     44
SEGMENTED | schema  | clients_b1 |    58541167    | 15202738       |     3 |     43
(6 rows)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章