Group by + Limit 的效率优化

2023-11-15

背景

最近接手一个项目,清洗历史表中的数据,在原有表中添加一个新的字段,并根据user_id进行分组,查询到证件号、证件类型后,换取唯一编码,将唯一编码存入历史数据中,以达到未来替换user_id的效果。
清洗数据的大体思路,将数据库中带清洗数据分10段,每段交给一条线程负责处理,项目启动后,出现一个问题,查询数据库中的数据出现 timeOut排查发现是因为 limit m,n 中的m太大,导致数据库扫描的数据块很大,所以出现超时。

优化过程
未优化前
  • 未优化前的SQL
SELECT user_id,id_card,paper_type FROM company_user WHERE person_code = '' GROUP BY user_id LIMIT 500000,100;
  • 执行时常 20s 以上,这是难以接受的
开始优化
  • 查找了网上一些博客分析GROUP BY 与临时表的关系 :
      1. 如果GROUP BY 的列没有索引,产生临时表.
      2. 如果GROUP BY时,SELECT的列不止GROUP BY列一个,并且GROUP BY的列不是主键 ,产生临时表.
      3. 如果GROUP BY的列有索引,ORDER BY的列没索引.产生临时表.
      4. 如果GROUP BY的列和ORDER BY的列不一样,即使都有索引也会产生临时表.
      5. 如果GROUP BY或ORDER BY的列不是来自JOIN语句第一个表.会产生临时表.
      6. 如果DISTINCT 和 ORDER BY的列没有索引,产生临时表.
  • 网上搜索得知内联表查询一般的执行过程是:
    1、执行FROM语句
    2、执行ON过滤
    3、添加外部行
    4、执行where条件过滤
    5、执行group by分组语句
    6、执行having
    7、select列表
    8、执行distinct去重复数据
    9、执行order by字句
    10、执行limit字句

通过上面的规则分析,尝试减少临时表的出现,让GROUP BY 的列和select 的列相同,先执行GROUP BY 然后再查询,通过子查询使得GROUP BY 先执行,sql如下:

SELECT user_id,id_card,paper_type,realname FROM company_user WHERE user_id IN
(SELECT user_id FROM (SELECT user_id FROM company_user WHERE person_code = '' GROUP BY user_id ) a) LIMIT 500000,100

执行时间从20s缩小到 17s,没有特别大的改善,依然不能接受

尝试将 LIMIT 500000,100 放到,子查询中

SELECT user_id,id_card,paper_type,realname FROM company_user WHERE user_id IN
(SELECT user_id FROM (SELECT user_id FROM company_user WHERE person_code = '' GROUP BY user_id LIMIT 500000,100) a)

执行时间从17s缩小到 15s,没有特别大的改善,依然不能接受

从索引的角度触发,person_code 是个单列索引,user_id是个单列索引,但效果不理想,尝试将person_code 和 user_id 创建组合索引,sql 不变

SELECT user_id,id_card,paper_type,realname FROM company_user WHERE user_id IN
(SELECT user_id FROM (SELECT user_id FROM company_user WHERE person_code = '' GROUP BY user_id LIMIT 500000,100) a)

执行时间从15s缩小到 1.5s,效率提升10倍,对于清洗数据这样对时间要求不是特别高的操作,已经可以接受了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Group by + Limit 的效率优化 的相关文章

