LightDB canopy 表管理
分散式表大小
分散式表大小的真實度量是作為分片大小的總和獲得的。 Canopy 提供函式來獲得表大小。
UDF | Returns |
---|---|
canopy_relation_size(relation_name) | Size of actual data in table |
canopy_table_size(relation_name) | 包含free spave map和visibility map |
canopy_total_relation_size(relation_name) | 總共大小 |
這些函式類似於標準 LightDB 物件大小函式中的三個,另外需要注意的是,如果它們無法連線到節點,則會出錯。
下面是使用輔助函式之一列出所有分散式表的大小的示例:
lightdb@test=# select canopy_total_relation_size('test'); canopy_total_relation_size ---------------------------- 229376 (1 row) SELECT logicalrelid AS name, pg_size_pretty(canopy_table_size(logicalrelid)) AS size FROM pg_dist_partition; name | size ------+-------- test | 224 kB (1 row)
Vacuuming Distributed Tables
在 LightDB(和其他 MVCC 資料庫)中,一行的 UPDATE 或 DELETE 不會立即刪除該行的舊版本。過時行的累積稱為膨脹,必須清理以避免查詢效能下降和磁碟空間需求無限制增長。 LightDB 執行一個稱為 auto-vacuum 守護程式的程式,該程式定期清理(也稱為刪除)過時的行。
在分散式資料庫中擴充套件的不僅僅是使用者查詢,vacuuming 也是如此。在 LightDB 中,繁忙的大表有很大的膨脹潛力,這既是因為對 LightDB 的真空比例因子引數的敏感性較低,而且通常是因為它們的行流失程度。將表拆分為分散式分片意味著單個分片是更小的表,並且自動真空工作器可以在不同機器上並行處理表的不同部分。通常 auto-vacuum 只能在每個表上執行一個 worker。
由於上述原因,對於大多數情況,Canopy 叢集上的自動真空操作可能已經足夠好了。但是,對於具有特定工作負載的表,或者有特定“安全”時間安排 vacuum 的公司,手動對錶進行 vacuum 可能比將所有工作留給自動 vacuum 更有意義。
要清理表,只需在協調器節點上執行以下命令:
VACUUM my_distributed_table;
對分散式表使用 vacuum 會向該表的每個工作節點傳送一個 vacuum 命令(每個位置一個連線)。這是並行完成的。支援除 VERBOSE 之外的所有選項(包括 column_list 引數)。 vacuum 命令也在協調器上執行,並在通知任何工作節點之前執行。注意,語句是原子性的,不合格的vacuum命令(比如沒指定表)是不會傳播到工作節點執行的。
Analyzing Distributed Tables
Canopy 將 ANALYZE 命令傳播到所有工作節點佈置。
要分析表,請在協調節點上執行:
ANALYZE my_distributed_table;
列儲存(使用限制較多)
Canopy 為分析和資料倉儲工作負載引入了僅附加列表儲存。當列(而不是行)連續儲存在磁碟上時,資料變得更加可壓縮,並且查詢可以更快地請求列的子集。
要使用列式儲存,請在建立表時指定 USING columnar:
CREATE TABLE contestant ( handle TEXT, birthdate DATE, rating INT, percentile FLOAT, country CHAR(3), achievements TEXT[] ) USING columnar;
您還可以在基於行(堆)和列式儲存之間進行轉換。
-- Convert to row-based (heap) storageSELECT alter_table_set_access_method('contestant', 'heap');-- Convert to columnar storage (indexes will be dropped)SELECT alter_table_set_access_method('contestant', 'columnar');
Canopy 在插入期間將行轉換為“stripes”中的列儲存。每個條帶包含一筆交易的資料,或 150000 行,以較少者為準。 (柱狀表的條帶大小和其他引數可以使用 alter_columnar_table_set 函式更改。)
例如,以下語句將所有五行放入同一個條帶中,因為所有值都插入到單個事務中:
-- insert these values into a single columnar stripeINSERT INTO contestant VALUES ('a','1990-01-10',2090,97.1,'XA','{a}'), ('b','1990-11-01',2203,98.1,'XA','{a,b}'), ('c','1988-11-01',2907,99.4,'XB','{w,y}'), ('d','1985-05-05',2314,98.3,'XB','{}'), ('e','1995-05-05',2236,98.2,'XC','{a}');
最好儘可能製作大條帶,因為 Canopy 按條帶分別壓縮列資料。我們可以使用 VACUUM VERBOSE 檢視有關柱狀表的資訊,例如壓縮率、條帶數和每個條帶的平均行數:
VACUUM VERBOSE contestant; INFO: statistics for "contestant": storage id: 10000000000 total file size: 24576, total data size: 248 compression rate: 1.31x total row count: 5, stripe count: 1, average rows per stripe: 5 chunk count: 6, containing data for dropped columns: 0, zstd compressed: 6
輸出顯示 Canopy 使用 zstd 壓縮演算法獲得 1.31x 資料壓縮。壓縮率將 a) 插入資料在記憶體中暫存時的大小與 b) 在其最終條帶中壓縮的資料大小進行比較。
由於它的測量方式,壓縮率可能與表的行儲存和列儲存之間的大小差異匹配,也可能不匹配。真正找到差異的唯一方法是構建包含相同資料的行和列表,並進行比較。
Measuring compression測試壓縮
Let’s create a new example with more data to benchmark the compression savings.
讓我們建立一個包含更多資料的新示例來對壓縮節省進行基準測試。
-- first a wide table using row storageCREATE TABLE perf_row( c00 int8, c01 int8, c02 int8, c03 int8, c04 int8, c05 int8, c06 int8, c07 int8, c08 int8, c09 int8, c10 int8, c11 int8, c12 int8, c13 int8, c14 int8, c15 int8, c16 int8, c17 int8, c18 int8, c19 int8, c20 int8, c21 int8, c22 int8, c23 int8, c24 int8, c25 int8, c26 int8, c27 int8, c28 int8, c29 int8, c30 int8, c31 int8, c32 int8, c33 int8, c34 int8, c35 int8, c36 int8, c37 int8, c38 int8, c39 int8, c40 int8, c41 int8, c42 int8, c43 int8, c44 int8, c45 int8, c46 int8, c47 int8, c48 int8, c49 int8, c50 int8, c51 int8, c52 int8, c53 int8, c54 int8, c55 int8, c56 int8, c57 int8, c58 int8, c59 int8, c60 int8, c61 int8, c62 int8, c63 int8, c64 int8, c65 int8, c66 int8, c67 int8, c68 int8, c69 int8, c70 int8, c71 int8, c72 int8, c73 int8, c74 int8, c75 int8, c76 int8, c77 int8, c78 int8, c79 int8, c80 int8, c81 int8, c82 int8, c83 int8, c84 int8, c85 int8, c86 int8, c87 int8, c88 int8, c89 int8, c90 int8, c91 int8, c92 int8, c93 int8, c94 int8, c95 int8, c96 int8, c97 int8, c98 int8, c99 int8);-- next a table with identical columns using columnar storageCREATE TABLE perf_columnar(LIKE perf_row) USING COLUMNAR;
插入大量資料:
INSERT INTO perf_row SELECT g % 00500, g % 01000, g % 01500, g % 02000, g % 02500, g % 03000, g % 03500, g % 04000, g % 04500, g % 05000, g % 05500, g % 06000, g % 06500, g % 07000, g % 07500, g % 08000, g % 08500, g % 09000, g % 09500, g % 10000, g % 10500, g % 11000, g % 11500, g % 12000, g % 12500, g % 13000, g % 13500, g % 14000, g % 14500, g % 15000, g % 15500, g % 16000, g % 16500, g % 17000, g % 17500, g % 18000, g % 18500, g % 19000, g % 19500, g % 20000, g % 20500, g % 21000, g % 21500, g % 22000, g % 22500, g % 23000, g % 23500, g % 24000, g % 24500, g % 25000, g % 25500, g % 26000, g % 26500, g % 27000, g % 27500, g % 28000, g % 28500, g % 29000, g % 29500, g % 30000, g % 30500, g % 31000, g % 31500, g % 32000, g % 32500, g % 33000, g % 33500, g % 34000, g % 34500, g % 35000, g % 35500, g % 36000, g % 36500, g % 37000, g % 37500, g % 38000, g % 38500, g % 39000, g % 39500, g % 40000, g % 40500, g % 41000, g % 41500, g % 42000, g % 42500, g % 43000, g % 43500, g % 44000, g % 44500, g % 45000, g % 45500, g % 46000, g % 46500, g % 47000, g % 47500, g % 48000, g % 48500, g % 49000, g % 49500, g % 50000 FROM generate_series(1,50000000) g; INSERT INTO perf_columnar SELECT g % 00500, g % 01000, g % 01500, g % 02000, g % 02500, g % 03000, g % 03500, g % 04000, g % 04500, g % 05000, g % 05500, g % 06000, g % 06500, g % 07000, g % 07500, g % 08000, g % 08500, g % 09000, g % 09500, g % 10000, g % 10500, g % 11000, g % 11500, g % 12000, g % 12500, g % 13000, g % 13500, g % 14000, g % 14500, g % 15000, g % 15500, g % 16000, g % 16500, g % 17000, g % 17500, g % 18000, g % 18500, g % 19000, g % 19500, g % 20000, g % 20500, g % 21000, g % 21500, g % 22000, g % 22500, g % 23000, g % 23500, g % 24000, g % 24500, g % 25000, g % 25500, g % 26000, g % 26500, g % 27000, g % 27500, g % 28000, g % 28500, g % 29000, g % 29500, g % 30000, g % 30500, g % 31000, g % 31500, g % 32000, g % 32500, g % 33000, g % 33500, g % 34000, g % 34500, g % 35000, g % 35500, g % 36000, g % 36500, g % 37000, g % 37500, g % 38000, g % 38500, g % 39000, g % 39500, g % 40000, g % 40500, g % 41000, g % 41500, g % 42000, g % 42500, g % 43000, g % 43500, g % 44000, g % 44500, g % 45000, g % 45500, g % 46000, g % 46500, g % 47000, g % 47500, g % 48000, g % 48500, g % 49000, g % 49500, g % 50000 FROM generate_series(1,50000000) g; VACUUM (FREEZE, ANALYZE) perf_row; VACUUM (FREEZE, ANALYZE) perf_columnar;
查詢壓縮比
SELECT pg_total_relation_size('perf_row')::numeric/ pg_total_relation_size('perf_columnar') AS compression_ratio; compression_ratio-------------------- 8.0196135873627944 (1 row)
Gotchas(陷阱)
• 列式儲存按條帶壓縮。條帶是為每個事務建立的,因此每個事務插入一行會將單行放入它們自己的條帶中。單行條帶的壓縮和效能會比行表差。始終批次插入到柱狀表。
• 如果將一堆細小的條紋弄亂並列化,則無法修復表格。唯一的解決方法是建立一個新的柱狀表並在一個事務中從原始表中複製資料:
BEGIN;CREATE TABLE foo_compacted (LIKE foo) USING columnar;INSERT INTO foo_compacted SELECT * FROM foo;DROP TABLE foo;ALTER TABLE foo_compacted RENAME TO foo;COMMIT;
• 從根本上說不可壓縮的資料可能是個問題,儘管使用列式資料仍然很有用,這樣在選擇特定列時載入到記憶體中的就更少了。
• 在混合了行和列分割槽的分割槽表上,更新必須仔細定位或過濾以僅命中行分割槽。
• 如果操作針對特定的行分割槽(例如 UPDATE p2 SET i = i + 1),它將成功;如果針對指定的列分割槽(例如 UPDATE p1 SET i = i + 1),它將失敗。
• 如果操作針對分割槽表並且具有排除所有列分割槽的 WHERE 子句(例如 UPDATE parent SET i = i + 1 WHERE timestamp = ‘2020-03-15’),它將成功。
• 如果操作針對的是分割槽表,但沒有排除所有的列分割槽,則會失敗;即使要更新的實際資料隻影響行表(例如 UPDATE parent SET i = i + 1 WHERE n = 300)。
Limitations使用限制
後續的canopy會逐步修復當前限制
• Append-only (no UPDATE/DELETE support)
• No space reclamation (e.g. rolled-back transactions may still consume disk space)
• Support for hash and btree indices only
• No index scans, or bitmap index scans
• No tidscans
• No sample scans
• No TOAST support (large values supported inline)
• No support for ON CONFLICT statements (except DO NOTHING actions with no target specified).
• No support for tuple locks (SELECT … FOR SHARE, SELECT … FOR UPDATE)
• No support for serializable isolation level
• No support for foreign keys, unique constraints, or exclusion constraints
• No support for logical decoding
• No support for intra-node parallel scans
• No support for AFTER … FOR EACH ROW triggers
• No UNLOGGED columnar tables
• No TEMPORARY columnar tables
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29990276/viewspace-2935321/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- LightDB canopy叢集管理
- LightDB Canopy 常見報錯問題分析(一)
- LightDB Canopy 常見報錯問題分析(二)DETAIL: Distributed relations cannot haveAI
- PostgreSQL/LightDB 分割槽表之分割槽裁剪SQL
- LightDB不記錄WAL日誌的表
- PostgreSQL/LightDB分割槽表之常見問題SQL
- LightDB部署模式模式
- LightDB 22.4 新特性之相容Oracle線上轉換普通表為分割槽表Oracle
- lightdb -- Oracle相容 -- rownumOracle
- LightDB/PostgreSQL 設定LightDB訪問白名單pg_hba.confSQL
- LightDB/Postgres 使用ora2pg遷移Oracle到LightDB/PostgresOracle
- LightDB-指定lightdb_syntax_compatible_type切換不同資料引擎
- LightDB-Oracle和LightDB邏輯備份測試對比(十二)Oracle
- lightdb -- merge into insert 相容 OracleOracle
- LightDB分散式實現分散式
- LightDB-指定lightdb_syntax_compatible_type切換不同資料引擎(十一)
- LightDB訂閱和釋出
- LightDB/PostgreSQL等待事件 Lock transactionidSQL事件
- LightDB/PostgreSQL 客戶端部署SQL客戶端
- lightdb的merge into使用介紹
- orcl建立表及管理表
- LightDB/Postgres邏輯複製的搭建
- lightdb WARNING: could not establish connection after 30000 ms
- LightDB/PostgreSQL 相容Oracle儲存過程SQLOracle儲存過程
- 使用GoldenGate 遷移Oracle到PostgreSQL/LightDBGoOracleSQL
- PostgreSQL/Lightdb 更改列屬性語法SQL
- LightDB 23.1相容Oracle新特性支援Oracle
- Oracle/MySQL透過odbc訪問PostgreSQL for LightDBOracleMySql
- 採用libpq連結lightdb示例程式
- LightDB常用備份恢復命令說明
- LightDB資料庫效能瓶頸分析(一)資料庫
- SQL教程——表的管理SQL
- Oracle OCP(21):管理表Oracle
- MySQL管理表和索引MySql索引
- 【SCRIPT】Oracle表管理段管理常用語句Oracle
- LightDB23.1新特性支援Oracle hint增強DB2Oracle
- LightDB 22.4 新特性之相容Oracle sqluldr2OracleSQL
- PostgreSQL/LightDB 不走並行是為什麼?SQL並行