将大于或小于的范围查询装换为等值查询

在生产环境,经常会遇到需要对Worker表进行多次尝试的业务,超过一定重试次数后抛弃或使用其他方式处理,在查找满足重试条件数据时,通常会使用“小于”运算符并伴随排序操作,这种场景很容易出现性能问题。

如下面查找执行次数小于最大执行次数的记录的SQL:

SELECT *
FROM worker_task
WHERE status = 3
AND execute_times < max_execute_times
LIMIT 50;

表中数据分布为:

SELECT COUNT(1),status
FROM worker_task
GROUP BY status; +----------+--------+
| COUNT(1) | status |
+----------+--------+
| 2 | 0 |
| 1 | 1 |
| 10597565 | 2 |
| 66836 | 3 |
+----------+--------+

问题分析:

上面满足status = 3条件的数据有6.6万条,由于execute_times < max_execute_times需要扫描6.6万条记录中的每一行来确定是否满足条件,因此查询需要读取全部数据并对比,严重消耗服务器IO和CPU资源,查询性能极差,且该数据量会随公司大促暴涨,很可能导致单条SQL需要扫描和对几千万上亿的数据。

优化方式:

由于每次worker尝试后,会更新execute_times的值,这种场景下,可以在表中新增一个字段表标识该记录是否需要再次重试is_over_time,并在表中增加索引idx_ status_is_over_time(status,is_over_time),查询能够通过等值查询快速定位到满足条件数据,将范围查询改为等值查找。

将IN语句的范围查询改为等值查询

查询满足条件并按照优先级和最早更新时间取前50行记录:

SELECT *
FROM t_task
WHERE status in(1,3,9)
ORDER BY priority,update_time
LIMIT 50;

问题分析:

查询需要对满足WHERE条件status in(1,3,9)的数据按照priority+update_time两个字段排序取TOP50,如果满足WHERE条件的数据量较大,那么读取这些数据并排序会消耗服务IO和CPU资源,导致性能问题。

优化方式1:

由于WHERE条件status in(1,3,9)需要分别扫描status=1 和status=3以及status=9的数据,如果能将该条件进行业务拆分,仅查询其中一个状态的数据再排序,那么可以通过符合索引(status,priority,pdate_time)来避免对大数据量数据排序,并通过LIMIT减少扫描数据量,降低IO和CPU资源。

优化后的SQL为:

SELECT *
FROM t_task
WHERE status = 1
ORDER BY priority,update_time
LIMIT 50;

优化方式2:

在促销期间,任务产生速度远高于任务处理速度,造成任务表大量数据积压,而优先级较高的任务需要优先处理,但优先级较高的任务的数据量较少,因此可以在应用程序端对数据进行分级处理,优先处理优先级高且更新时间早的任务,保证这些任务优先处理的情况下,对普通任务进行随机处理(注意避免任务被连续多次重试)。

查找优先级高的任务(使用排序):

SELECT *
FROM t_task
WHERE status in(1,3,9) and priority = 9
ORDER BY update_time
LIMIT 50;

查看优先级地的任务(不使用排序):

SELECT *
FROM t_task
WHERE status in(1,3,9) and priority <> 9
LIMIT 50;

总结:

优化就是使用合理方式降低扫描的数据量和排序的数据量。

