mysql order by limit 使用技巧及优化分析
SQL语句如下:
EXPLAIN
SELECT id,PushData
FROM UserCardPushlog
WHERE status = 0
AND HANDleLock = 0
ORDER BY CreateTime
LIMIT 2000
行数:2200W
status、CreateTime 均有索引
执行计划如下:
type key rows extra
index ix_UserCardPushlog_CreateTime 88469 Using where
运行时间:33s
当去掉order by、limit时执行计划如下:
type key rows extra
ref ix_UserCardPushlog_status 350140 Using where
运行时间:1s
Q1:status、CreateTime上都有索引为何执行时间相差这么多?
Q2:status 字段上的索引为什么没有被使用?
-
单路排序与双路排序
1) 双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序。
2) 单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序。
所有字段长度总数小于max_length_for_sort_data,则使用单路排序,否则使用双路排序。
当前服务器max_length_for_sort_data配置为1024,而表UserCardPushlog所有字段长度总数大于max_length_for_sort_data,也就是说当前SQL使用的是单路排序。
可以看到type为index,说明扫描了CreateTime字段的所有数据然后进行排序。所以很慢。
Q2 是否可以理解为如果SQL查询的是单表并且包含order by且有索引,那么就将会使用order by 字段后的索引进行排序。最后才使用where条件进行过滤?
优化方案:使用status过滤数据后再进行排序。
-
使用子查询过滤数据后进行排序,如下SQL仍然没有使用status的索引。
EXPLAIN SELECT id,PushData FROM (SELECT id, PushData, CreateTime as s FROM UserCardPushlog WHERE status = 0 AND HANDleLock = 0) as t ORDER BY t.s LIMIT 2000 ;
-
最终解决方案:强制使用索引FORCE INDEX
EXPLAIN SELECT id,PushData FROM UserCardPushlog FORCE INDEX(ix_UserCardPushlog_status) WHERE status = 0 AND HANDleLock = 0 ORDER BY CreateTime LIMIT 2000 /* http://www.manongjc.com/article/1641.html */
-
另一种解决方案可以参考一下:where 条件后面加上CreateTime的过滤条件,这样index就会变成range,时间也只需要15s左右。SQL如下:
EXPLAIN SELECT id,PushData FROM UserCardPushlog WHERE status = 0 AND HANDleLock = 0 AND CreateTime >='2017-01-01' ORDER BY CreateTime LIMIT 2000
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- 后端逆袭,一份不可多得的PHP学习指南
- 走进Java接口测试之工具类库 Hutool
- Go开源游戏服务器框架——Pitaya
- 性能分析之pidstat新版本的%wait和mpstat的%iowait、top的wa
- 走进Java接口测试之整合ELK实现日志收集
- 【一天一大 lee】 监控二叉树 (难度:困难)-Day20200922
- 网络学习笔记2——物理层基础(信号与系统)(未完待续)
- 浅谈 React 中的 XSS 攻击
- Chrome 80+ 跨域Samesite 导致的cookie not found 解决方法
- 再不迁移到Material Design Components 就out啦
- hbase 学习
- 再谈Fragment
- java线程池(四):ForkJoinPool的使用及基本原理
- 算法书中算法
- Robo3T 与 NaviCat 的安装