AWS Aurora MySQL count(distinct)查询JSON列无匹配返回1异常
问题判定
这是AWS Aurora MySQL的已知Bug,并非SQL写法错误。
该Bug的触发边界非常清晰:
- 执行
COUNT(DISTINCT)统计的目标字段为JSON类型 - 查询过滤后无任何匹配行
- 出现在部分Aurora MySQL 2.x(兼容MySQL 5.7)、早期3.x(兼容MySQL 8.0)版本中
该问题是Aurora对JSON字段去重计数的执行逻辑做自研优化时引入的缺陷,空结果集场景下返回值初始化错误,才会返回1而非正确值0,原生MySQL不存在这个逻辑问题。当统计字段换为非JSON类型、或者去掉DISTINCT关键字时,不会触发这个有缺陷的执行路径,因此能返回正确的0值。
规避方案
以下方案按落地成本从低到高排列:
- 对JSON统计字段做显式类型转换,绕开有缺陷的优化路径
直接在COUNT(DISTINCT)内将JSON字段转为字符串类型,语义和原需求完全一致,不需要改动其他逻辑:select count(distinct CAST(`t`.`input` AS CHAR)) from `db`.`Transactions` as `t` join `db`.`Users` as `user` on `user`.`id` = `t`.`userId` where `t`.`documentId` = 'THIS DOESNT EXIST' - 改写查询分层执行
先通过子查询拿到所有符合条件的行,再在外层做去重计数,让优化器无法命中有问题的优化路径:select count(distinct input) from ( select `t`.`input` from `db`.`Transactions` as `t` join `db`.`Users` as `user` on `user`.`id` = `t`.`userId` where `t`.`documentId` = 'THIS DOESNT EXIST' ) as filter_res - 升级Aurora小版本
AWS已经在后续的Aurora MySQL补丁版本中修复了该计算错误,可以查阅官方版本发布说明,将集群升级到已修复该问题的版本,从根源解决问题。 - 业务层做兜底判断
如果暂时无法修改SQL或升级版本,可以在业务代码中先判断查询命中的行数,若行数为0直接将聚合结果置为0,规避数据库返回错误值的影响。
内容的提问来源于stack exchange,提问作者bersling
相关产品推荐
相关产品推荐

