原创

记一个MYSQL深度查询问题思考

温馨提示:
本文最后更新于 2024年10月28日,已超过 86 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

背景

产品提了一个数据同步需求,结果导致MySql出现深度查询触发框架限制问题;需求目的是希望将历史同步失败数据重新同步一次,数据来源于EXCEL导入与已有数据匹配校验后生成,单次导入EXCEL最大2W条;触发重新同步后,发现系统仅能同步1W条数据,查看日志发现超过1W条后数据查询结果全部为空,一开始以为是深度查询的查询频率限制,修改步长后发现不仅是查询频率,而是深度查询超过1W后直接返空,而SQL直接复制到客户端执行没有任何问题
深度查询
客户端结果

原因

看到执行日志,看到SQL写法初步判断为MYSQL深度查询问题;经过日志排查及SQL验证,修改步长任然无法避免,确认了架构底层限制了深度查询频率及查询深度;虽然个人对限定值有所疑虑(本文不做讨论),但无法改变底层限制规则,只能修改SQL来解决该问题;

分析

我们知道,语句select * from table limit m,n在查询时,

  • 当m固定时,随着n值增大,查询所花费的时间会越来越多
  • 当n固定时,随着m值增大,查询所花费的时间随着m的增大急剧增加;因为此时数据库每次都会从第一条记录开始扫码,随着m值增大,所需查询的数据越多,速度越慢;

而我们常见分页查询几乎都是数据条数n值固定而偏移量m增加,所以很多公司业务才对深度查询做出限制;

解决方案

  • 子查询:先查出当前条件下第一条数据ID,然后再查询ID后当前页剩余数据;对于业务常用查询条件,我们一般都会设置索引,MYSQL的InnoDB引擎为绝大部分公司默认引擎,在该引擎下,根据索引查询ID不需要回表可直接返回,因为索引所对应的值就是ID;再根据ID及条件查询后面N条数据,也就是此时根据条件筛选后仅查询N条数据即可,大大降低了查询的深度;
  • 主键分页:这种场景在ID时连续自增时,根据查询页数和记录数算出ID的范围,然后配合limit使用:select * from table where id > m * (n - 1) limit n,与子查询类似
  • 业务限制:在某些业务场景下,我们认为用户不应该或者说绝大部分用户不会使用到深度查询结果集,固我们设定一个深度值,超过该值后数据不允许查询;例如:淘宝、京东等平台最大查询页数为100页,而在这种体量的平台中,显然数据量不止100页,当用户随意条件搜索时,认为100页后禁用数据,须用户使用更精准查询条件搜索;
    淘宝
    京东
正文到此结束
本文目录