Delta Lake多版本同物理文件引用合法性及Databricks查询不一致确认
Delta表版本与查询结果不一致问题分析
问题场景
我有一个包含2个版本的Delta表:
- 版本1添加事务:path =
"a.parquet",numRecords = 10,deletionVector = null - 版本2添加事务:path =
"a.parquet",numRecords = 10,deletionVector = (..., cardinality = 2)
注:两个事务指向同一物理路径"a.parquet",无单独删除事务。
根据Delta协议,我认为这是合法的Delta表,查询应返回18行,这个理解是否正确?实际在Databricks测试时,select(*)返回18行,count(*)返回8行,结果不一致。
问题解答
合法性判断
根据Delta Lake协议,这种情况是合法的。Delta允许不同版本的添加事务指向同一数据文件,每个事务的deletionVector仅作用于该事务对应的文件数据。版本1的事务无删除向量,贡献10行;版本2的事务通过删除向量标记该文件中2行待删除,贡献8行,合计18行,你的理论预期是正确的。
查询结果不一致的原因
出现select(*)和count(*)结果差异,源于Delta Lake的查询优化逻辑不同:
select(*)会直接扫描所有符合版本要求的数据行,应用对应事务的删除向量过滤,因此能正确计算出18行。count(*)默认依赖Delta表的元数据统计信息(事务记录的numRecords减去删除向量的cardinality),但由于两个事务指向同一文件,元数据统计逻辑出现冲突:错误地对同一文件的记录数进行重复计算后叠加删除向量,最终得出8行的错误结果。
修复方案
强制count(*)扫描实际数据而非依赖元数据,执行以下语句:
SELECT COUNT(*) FROM your_table_name OPTION (skipMetadataOnCount = true)
执行后会返回正确的18行结果。
内容的提问来源于stack exchange,提问作者Shani Solomon
相关产品推荐
相关产品推荐

