配置设置
配置设置
DataFusion 的配置控制着 DataFusion 规划与执行的各个方面
设置配置选项
通过编程方式
你可以通过 ConfigOptions 对象以编程方式设置这些选项。例如,若要通过 API 配置 datafusion.execution.target_partitions:
use datafusion::common::config::ConfigOptions;
let mut config = ConfigOptions::new();
config.execution.target_partitions = 1;通过环境变量配置
你还可以通过 ConfigOptions::from_env 使用环境变量来设置配置选项,例如
DATAFUSION_EXECUTION_TARGET_PARTITIONS=1 ./your_program通过 SQL 配置
你也可以通过 SQL 使用 SET 命令来设置配置选项。例如,要配置 datafusion.execution.target_partitions:
SET datafusion.execution.target_partitions = '1';以下配置项可供使用:
| 配置项 | 默认值 | 说明 |
|---|---|---|
| datafusion.catalog.create_default_catalog_and_schema | true | 是否自动创建默认的 catalog 与 schema。 |
| datafusion.catalog.default_catalog | datafusion | 默认 catalog 名称——当 SQL 查询未指定 catalog 时将使用它。 |
| datafusion.catalog.default_schema | public | 默认 schema 名称——当 SQL 查询未指定 schema 时将使用它。 |
| datafusion.catalog.information_schema | false | DataFusion 是否提供对 information_schema 虚拟表的访问,以便展示 schema 信息。 |
| datafusion.catalog.location | NULL | 扫描以加载 default schema 中表的位置。 |
| datafusion.catalog.format | NULL | 加载 default schema 时使用的 TableProvider 类型。 |
| datafusion.catalog.has_header | true | 当 CREATE EXTERNAL TABLE 语句中未显式指定时,format.has_header 的默认值。 |
| datafusion.catalog.newlines_in_values | false | 指定是否支持(带引号的)CSV 值中的换行符。当 CREATE EXTERNAL TABLE 语句中未显式指定时,这是 format.newlines_in_values 的默认值。解析带引号值中的换行符可能会受到并行文件扫描等执行行为的影响。将其设置为 true 可确保值中的换行符被成功解析,但这可能会降低性能。 |
| datafusion.execution.batch_size | 8192 | 创建新批次时的默认批大小,这对于内存中缓冲的批次尤其有用,因为创建过小的批次会导致过多的元数据内存消耗。 |
| datafusion.execution.perfect_hash_join_small_build_threshold | 1024 | 当构建侧键的范围(max - min)小于该阈值时,将考虑使用完美哈希连接(详见 HashJoinExec)。这为键范围极小的连接提供了一条快速路径,跳过密度检查。目前仅支持 build_side.num_rows() < u32::MAX 的情况,对 build_side.num_rows() >= u32::MAX 的支持将在未来添加。 |
| datafusion.execution.perfect_hash_join_min_key_density | 0.15 | 考虑使用完美哈希连接(详见 HashJoinExec)时,构建侧连接键所需的最小密度。密度计算方式为:(行数) / (max_key - min_key + 1)。如果实际键密度大于该值,就可能使用完美哈希连接。目前仅支持 build_side.num_rows() < u32::MAX 的情况,对 build_side.num_rows() >= u32::MAX 的支持将在未来添加。 |
| datafusion.execution.coalesce_batches | true | 设置为 true 时,会在每个算子之间检查记录批次,并将小批次合并为较大的批次。当存在选择性很高的过滤器或可能产生极小输出批次的连接时,这非常有用。目标批大小由配置项决定。 |
| datafusion.execution.collect_statistics | true | DataFusion 是否在首次创建表时收集统计数据。表创建之后该设置不再生效。默认为 true。 |
| datafusion.execution.target_partitions | 0 | 查询执行的分区数。增加分区数可以提高并发度。默认为系统 CPU 核心数。 |
| datafusion.execution.time_zone | NULL | 默认时区。某些函数(例如 now)会以该时区返回时间戳。 |
| datafusion.execution.parquet.enable_page_index | true | (读取)若为 true,则读取 Parquet 数据页级别的元数据(Page Index,如果存在),以减少 I/O 和需要解码的行数。 |
| datafusion.execution.parquet.pruning | true | (读取)若为 true,parquet 读取器会根据查询中的谓词以及 parquet 文件中存储的元数据(最小/最大值)尝试跳过整个 row group。 |
| datafusion.execution.parquet.skip_metadata | true | (读取)若为 true,parquet 读取器会跳过文件 Schema 中可能存在的可选内嵌元数据。当查询多个 parquet 文件、其 schema 含有兼容类型但元数据不同时,此设置有助于避免 schema 冲突。 |
| datafusion.execution.parquet.metadata_size_hint | 524288 | (读取)如果指定,parquet 读取器会乐观地尝试获取 parquet 文件末尾的 size_hint 字节。若未指定,则需要两次读取:一次读取 8 字节的 parquet footer,另一次读取 footer 中编码的元数据长度。默认设置为 512 KiB,对大多数 parquet 文件而言已经足够,可为每个 parquet 文件减少一次 I/O 操作。如果元数据大于该提示值,仍会执行两次读取。 |
| datafusion.execution.parquet.pushdown_filters | false | (读取)若为 true,过滤表达式将在 parquet 解码操作期间被应用,以减少解码的行数。该优化有时被称为“延迟物化”。 |
| datafusion.execution.parquet.reorder_filters | false | (读取)若为 true,parquet 解码操作期间求值的过滤表达式会被启发式地重新排序,以使求值成本最低。若为 false,则过滤器按照查询中书写的顺序应用。 |
| datafusion.execution.parquet.force_filter_selections | false | (读取)当启用 pushdown_filters 时,强制对过滤结果使用 RowSelection。若为 false,读取器会根据选中行的数量和模式在 RowSelection 与 Bitmap 之间自动选择。 |
| datafusion.execution.parquet.schema_force_view_types | true | (读取)若为 true,parquet 读取器会以 Utf8View 读取 Utf8/Utf8Large 列,以 BinaryView 读取 Binary/BinaryLarge 列。parquet 读取器针对 Utf8View 和 BinaryView 做了优化,因此这类查询比先读取 Utf8/Binary 再转换为 view 类型要快得多。 |
| datafusion.execution.parquet.binary_as_string | false | (读取)若为 true,parquet 读取器会以 Utf8 读取 Binary/LargeBinary 列,以 Utf8View 读取 BinaryView 列。某些传统写入器生成的 parquet 文件没有正确设置字符串的 UTF8 标志,导致字符串列被作为 BLOB 加载。parquet 读取器针对 Utf8 校验有专门的优化,因此以字符串方式读取这类列比先以二进制读取再转换为字符串要快得多。 |
| datafusion.execution.parquet.coerce_int96 | NULL | (读取)若为 true,parquet 读取器会将物理类型为 int96 的列视为来自与纳秒不同的时间分辨率。这对于读取 Spark 等系统的数据很有用,这类系统将微秒分辨率的时间戳存储在 int96 中,从而能够写入比 64 位纳秒分辨率时间戳更宽的日期范围。 |
你也可以通过 SQL 中的 RESET 命令将配置项重置为默认设置。例如,设置并重置 datafusion.execution.batch_size:
SET datafusion.execution.batch_size = '10000';
SHOW datafusion.execution.batch_size;
datafusion.execution.batch_size 10000
RESET datafusion.execution.batch_size;
SHOW datafusion.execution.batch_size;
datafusion.execution.batch_size 8192运行时配置设置
DataFusion 的运行时配置可以通过 SQL 使用 SET 命令进行设置。
例如,要配置 datafusion.runtime.memory_limit:
SET datafusion.runtime.memory_limit = '2G';以下是可用的运行时配置设置:
| 键 | 默认值 | 描述 |
|---|---|---|
| datafusion.runtime.file_statistics_cache_limit | 20M | 文件统计信息缓存可使用的最大内存。支持后缀 K(千字节)、M(兆字节)和 G(吉字节),或使用 ‘0’ 表示 0。示例:‘2G’ 表示 2 吉字节。 |
| datafusion.runtime.list_files_cache_limit | 1M | 文件列表缓存可使用的最大内存。支持后缀 K(千字节)、M(兆字节)和 G(吉字节),或使用 ‘0’ 表示 0。示例:‘2G’ 表示 2 吉字节。 |
| datafusion.runtime.list_files_cache_ttl | NULL | 文件列表缓存中各条目的 TTL(生存时间)。支持单位 m(分钟)和 s(秒)。示例:‘2m’ 表示 2 分钟。 |
| datafusion.runtime.max_spill_merge_fan_in | 0 | 单次外部归并过程中打开的溢写文件的最大数量。设为 0 表示不限制。小于 2 的值仍会按 2 使用,以确保归并能够继续进行。 |
| datafusion.runtime.max_temp_directory_size | 100G | 临时文件目录的最大大小。支持后缀 K(千字节)、M(兆字节)和 G(吉字节),或使用 ‘0’ 表示 0。示例:‘2G’ 表示 2 吉字节。 |
| datafusion.runtime.memory_limit | NULL | 查询执行的内存上限。支持后缀 K(千字节)、M(兆字节)和 G(吉字节),或使用 ‘0’ 表示 0。示例:‘2G’ 表示 2 吉字节。 |
| datafusion.runtime.metadata_cache_limit | 50M | 文件元数据缓存(例如 Parquet 元数据)可使用的最大内存。支持后缀 K(千字节)、M(兆字节)和 G(吉字节),或使用 ‘0’ 表示 0。示例:‘2G’ 表示 2 吉字节。 |
| datafusion.runtime.temp_directory | NULL | 临时文件目录的路径。 |
调优指南
短查询
默认情况下,DataFusion 会尝试最大化并行度并使用所有核心——例如,如果你有 32 个核心,每个执行计划会将数据拆分为 32 个分区。但是,如果数据量很小,为启用并行而拆分数据的开销可能会超过实际计算本身。
你可以通过 EXPLAIN 命令查看执行计划中的分区数量,从而了解使用了多少个核心。
datafusion.optimizer.repartition_file_min_size 选项控制 ListingTable 数据源提供方尝试重新分区的最小文件大小。但是,该选项不适用于用户自定义的数据源,并且仅在 DataFusion 拥有准确的统计信息时才有效。
如果你知道数据量很小,可以将 datafusion.execution.target_partitions 选项设置为较小的值,以减少重新分区的开销。对于非常小的数据集(例如小于 1MB),我们建议将 target_partitions 设置为 1,以完全避免重新分区。
SET datafusion.execution.target_partitions = '1';内存受限的查询
在严格的内存限制下执行内存消耗较大的查询时,DataFusion 会将中间结果溢写(spill)到磁盘。
当使用 FairSpillPool 时,内存会在各分区之间平均分配。datafusion.execution.target_partitions 的值越大,每个分区分到的内存就越少,out-of-core 执行路径可能更频繁地被触发,从而可能拖慢执行速度。
此外,在溢写过程中,数据会以 datafusion.execution.batch_size 指定的批大小读回。该值越大,能够合并的已排序溢写段(sorted run)就越少。调小此设置有助于减少后续所需的溢写次数。
总之,对于在非常严格的内存限制下运行的查询,建议将 target_partitions 和 batch_size 设置为较小的值。
-- Query still gets parallelized, but each partition will have more memory to use
SET datafusion.execution.target_partitions = 4;
-- Smaller than the default '8192', while still keep the benefit of vectorized execution
SET datafusion.execution.batch_size = 1024;连接查询
目前 Apache DataFusion 支持以下连接算法:
- 嵌套循环连接(Nested Loop Join)
- 排序归并连接(Sort Merge Join)
- 哈希连接(Hash Join)
- 对称哈希连接(Symmetric Hash Join)
- 分段归并连接(Piecewise Merge Join,实验性)
物理计划器会根据两张表的统计数据和连接条件选择合适的算法。
连接算法优化器配置
你可以通过设置特定的配置项来修改查询中的连接优化行为。使用以下命令更新配置:
SET datafusion.optimizer.<configuration_name>;示例
SET datafusion.optimizer.prefer_hash_join = false;调整以下配置值会影响优化器选择用于执行 SQL 查询的连接算法:
连接优化器配置
调整以下配置值会影响优化器选择用于执行 SQL 查询的连接算法。
allow_symmetric_joins_without_pruning(bool,默认 = true)
控制在输入缺少排序或过滤的情况下,是否允许对无界数据源使用对称哈希连接。
- 如果禁用,
SymmetricHashJoin算子将无法对其内部缓冲区进行裁剪,从而只能在执行结束时产出结果。
prefer_hash_join(bool,默认 = true)
决定在物理计划选择阶段,优化器是优先选择哈希连接(Hash Join)还是归并排序连接(Sort Merge Join)。
- true:在内存充足时优先选择 HashJoin,以获得更快的执行速度。
- false:当需要更节省内存的执行方式时,允许选择 SortMergeJoin。
enable_piecewise_merge_join(bool,默认 = false)
启用实验性的分段归并连接(Piecewise Merge Join)算法。
- 启用后,如果连接条件中恰好只有一个范围过滤条件,物理规划器可能会选择 PiecewiseMergeJoin。
- 对于单个范围过滤条件,分段归并连接在性能上优于嵌套循环连接(Nested Loop Join),但当连接的两个大表(num_rows > 100,000)规模相近时除外。
评论
登录后参与评论
KnowForge