Tidb 跨分区使用count distinct if 统计不准(有bug)

本文讲述了在使用 TiDB 数据库时遇到的一个关于分区表统计不准确的问题。当尝试通过用户ID和事件类型进行去重计数时,原始SQL在全表查询时返回错误结果,但在单分区查询时正确。最终通过修改SQL,用0替换NULL并做差值计算得到了准确结果。问题涉及到分布式数据库的统计特性和SQL优化。
摘要由CSDN通过智能技术生成

我们公司使用了tidb,然后我就发现了这东西有点不靠谱,用新技术果然要付出代价。不要问我为什么用,反正很蛋疼

正文

如标题所示,假设一张表结构如下,用日期进行分区

CREATE TABLE `table_xiucai` (
  `user_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '用户id',
  `event_type` varchar(100) COLLATE utf8_general_ci NOT NULL COMMENT '事件类型',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `par` date NOT NULL COMMENT '分区键'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci 
PARTITION BY RANGE ( TO_DAYS(`par`) ) (
  PARTITION `20211215` VALUES LESS THAN (738504)
)

表中用户id默认值为0(实际表中会存在为0的记录)。

业务需求

需要统计不同事件类型的uv数,也就是根据user_id进行去重,按照我们最简单的mysql写法如下

select count(distinct(if(event_type = 'xx1' and user_id > 0, user_id, null))) as count1,
	count(distinct(if(event_type = 'xx2' and user_id > 0, user_id, null))) as count2
from table_xiucai 
where par >= 20210101 and par <= 20220101 

然后把以上sql拿到tidb去运行,结果返回的结果是不准的,非常的坑,但是我自测的时候用的是单个分区,如下

select count(distinct(if(event_type = 'xx1' and user_id > 0, user_id, null))) as count1,
	count(distinct(if(event_type = 'xx2' and user_id > 0, user_id, null))) as count2
from table_xiucai 
where par = 20210101 

这样统计出来的结果是准确的,一万个操蛋。最终没有办法改成了以下sql才得到正确结果

select count(distinct(if(event_type = 'xx1' and user_id > 0, user_id, 0)))  - count(distinct if(event_type = 'xx1' and user_id = 0, 1, null)) as count1,
	count(distinct(if(event_type = 'xx2' and user_id > 0, user_id, 0)))  - count(distinct if(event_type = 'xx2' and user_id = 0, 1, null)) as count2  
from table_xiucai 
where par = 20210101 
distinct(if(user_is_new = 1, user_id, 0))是用于统计新增用户量的方法,通过在if语句中判断用户是否是新用户来区分统计的用户。这样可以确保结果准确且去重。 然而,在使用这种统计方法时,有时可能会出现结果不准确的情况。为了解决这个问题,可以使用更复杂的SQL查询语句来进行统计。在这个例子中,使用了嵌套的if语句和count函数来分别统计不同的事件类型和用户ID,并进行减法操作来得到正确的结果。 然而,尽管这样的查询语句在自测时可能会得到准确的结果,但当将其应用于tidb时,可能会出现不准确的情况。这可能是因为在运行查询时,涉及到的数据分区的不同导致结果不一致。因此,在使用这种查询语句时,需要注意并确保数据分区的一致性,以获得准确的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【hive】count() count(if) count(distinct if) sum(if)的区别](https://blog.csdn.net/weixin_39996750/article/details/113980253)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Tidb 分区使用count distinct if 统计不准(有bug)](https://blog.csdn.net/lvqinglou/article/details/126878850)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值