ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

DataHub SQL Profiling 完全指南:表级与列级统计采集、SQLAlchemy Profiler 实现与成本优化策略

DataHub SQL Profiling 完全指南:表级与列级统计采集、SQLAlchemy Profiler 实现与成本优化策略 DataHub SQL Profiling 完全指南表级与列级统计采集、SQLAlchemy Profiler 实现与成本优化策略【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahubSQL ProfilingSQL 剖析是 DataHub 为关系型数据源提供的元数据能力增强模块在常规元数据摄取的同时按表采集行数、列数以及各列的 null 数、distinct 数、极值、均值、中位数、标准差、分位数与值频次分布等统计信息。本文以 metadata-ingestion/docs/dev_guides/sql_profiles.md 为主线结合仓库源码深入讲解其能力边界、SQLAlchemy Profiler 的实现原理以及如何通过 Query Combining、Aggregate Flattening、Sampling 三种手段在保留统计质量的前提下显著降低 Profiling 成本。读完本文你将能够在任意 SQL 数据源的 recipe 中正确启用并调优 Profiling并学会用 profiler 报告中的计数器定位瓶颈。SQL Profiling 是什么SQL Profiling 采集表级table level与列级column level统计信息。它不是一个独立运行的源而是一个可挂在任意 SQL 源上的可选能力——任何基于 SQL 的摄取源如 MySQL、PostgreSQL、Snowflake、BigQuery、Redshift 等都可以在配置中开启 Profiling。需要预先明确的一个事实是启用 Profiling 会拖慢摄取ingestion速度。这是因为它会在原有元数据查询之外额外对目标表发起多轮统计查询。因此官方文档专门给出警告对大量表或大量行运行 Profiling 可能产生可观的成本。尽管我们已经尽力限制 profiler 所执行查询的开销你仍应谨慎控制开启 Profiling 的表集合以及 Profiling 的运行频率。这条警告不是泛泛而谈——下面会看到一个宽表上每条度量一条查询的默认行为确实可能产生上百次往返与上百次全表扫描这正是本文后半部分要解决的核心问题。CapabilitiesProfiler 能提取哪些统计量Profiling 产出的统计信息分为两层表级每个表行数row count列数column count列级每个列视类型而定null 计数与占比null counts and proportionsdistinct 计数与占比distinct counts and proportions最小值、最大值、均值、中位数、标准差以及部分分位数值min / max / mean / median / stddev / quantiles直方图或唯一值频次分布histograms / frequencies of unique values这些能力对应到源码中 ge_profiling_config.py 里一组include_field_*开关默认值与描述如下配置项默认值作用include_field_null_counttrue是否统计每列 null 数量include_field_distinct_counttrue是否统计每列 distinct 数量include_field_min_value/include_field_max_valuetrue数值列最小值 / 最大值include_field_mean_valuetrue数值列均值include_field_median_valuetrue数值列中位数include_field_stddev_valuetrue数值列标准差include_field_quantilesfalse数值列分位数如 5%、25%、75%、95%include_field_distinct_value_frequenciesfalse唯一值频次分布include_field_histogramfalse数值字段直方图include_field_sample_valuestrue所有列采样值从 sqlalchemy_profiler.py 的实现看数值列统计由_process_numeric_column_stats处理分位数只有在include_field_quantiles开启时才通过 runner 的get_column_quantiles获取如果底层数据库适配器不支持分位数例如 MySQL 没有对应的原生函数则会捕获异常并跳过而不会让整个 Profiling 流程失败——这种能力降级而非报错的设计贯穿整个 profiler。支持的源文档中 Supported Sources 一节通过{{ inline }}指令嵌入了自动生成的表格片段sql_profiling_support_table.md.snippet。该片段并非手写维护而是由 docgen.py 中的generate_sql_profiling_support_table自动生成脚本遍历所有源的插件注册信息凡是在capabilities中声明了SourceCapability.DATA_PROFILING且supportedTrue的源都会被收录进表格。从仓库源码中可以看到声明了该能力supportedTrue的源至少包括SQL 通用层 sql_common.py 中注册的多个 SQL 源snowflake/snowflake_v2.pySnowflakecassandra/cassandra.pyCassandradremio/dremio_source.pyDremioinformix/source.pyInformixvertica.pyVerticaexcel/source.py、kafka/kafka.py、kafka_connect/kafka_connect.py 等非传统 SQL 但同样支持 Profiling 的源需要注意的是不同源对 Profiling 的支持程度并不一致例如use_sampling只对 BigQuery 和 Snowflake 生效profile_table_row_count_estimate_only只对 Postgres 和 MySQL 生效这些约束通过配置项上的SupportedSources(...)注解在源码中显式声明见 ge_profiling_config.py。Profiler 实现SQLAlchemy 统一实现零额外依赖DataHub 对所有SQL 源统一使用基于 SQLAlchemy 的 profiler即SQLAlchemyProfiler类见 sqlalchemy_profiler.py。它的工作方式不是旁路复制数据而是直接在你已有的 SQLAlchemy 连接上执行 Profiling 查询把结果整理成表级与列级统计后写入 DataHub。由于复用了源已有的连接除了 SQL 连接器本身外不需要任何额外依赖。从源码结构看profiler 采用核心引擎 平台适配器adapter的架构adapters 目录下为各平台提供了差异化实现bigquery.py含采样支持snowflake.py含采样支持mysql.pypostgres.pyredshift.py、athena.py、clickhouse.py、databricks.py、mssql.py、trino.pygeneric.py其余平台的通用回退不同平台的分位数计算、采样语法、数据类型映射见 type_mapping.py都通过适配器隔离这样 profiler 核心逻辑可以保持平台无关。启用方式Profiling 不需要额外安装任何组件也不需要单独配置——任何开启 profiling 的 SQL 源都会自动使用 SQLAlchemy profiler。最简配置source: config: profiling: enabled: true关于profiling.method: ge的说明文档明确指出旧的 Great Expectations profilerprofiling.method: ge已被移除。SQLAlchemy 现在是唯一的 SQL profilerprofiling.method选项不再有任何效果可以从 recipe 中直接删掉。这一变化也解释了为什么配置类文件仍名为ge_profiling_config.py——它保留了历史命名但其中turn_off_expensive_profiling_metrics、query_combiner_enabled、query_combiner_flatten_enabled等配置早已全面转向服务新的 SQLAlchemy profiler。成本问题为什么 Profiling 会慢理解优化手段之前先看清成本从何而来。默认情况下profiler 对每个指标、每个列各发一条查询。这意味着一张宽表可能有数十上百个列每个列又要 null、distinct、min、max、mean 等多条度量查询每条查询都是一次独立的数据库往返round trip每条聚合查询都是一次独立的表扫描table scan。于是一张宽表可能产生数百次往返和数百次全表扫描。针对这一现状DataHub 提供了三个互相独立、可以叠加组合的优化选项分别作用于不同的成本维度。优化一Query Combining查询合并配置项profiling.query_combiner_enabled默认开启它的原理是把每条恰好返回一行single-row的查询各自包装成一个 CTE再用交叉连接cross-join把多个 CTE 合并进一条SQL从而把多次往返压缩成一次-- 合并前示意N 条查询 SELECT count(*) FROM t; SELECT count(col1) FROM t; SELECT count(DISTINCT col1) FROM t; ... -- 合并后示意1 条查询、多个 CTE 交叉连接 SELECT (SELECT count(*) FROM t), (SELECT count(col1) FROM t), (SELECT count(DISTINCT col1) FROM t);需要精确理解它的收益边界它削减的是往返次数round trips而不是表扫描次数。因为每个 CTE 仍然是各自对表的独立聚合数据库仍然可能为每条度量各扫描一次表。换言之query combining 解决的是网络往返过多的问题扫描开销原封不动。其实现与报告类位于 query_combiner.py 与 query_combiner_runner.py。优化二Aggregate Flattening聚合展平配置项profiling.query_combiner_flatten_enabled默认关闭Query combining 只解决往返不解决扫描。对于同一张表上形态相同的聚合same-shape aggregates over the same tableAggregate Flattening 走得更远它不再为每个指标生成一个 CTE而是直接发一条扁平化的单条聚合语句-- 合并前示意N 个 CTE、N 次扫描 SELECT (SELECT count(*) FROM t), (SELECT min(v) FROM t), (SELECT max(v) FROM t); -- 展平后示意1 条语句、1 次扫描 SELECT count(*), min(v), max(v) FROM t;这把多次全表扫描折叠成一次对行存储row store数据库收益最大——例如 MySQL 这类每次扫描都要读取整张表的引擎。启用方式flattening 运行在 combiner 内部因此必须先开启 query combiningsource: config: profiling: enabled: true query_combiner_enabled: true # 必须开启——flattening 在 combiner 内部运行 query_combiner_flatten_enabled: trueFlattening 的适用边界并非所有查询都能被展平。文档明确了两条边界只有单聚合作用于整张表的查询才会被展平。凡是 profiler 自己构造的复杂查询——带过滤条件的 countfiltered count、采样行数sampled row count、中位数回退计算median fallback——都会回退到 CTE 路径结果依然正确但不会被折叠。COUNT(DISTINCT)每个语句有数量上限。因为每个 distinct 计数都会在数据库服务端内存中构建一棵去重树distinct-value tree合并太多会撑爆内存。因此展平对廉价聚合count、min、max 等收益最大对 unique 计数收益较小。控制这个上限的配置是profiling.max_distinct_per_statement默认 5即一条展平语句中最多允许包含多少个COUNT(DISTINCT)列。需要留意的是官方文档指出这个默认值是起点而非实测最优值应根据实际表的宽度与数据库内存情况调整。如何读懂 profiler 报告展平策略的本质是用往返换扫描所以报告里combined_queries_issued合并后发出的查询数可能反而上升——这不是回归必须结合scans_avoided一起看。相关计数器的含义如下计数器含义scans_avoided节省的表扫描次数这是成功信号只在一条展平语句的结果被成功提取后才计数flat_queries_issued尝试发出的展平语句数在执行前计数flatten_rejectedprofiler 自己构造的查询带过滤、采样或多行返回从未具备展平资格flatten_singletons在其表分组中孤身一人的查询被送入 CTE 路径——因为只展平一条语句毫无收益flat_group_failures展平语句执行失败并回退的数量flat_group_cte_recoveries其中由 CTE 路径在单次往返内恢复的数量flat_group_serial_fallbacks其中最终退化为每条查询一次往返的数量诊断方法如果scans_avoided很低就看最后四个计数器找原因——flatten_singletons很高说明当前负载本就没什么可合并的flat_group_serial_fallbacks非零则说明展平不但没省扫描、反而多花了往返此时这个开关关掉更好better off。这些计数器全部定义在 query_combiner.py 的SQLAlchemyQueryCombinerReport中并由 profiler 在结束阶段汇总进全局 reportreport_from_query_combiner因此你在摄取日志/报告中看到的正是源码中这组计数器的直接输出。优化三Sampling采样配置项profiling.use_sampling仅 BigQuery 和 Snowflake 支持默认开启前面两个选项解决的是减少发出的查询与扫描数量而 Sampling 解决的是降低单次扫描的成本——对于超大表它只对表的一个样本sample做 Profiling而不是全表。这决定了它与前两者天然可组合在支持的平台上三者可以同时开启。选择采样前必须理解的关键区别采样会改变你得到的数字。特别是 distinct 计数它是在样本上计算的因此uniqueCount会变成一个估算值estimate。相比之下query combining 与 flattening 只改变查询的发出方式它们产生的统计量与逐条执行每条查询完全一致——统计质量不受影响。与采样相关的其他配置见 ge_profiling_config.pyprofiling.sample_size默认10000采样的行数仅当use_sampling为 true 时生效profiling.ignore_sampling_tag_urns需要忽略采样的固定标签列表每个条目可以是完整标签 URN如urn:li:tag:my_tag或仅标签名如my_tag。若未指定表将基于use_sampling统一决定是否采样另外还有profiling.profile_table_row_count_estimate_only仅 Postgres / MySQL只对表行数做估算进一步减少精确 count 的开销。采样相关的适配器逻辑见 bigquery.py 与 snowflake.py。组合配置示例三管齐下的完整 recipe把三种手段组合到一份 recipe 中source: type: your-sql-source # 例如 mysql、postgres、snowflake、bigquery ... config: profiling: enabled: true # 手段一查询合并默认已开启这里显式写出 query_combiner_enabled: true # 手段二聚合展平默认关闭行存储如 MySQL 上收益最大 query_combiner_flatten_enabled: true # 每条展平语句允许的 COUNT(DISTINCT) 列数上限默认 5 max_distinct_per_statement: 5 # 手段三采样仅 BigQuery / Snowflake默认 true use_sampling: true sample_size: 10000最佳实践与注意事项小结按需开启Profiling 默认不开启且会拖慢摄取。建议只对需要做数据质量分析、schema 演化监控或数据集发现的核心表开启并控制 Profiling 运行频率避免在每次摄取都全量 Profiling 大表。成本优化三选或三合一Query Combining 削减往返默认开启一般无需关闭Aggregate Flattening 削减扫描行存储数据库收益最大建议结合报告中的scans_avoided验证Sampling 削减单次扫描成本仅 BigQuery / Snowflake。用报告数据说话开启 flattening 后把scans_avoided当作成功信号与combined_queries_issued一起解读如果flat_group_serial_fallbacks持续非零说明展平在增加往返而非节省扫描应当关闭该开关。接受估算启用采样后distinct 计数等统计量是样本估算值而非精确值需要精确统计的场景应关闭采样或只对非核心表使用采样。废弃配置清理profiling.method: ge已无任何效果请从旧 recipe 中删除避免误导后续维护者。至此从 Profiling 能采集什么、底层如何实现到三种成本优化手段的原理与报告解读你已经掌握了在 DataHub 中安全、高效地使用 SQL Profiling 的完整方法。【免费下载链接】datahubThe Context Platform for your Data and AI Stack项目地址: https://gitcode.com/GitHub_Trending/da/datahub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表