MySQL Execution Plan--将范围扫描转换为等值查询的更多相关文章

  1. MySQL Execution Plan--执行计划中的Type列

    在一次的优化过程中,由于没有关注执行计划中type列,仅看key列来查看"使用到的索引",导致优化过程走了不少弯路. 以下面SQL为例: SELECT wave_no, SUM(I ...

  2. MySQL Execution Plan--IN查询计划

    对于IN查询,MySQL会根据当前表数据结构(索引)和数据分布(统计信息和预估)生成多种执行计划,并根据执行成本挑选出“最优执行计划”. 假设有查询 SELECT * FROM student ,,, ...

  3. Oracle SQL explain/execution Plan

    From http://blog.csdn.net/wujiandao/article/details/6621073 1. Four ways to get execution plan(anyti ...

  4. sql server 执行计划(execution plan)介绍

    大纲:目的介绍sql server 中执行计划的大致使用,当遇到查询性能瓶颈时,可以发挥用处,而且带有比较详细的学习文档和计划,阅读者可以按照我计划进行,从而达到对执行计划一个比较系统的学习. 什么是 ...

  5. Execution Plan 执行计划介绍

    后面的练习中需要下载 Demo 数据库, 有很多不同的版本, 可以根据个人需要下载.  下载地址 -http://msftdbprodsamples.codeplex.com/ 1. 什么是执行计划 ...

  6. Mysql如何避免全表扫描的方法

    在以下几种条件下,MySQL就会做全表扫描: 1>数据表是在太小了,做一次全表扫描比做索引键的查找来得快多了.当表的记录总数小于10且记录长度比较短时通常这么做. 2>没有合适用于 ON ...

  7. MySQL Execution Plan--COUNT相关测试

    COUNT全表记录 在MySQL中,相同的SQL不同的存储引擎执行计划不同: 对于MyISAM引擎,由于使用表锁进行并发控制,同一时间点多个并发线程执行相同查询获得的结果相同,且MyISAM存储引擎专 ...

  8. MySQL Execution Plan--文件排序(file sort)

    在MySQL处理ORDER BY语句时,如果查询无法利用索引的有序性,则需要额外操作对数据进行排序.在MySQL中有三种排序算法: 1.快速排序(Quick Sort),对冒泡排序的一种改进,基本思想 ...

  9. MySQL学习-MySQL内置功能_索引与慢查询

    1.索引基础 1.1 介绍 (1.)为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂 ...

随机推荐

  1. 洛谷p1458顺序的分数题解

    抱歉,您们的蒟蒻yxj不知道怎么插入链接qwq就只好粘个文本的了qwq:https://www.luogu.org/problemnew/show/P1458 没错,是个黄题,因为你们的小蒟蒻只会这样 ...

  2. Java class 和public class 区别

    1.类的访问权限 为了控制某个类的访问权限,修饰词必须出现在关键字class之前.例如:public class Student {}    在编写类的时候可以使用两种方式定义类:    (A)pub ...

  3. log4j2使用RollingFile重启丢失日志问题

    <RollingFile name="cnkiLogRollingFileError" fileName="${logbigdata.dir}/Log8080/er ...

  4. 【06月19日】A股滚动市盈率PE最低排名

    ​仅根据最新的市盈率计算公式进行排名,无法对未来的业绩做出预测. 方大集团(SZ000055) - 滚动市盈率PE:2.59 - 滚动市净率PB:1.16 - 滚动年化股息收益率:3.91% - 建筑 ...

  5. Tomcat通过脚本自动部署

    1:autodeploy_tomcat_app.sh now=`date +%Y%m%d%H%M%S` tomcatPath=/home/test/apache-tomcat- backupPath= ...

  6. VisualStudio更改项目文件夹名称

    新建了一个空的解决方案(SolutionTest.sln),在文件夹Api中新建了一个webapi项目,物理位置为解决方案根目录下的叫Api文件夹里, 现在想把文件夹名由Api改为MyApi,需要做以 ...

  7. Lua table concat

    [1]table concat 简介 使用方式: table.concat(table, sep, start, end) 作用简介: concat是concatenate(连锁.连接)的缩写. ta ...

  8. 避免maven package 打包时执行 mybatis-generator-maven-plugin 插件

    一.为什么打包时会执行该插件mybatis-generator-maven-plugin默认绑定了package的生命周期 二.如何解决如果在package和install 执行插件,修改pom中的配 ...

  9. mysql中,手动提交事务

    1: 在mysql中,手动提交事务的案例:CREATE PROCEDURE tfer_funds       (from_account int, to_account int, tfer_amoun ...

  10. mosquitto: error while loading shared libraries: libwebsockets.so.12: cannot open shared object file

    错误描述: # mosquitto -c /etc/mosquitto/mosquitto.conf -dmosquitto: error while loading shared libraries ...