场景
10月11日,某个用户出现了信息重复推送,导致出现重复数据,影响到了统计。
需要通过用户ID、时间戳、事件,找出相同msgid字段相同的数据,并删除。
已知,表有接近1亿条数据。
解决
查询重复数据
查看表索引,刚好有匹配的索引
KEY `idx_storeid_event_ctime` (`store_id`,`event`,`ctime`),
SELECTmsgid,COUNT(*) AS duplicate_count,min(id) as id
FROM`user_msg_list`
WHEREstore_id = 233AND ctime > 1728615600AND ctime < 1728622800AND `event` = 'EventGroupChat'
GROUP BYmsgid
HAVINGCOUNT(*) > 1;
# 查询的时候不要用 order by id desc
# 否则查询的时候,因为缺少id的索引,引起慢查询。
遍历删除
防止删除到其他的数据,所以还得把前边的条件一起放进来
DELETE
FROMuser_msg_list`
WHEREstore_id = 233AND ctime > 1728615600AND ctime < 1728622800AND `event` = 'EventGroupChat'AND id != 10086AND msgid !=318692996
项目上完整代码
我用的是thinkphp框架
$where = "store_id = 233AND ctime > 1728615600AND ctime < 1728622800AND `event` = 'EventGroupChat'";$data = Db::table("user_msg_list")->where($where)->field("msgid,COUNT(*) AS duplicate_count,min(id) as id")->group("msgid")->having("COUNT(*) > 1")->select()->toArray();foreach ($data as $v) {$id = $v['id'];$msgid = $v['msgid'];$msgIds = Db::table("user_msg_list")->where($where)->where("id!={$id}")->where("msgid", $msgid)->column("id");$res = Db::table("user_msg_list")->whereIn('id',$msgIds)->delete();dump($res);}
结束
数据太多了,动不动就是几秒都还无结果,3秒无结果的时候我都会停止运行。
防止出现缩表影响到正常业务的开展。