MySQL 索引优化实践(二)(上)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: MySQL 索引优化实践

注意:如果文中的 SQL 无法执行,请使用编辑器重新编辑后再粘贴复制,可能 web 浏览器对空格或者特殊符号转码导致。


查询优化


数据初始化


# DDL 语句
CREATE TABLE `employees` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(24) NOT NULL DEFAULT '' COMMENT '姓名' COLLATE 'utf8_general_ci',
  `age` INT(10) NOT NULL DEFAULT '0' COMMENT '年龄',
  `position` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '职位' COLLATE 'utf8_general_ci',
  `hire_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_name_age_position` (`name`, `age`, `position`) USING BTREE,
  INDEX `idx_age` (`age`) USING BTREE
)
COMMENT='员工记录表';
# 随机数(随机生成员工年龄)
drop function if exists `rand_num`;
delimiter ;;
create function `rand_num`(
    `start_num` integer,
    `end_num` integer
)
    returns int
    comment ''
begin
    return floor(start_num + rand() * (end_num - start_num + 1));
end ;;
# 随机字符串函数
drop function if exists `rand_str`;
delimiter ;;
create
    definer = `root`@`localhost` function `rand_str`(
    `n` int
)
    returns varchar(255)
begin
    declare chars_str varchar(100) default 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz';
    declare return_str varchar(100) default '';
    declare i int default 0;
    while i < n
        do
            set return_str = concat(return_str, substring(chars_str, floor(1 + rand() * 52), 1));
            set i = i + 1;
        end while;
    return return_str;
end ;;
# 生成测试数据
drop procedure if exists `insert_emp`;
delimiter ;;
create procedure `insert_emp`(
    in `max_num` int(10)
)
begin
    declare i int default 0;
    set autocommit = 0;
    repeat
        set i = i+1;
        insert into `employees` (`name`, `age`, `position`, `hire_time`)
        values (rand_str(6), rand_num(20, 40), 'dev', now());
    until i = max_num
        end repeat;
    commit;
end ;;
delimiter ;
call insert_emp(10000);


很多时候我们业务系统实现分页可能会用到如下的 sql 实现:


select * from employees limit 50000, 10;


表示表 employees 中去除 50001 行开始的 10 行记录。看似只查询 10 条记录,实际这条 SQL 是优先读取 10010 条记录,然后抛弃前 10000 条记录,然后读后面想要的 10 条数据,因此要查询一张大表比较靠后的数据,执行效率是非常低的。


分页 Limit 优化


1、 更具自增且连续的主见爱心的分页查询


首先来看一个根据自增且连续主键排序的分页查询的例子:


mysql> select * from employees limit 90000,5; 


image.png


该 SQL 表示查询从第 90001开始的五行数据,没添加单独 order by,表示通过主键排序。我们再看表 employees ,因为主键是自增并且连续的,所以可以改写成按照主键去查询从第 90001开始的五行数据,如下:


select * from employees where id > 90000 limit 5; 


image.png


查询的结果是一致的。我们再对比一下执行计划:


EXPLAIN select * from employees limit 90000,5; 


image.png


EXPLAIN select * from employees where id > 90000 limit 5;


image.png


显然改写后的 SQL 走了索引,而且扫描的行数大大减少,执行效率更高。 但是,这条改写的SQL 在很多场景并不实用,因为表中可能某些记录被删后,主键空缺,导致结果不一致,如下图试验所示(先删除一条前面的记录,然后再测试原 SQL 和优化后的 SQL):直接 limit :


image.png


**id > x limit **

image.png


两条 SQL 的结果并不一样,因此,如果主键不连续,不能使用上面描述的优化方法。 另外如果原 SQL 是 order by 非主键的字段,按照上面说的方法改写会导致两条 SQL 的结果不一致。所以这种改写得满足以下两个条件:


  • 主键自增且连续


  • 结果是按照主键排序的


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
13天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
12 0
|
19天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
|
19天前
|
存储 SQL 关系型数据库
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
轻松入门MySQL:加速进销存!利用MySQL存储过程轻松优化每日销售统计(15)
|
19天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:优化进销存管理,掌握MySQL索引,提升系统效率(11)
轻松入门MySQL:优化进销存管理,掌握MySQL索引,提升系统效率(11)
|
13天前
|
SQL 缓存 关系型数据库
mysql性能优化-慢查询分析、优化索引和配置
mysql性能优化-慢查询分析、优化索引和配置
79 1
|
19天前
|
存储 关系型数据库 MySQL
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
|
19天前
|
缓存 关系型数据库 MySQL
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
|
10天前
|
存储 关系型数据库 MySQL
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
【4月更文挑战第9天】InnoDB数据库使用B+树作为索引模型,其中主键索引的叶子节点存储完整行数据,非主键索引则存储主键值。主键查询只需搜索一棵树,而非主键查询需两次搜索,因此推荐使用主键查询以提高效率。在插入新值时,B+树需要维护有序性,可能导致数据页分裂影响性能。自增主键在插入时可避免数据挪动和页分裂,且占用存储空间小,通常更为理想。然而,如果场景仅需唯一索引,可直接设为主键以减少查询步骤。
13 1
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
|
12天前
|
关系型数据库 MySQL 数据库
6. 了解过Mysql的索引嘛 ?
了解MySQL的索引类型,包括单列索引(普通、唯一、主键和全文索引)和组合索引。单列索引用于一列,如普通索引允许重复值,唯一索引和主键索引不允许,后者不允许空值。全文索引适用于特定文本字段。组合索引是多列的,遵循左前缀原则,通常推荐用于提高查询效率,除非是主键。
12 0
|
14天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)