随机推荐

  • 使用socket判断http请求或http响应的传输结束

    使用socket判断http请求或http响应的传输结束 先把header直到 r n r n整个地收下来 1 传输完毕就关闭connection 即recv收到0个字节 2 有内容 if Transfer Encoding chunked
  • 用户数据报协议UDP

    UDP的格式 载荷存放的是 应用层完整的UDP数据报 报头结构 源端口号 发出的信息的来源端口 目的端口号 信息要到达的目的端口 UDP长度 2个字节 16位 即UDP总长度为 2 16bit 2 10bit 2 6bit 1KB 64 6
  • lazyload ajax同步,jQuery lazyload 的重复加载错误以及修复方法

    分析代码也可以知道 最主要的原因是 写在页面上的 一经加载 就去向服务器申请图片地址 加载大图片 如果想实现原定的效果 则 写在页面上的待加载地址 必须不能是大图片的地址 而我们可以将真正的图片地址数据 存储在alt属性中 正确的例子如下
  • 批量转移(复制)文件夹内同类型文件(win10)

    1 打开cmd 2 批量转移 在cmd窗口中输入 move 空格 需要移动的文件后缀名所在的文件夹路径 需要移动的文件后缀名 空格 目标文件夹路径 例如 move E Pictures jpg E Work 3 批量复制 在cmd窗口中输入
  • ubuntu18.04的Android环境配置

    文章目录 1 安装Java jdk 2 安装Android studio 3 安装android sdk 4 安装 ndk 5 添加环境变量 1 安装Java jdk sudo apt get install openjdk 8 jre o
  • 获取文件夹中所有图片文件

    开发中常遇到要读取指定文件夹中的某一类文件 这时如果每次都以拼字符串地址的形式查找文件比较麻烦 分享两个读取指定文件夹中某一类文件的方法 以图片文件为例 1 以WWW方式进行加载 显示在RawImage上 2 以数据流形式读取文件 显示在R
  • 人工智能中的机器人教育

    现在有一种很普遍的思想 就是家长并不太关心孩子考的大学事都否是985和211 而且在意所录取的专业是否利于就业 格物斯坦温馨提示 这是一个很现实的问题 比如今几年兴起的人工智能专业 招生办的老师都说该专业毕业后平均月薪过万 而要学好这专业的
  • 入侵排查与响应-window和linux版

    目录 一 关于这方面的一些简单了解 1 我们的电脑为什么会被黑客入侵 2 黑客攻击的方式 二 window入侵排查 1 查看异常特征 2 系统账户安全 3 检测异常端口 进程 4 查看启动项 计划任务 服务 5 检查系统相关信息 三 lin
  • 2023年前端面试题集锦

    2023年又是行情惨淡的一年 为此我从 枇杷村IT面试宝典 小程序里收集了一些题目 更多题目可以扫下方二维码查看 现做个总结如下 1 在JavaScript中 0 0的结果是什么 结果为true 严格等于比较的是值和类型 对象除外 只要值和
  • react路由守卫、路由监听等总结

    1 路由守卫 拦截 react框架没有路由守卫功能 只能通过在路由里设置meta元字符实现路由拦截 路由拦截就是路由在发生变化时需要进行的拦截处理 2 监听路由变化 方式 1 路由下的内容组件通过history对象来进行监听 class H
  • games101,作业1

    正交变换 左边是缩放变换 右边是平移变换 对图形进行正交变换需要 先平移 再缩放 但是做矩阵乘法时 先相乘的矩阵放在右边 后相乘的矩阵放在左边 视口平移 Translate M ortho trans lt lt 1 0 0 r l 2 0
  • 计算机报名显示错误程序,在使用计算机等级考试模拟软件时出现这个COMDLG32.OCX错误解决办法...

    在现在 电脑的使用已经是非常普遍了 有用户反馈自己在计算机等级考试的学习中 做题时遇到了系统错误 提示说 Component COMDLG32 OCX or one of its dependencies not correctly reg
  • PTA程序设计类实验辅助教学平台-基础编程题--JAVA--7.8 超速判断

    import java util Scanner public class Main public static void main String args Scanner sc new Scanner System in int sp s
  • 什么是基于opencv的火灾识别

    基于OpenCV的火灾识别是一种利用计算机视觉技术和OpenCV库进行火灾检测和识别的方法 该方法通过处理火灾图像或视频流 提取关键特征和信息 如颜色 纹理 形状等 来判断是否存在火灾 并进一步确定火灾的位置 大小和程度等 通过基于Open
  • Android OBB文件

    从Android 2 3开始新增了一个OBB文件系统和StorageManager类用来管理外部存储上的数据安全 如果你过去开发过Symbian S60第三版或以上的版本可能发现都有一个隔离的文件系统 仅根据自己应用的UID才能读取 当然这
  • WSL——NextCloud 在 Windows 端的网络访问配置

    NextCloud 在 Windows 端的网络访问配置 1 WSL2 的 IP 配置问题 在 Windows 每次重启后 WSL2 的 IP 将会发生变化 即 WSL2 的 IP 并非静态地址 为此 通过下述代码可以手动为 WSL2 增加
  • golang:ent实体框架

    好烦 我就想自己使用自定义除了id字段以外的字段作为主键名 参见评论区大佬 field String id StorageKey stu id Unique Immutable
  • 归并排序MergeSort算法--分治

    归并排序 MergeSort 是一种有效的排序算法 该算法是采用分治法 Divide and Conquer 的一个非常典型的应用 将已有序的子序列合并 得到完全有序的序列 即先使每个子序列有序 再使子序列段间有序 若将两个有序表合并成一个
  • Django之路由层

    目录 django请求生命周期流程图 路由匹配 分组命名匹配 无名分组 有名分组 传递额外的参数给视图函数 命名URL 和 URL反向解析 命名URL URL反向解析 前端 URL反向解析 后端 无名分组反向解析 有名分组反向解析 路由分发
  • Group by + Limit 的效率优化

    背景 最近接手一个项目 清洗历史表中的数据 在原有表中添加一个新的字段 并根据user id进行分组 查询到证件号 证件类型后 换取唯一编码 将唯一编码存入历史数据中 以达到未来替换user id的效果 清洗数据的大体思路 将数据库中带清洗