原创 DeepSeek总结的DuckLake:权威指南第5章性能优化-3

监控目录增长
无论您选择哪种目录平台,都应定期审查目录增长和整体健康状况。
随着时间的推移,元数据表可能会积累大量快照、文件统计信息、清单和历史记录。虽然DuckLake设计为可扩展到大型元数据量,但监控目录增长并执行日常维护可以帮助保持响应能力并简化故障排除。
作为一般规则,预防目录膨胀通常比在其成为性能问题后再修复更容易。
目录性能分析与故障排除
在进行性能更改之前,重要的是了解时间实际花在哪里。DuckLake提供了几种方法来分析元数据活动并调查运行缓慢的操作。
目录日志记录
DuckDB和Postgres目录都支持日志记录功能,可以帮助识别运行缓慢的操作。表5-1提供了文档链接:
86 | 第5章:性能优化
表5-1. 目录日志记录文档
目录主机 | 日志记录文档
DuckDB | DuckLake日志记录
Postgres | Postgres日志记录
例如,要在DuckDB托管的目录中启用日志记录:

CREATE table sales_dly (sls_dt date, region_name varchar, sls_amt double);
CALL enable_logging('DuckLakeMetadata');
INSERT INTO sales_dly VALUES ('2025-01-01', 'North', 200.05);
SELECT catalog, elapsed_ms, query
FROM duckdb_logs_parsed('DuckLakeMetadata');

duckdb_logs_parsed表函数返回已执行的查询及其执行时间。在排查脚本或工作负载中某些步骤耗时超出预期的情况时,这可能非常有用。
EXPLAIN ANALYZE
一旦日志记录帮助识别了慢查询,下一步通常是检查查询计划。
DuckDB提供EXPLAIN ANALYZE命令,显示执行计划。

EXPLAIN ANALYZE
SELECT *
FROM sales_dly
WHERE sls_dt = '2025-01-01'
AND region_name = 'North';

下面生成的执行图提供了DuckDB如何处理查询的详细见解,可以帮助识别瓶颈,如昂贵的扫描、连接或过滤操作。
Postgres和SQLite也支持EXPLAIN功能,尽管语法和输出格式略有不同。请参阅您所使用的特定目录平台的文档。
存储优化
开箱即用,DuckLake的存储配置设置已经高度优化,适用于大多数工作负载。然而,随着湖仓的增长,有几项维护和调优策略值得了解。其中一些
存储优化 | 87
策略侧重于控制文件增长和管理时间旅行保留,而另一些则侧重于优化Parquet文件的写入方式。
本节涵盖存储维护和文件参数调优技术,可以帮助提高性能并降低存储成本。
管理文件增长
数据湖仓架构的标志之一是通过数据集的历史版本进行时间旅行的能力。正如我们在前面章节中演示的,DuckLake通过快照完全支持这一能力。然而,这有一个权衡:每次插入、更新、删除和合并操作都会创建额外的元数据,如果要保持历史版本可访问,就必须保留这些元数据。
随着时间的推移,这可能导致Parquet文件和快照数量不断增加。幸运的是,DuckLake提供了几种维护程序,允许您在平衡性能、存储成本和历史保留要求的同时控制存储增长。
三种主要的存储维护操作是文件合并、快照过期和物理文件清理。表5-2显示了每种操作的优缺点。
表5-2. 文件合并、快照过期和文件清理的优缺点
操作 | 保留时间旅行 | 回收存储 | 改善查询性能
合并相邻文件(压缩)| 是 | 否 | 是
快照过期 | 否 | 否 | 有时
清理旧文件 | 否 | 是 | 最小
理解这些操作如何协同工作对于维护健康的DuckLake部署至关重要。
文件压缩
数据湖架构中的一个常见挑战是小文件问题。尽管DuckLake支持非常小插入的数据内联,但一旦数据超过内联阈值并写入对象存储,重复的插入操作可能会逐渐产生大量Parquet文件。
例如,想象一个应用程序每隔几分钟插入几百行,全天如此。随着时间的推移,数据集可能会积累数百或数千个小Parquet文件。虽然每个文件都是有效的,但查询性能可能会受到影响,因为查询引擎必须打开和评估更多的文件。
为了解决这个问题,DuckLake提供了ducklake_merge_adjacent_files()过程。
88 | 第5章:性能优化

CALL ducklake_merge_adjacent_files('dl1');

此操作合并相邻文件并创建一组新的优化Parquet文件。这种方法的主要优势之一是快照历史完全保留。现有的时间旅行功能继续像以前一样工作。
此操作不会物理删除任何旧文件。相反,它创建一组新的活动文件供未来查询使用,并将旧文件标记为逻辑无效。由于需要扫描的文件更少,压缩后查询性能通常会改善。
快照保留
压缩有助于减少活动文件的数量,但它不会减少目录为时间旅行目的保留的历史数据量。如果您的组织不需要无限期的历史事务保留,您可以选择使较旧的快照过期。
DuckLake为此提供了ducklake_expire_snapshots()过程。

CALL ducklake_expire_snapshots(
'dl1',
older_than => now() - INTERVAL '1 week'
);

