为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【TiDB 版本】:3.1
【问题描述】:这样的表结构和索引,如何提升查询效率
背景: 有一个日志表,日增1亿。
表结构, 主要3个字段
| id | customer_id | device_id |
id是基于雪花算法生成的,按时间粗略递增
customer_id 表示客户id
device_id 是设备
索引:1、id主键索引 2、customer+device联合索引
目前有一个查询问题是 : 日新增的80%来自某2个大客户数据,其他数据较少。
sql: select id, device_id, receive_time from xxx where id < 141021042096209919 and id > 139907782278119424 and customer_id = ‘xxxx’ order by id desc limit 0,50;
这样的sql会被解析成按id索引扫描数据,直到满足50个。如果被大客户的热点数据淹没,目标数据的id会相对靠后,就比较慢了。
目前的解决办法是非大客户数据强制使用联合索引查询,效果会好一些。
但不知道有没有什么设计上改进办法
像这样的情况,应该如何优化。
是需要把大客户的数据单独分出来吗,分表?分区? 还是索引设计上可以有什么改进
TiDB的初衷好想不希望我们分库分表。
若提问为性能优化、故障排查 类问题,请下载脚本 运行。终端输出打印结果,请务必全选 并复制粘贴上传。
不懂是不是有什么设计或者架构上的优化
比如说,需要按客户分数据吗,分片?
这样就不会干扰了
毕竟走联合索引在后期可能还是会有局限
来了老弟
2020 年6 月 4 日 03:20
4
你好,
id 是否对实际业务有明确意义,如果针对客户, customer_id 应为唯一索引,将从此表拆分,设立单独的 customer 客户表,设备如果与客户是多对一的关系,可以使用 left join 来查找设备。
fzhedu
(fzhedu-PingCAP)
2020 年6 月 4 日 03:24
5
可行的内部优化是将 两个 index 的结果merge到一起,减少数据扫描量。具体来说,根据 index 2 找到 id,然后再根据 index 1 筛选合格的 ID,这样两个索引综合考虑可以减少数据扫描量。这个优化我们正在考虑。如果可以的话,请提供具体的建表语句,scheme,部分数据,或者stats,方便我们内部构造实验场景。谢谢。
1 个赞
id只是粗略表示时间
目前还没有涉及跨客户查询和事务,我也有想法拆分,不过不能保证后续会涉及跨客户的事务和查询
联合索引的初衷是为了快速查询设备相关信息。如果只有客户索引,通过join查询设备数据,还会高效吗
来了老弟
2020 年6 月 4 日 03:50
7
@fzhedu 为我们的研发童鞋,
@tianyu4552 看下是否配合下提供上述信息,方便我们继续优化。
希望可以通过实验结果当做结论,我的理解是可以的,id 的 scan 我认为是没有意义的。
fzhedu
(fzhedu-PingCAP)
2020 年6 月 8 日 02:41
8
鉴于实现 index merge 的周期较长,建议的方案有如下两个:
取决于 customer id 不同值有多少,如果不到 一千,建议按照 customer id 采用 partition table 存储,每个 customer 一个 partition;
如果 customer id 过多,建议将热点 customer 单独存储到另外的表,然后结果上 union 一起返回或者进行后续的操作。
system
(system)
关闭
2022 年10 月 31 日 19:06
11
此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。