当快照过期后,它们不再被视为对时间旅行操作有效。结果,用户将失去查询那些历史版本数据的能力。
在实施快照过期策略之前,重要的是咨询业务利益相关者,了解可能规定历史版本数据必须保留多长时间的审计、监管、法律或合规要求。
DuckLake还支持通过目录设置expire_older_than设置过期策略:

CALL dl1.set_option('expire_older_than', '1 month');
-- 现在只需调用过程使快照过期
CALL ducklake_expire_snapshots('dl1');

许多组织使用的一种实用策略是按固定计划使快照过期。例如,每周日晚上运行快照过期,创建一个粗粒度的历史记录,其中每周快照仍然可用,而较旧的日级和小时级历史被删除。这种方法在历史可恢复性和存储成本之间提供了平衡。
存储优化 | 89
物理文件清理
一个经常让新用户感到惊讶的重要细节是,使快照过期并不会物理删除任何文件。当快照过期时,DuckLake只是将相应的文件标记为不再对查询处理有效。文件本身仍然存在于存储中。
要物理删除不再被活动快照引用的文件,请使用ducklake_cleanup_old_files()过程。

CALL ducklake_cleanup_old_files(
'dl1',
cleanup_all => true
);

此操作从存储中永久删除过时文件,是实际回收存储容量的步骤。重要的是安排旧文件的删除发生在任何当前查询可能尝试读取它们之后。一种常见方式是将文件删除延迟到最长可能查询运行时间(也许您的系统有全局查询超时)。例如,在压缩或快照过期与物理删除旧文件之间等待24小时可能是有意义的。
许多生产环境将压缩、快照过期和清理安排为定期维护作业。这三个操作共同帮助维护查询性能,同时防止存储成本不必要地增长。
文件参数调优
在建立适当的维护策略后,您可能希望进一步优化Parquet文件的写入方式。DuckLake公开了几个控制Parquet文件生成和存储行为的配置设置。完整选项列表可在DuckLake文档中找到。以下设置是最常调整的。
压缩
要评估的单个最高影响的文件设置是压缩。DuckLake允许在全局、模式级别甚至单个表级别配置压缩设置。DuckLake默认使用Snappy压缩,因为它提供了出色的兼容性和快速写入性能。然而,许多现代工作负载受益于ZSTD压缩,它通常提供显著更好的压缩率,同时保持强大的读取性能。
Parquet版本
DuckLake默认使用Parquet 1.0版本以实现与外部系统的最大兼容性。如果您的环境主要使用现代查询引擎,请考虑
90 | 第5章:性能优化
升级到Parquet 2.0版本。在许多工作负载中,2.0版本以最小的缺点提供改进的压缩效率。
目标文件大小
在压缩或刷新数据时,DuckLake将力求Parquet文件大致与target_file_size参数对齐。DuckLake默认的512MB对大多数情况是合理的,但如果读取性能最重要,请考虑将该参数增加到1-2GB范围。这允许DuckLake从对象存储中拉取更大的数据块,从而提高总吞吐量。增加目标文件大小的缺点是写入这些较大文件可能需要更多内存,特别是在使用聚类时。
行组大小
DuckLake通过基于字节的阈值和基于行数的阈值公开行组大小。默认行组大小为122880行。对于存储在对象存储中的大型分析数据集,一些团队可能受益于尝试更大的行组,也许是2倍-4倍大。更大的行组可以提高压缩效率并改善数据从对象存储到计算环境的吞吐量。然而,要在使用聚类时获得任何好处,必须在一个文件中有多个行组。一个好的经验法则是大约10个行组。此参数与目标文件大小相互作用——同时增加两者往往是有意义的。
请注意,更大的行组会增加内存需求,因此建议在更改之前进行基准测试。如果表非常宽或行内包含大的单个值(例如大文本或JSON值),尤其如此。
DuckLake还提供基于行数的字节设置。这种方法不太依赖于行宽(不同表之间可能差异很大),因此可能比行数方法更容易调优。一个重要的前提是在调整基于字节的行组设置之前,必须禁用DuckDB的插入顺序保留。因此,尽管基于字节的设置通常更容易理解,但在使用聚类时,您应该使用基于行数的设置。
以下是调整这些常见设置的演示:

CALL dl1.set_option('parquet_version', '2.0');
-- 更改行组大小字节之前必须执行
SET preserve_insertion_order = false;
CALL dl1.set_option('parquet_row_group_size_bytes', '100MB');
CALL dl1.set_option('parquet_row_group_size', '1000000');

存储优化 | 91

-- 全局压缩设置
CALL dl1.set_option('parquet_compression', 'zstd');
CREATE SCHEMA sales;
CREATE TABLE dl1.sales.sales_dly (sls_dt date,region_name varchar,
sls_amt double
);
-- 模式级压缩设置
CALL dl1.set_option('parquet_compression','zstd'
,schema => 'sales');
-- 表级压缩设置
CALL dl1.set_option('parquet_compression','zstd'
,schema => 'sales',
table_name => 'sales_dly'
);

与任何性能调优练习一样,我们建议采用系统化的方法。同时更改多个设置可能使您难以确定哪个调整改善或降低了性能。然而,许多DuckLake设置彼此相关(例如行组大小和总文件大小),所以不要调优一个设置然后继续下一个——要研究多种设置更改的组合。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值