高性能的MySQL(5)索引策略-索引案例分析

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介:

理解索引最好的办法是结合实例,接下来分析一个例子。

假设要设计一个在线约会网站,用户信息表有很多列,包括国家,地区,城市,性别,眼睛颜色等等。网站必须支持上面的各种组合来搜索用户,包括根据用户的最后在线时间,评分等进行排序的限制。

需要考虑是需要索引来排序还是先检索数据再排序,因为使用索引排序会严格限制索引和查询的设计。如果MySQL使用了某个索引的范围查询,也就无法再使用另一个索引或者是该索引的后续字段进行排序了。接下来一步步讨论:

1、支持多种过滤条件

country列的选择性通常不高,但是可能很多查询会用到。sex列的选择性很低,但是也会有很多查询用到。所以考虑到使用频率,建议创建不同组合的时候将(country,sex)作为前缀。

这和以前说的不应该在选择性低的列上创建索引是矛盾的,这么做有2个理由:

a、因为sex使用的太频繁。

b、更重要的一点是索引加了这一列没有什么坏处,即使查询没有使用sex,我们也可以通过技巧绕过,那就是在查询条件中增加and sex in ('m','f'),这样写不会过滤任何行,而且能够匹配索引最左前缀,这个非常有效,但是不要让in()列表太长

因为查询条件的复杂,可能会有很多需要常见的符合索引比如,(sex,country,age),(sex,country,region,age),(sex,country,region,city,age),如果想尽可能重用索引,那么in()技巧是很重要的,但是也不可滥用,如果列表太长的话,组合到一起会很影响性能。

我们会注意到一点,我们一直将age列放到索引的最后面。这是因为age特点,age列会有很多范围查询,而最左前缀中,遇到第一个范围查询,则后面的列索引就不能使用了。

所以一个重要的原则是将范围查询较多的列放在后面。

2、避免多个范围查询

什么是范围查询?从explain的输出很难区分范围查询(<,>,between)和列表值查询in(),因为explain中的type都是range,但是两种访问效率不同,对于后面字段的索引使用也是完全不一样的。前者后面的索引不能用了,后者却可以。

3、优化排序

使用文件排序对小数据是很快的,但是如果上百万数据,如何排序?

比如创建(sex,rating)索引用于下面的排序

1
select  <clos>  from  profiles  where  sex= 'M'  order  by  rating limit 10;

如过数据需要翻页,那么比较靠后的查询可能会像这样

1
select  <cols>  from  profiles  where  sex= 'M'  order  by  rating limit 100000,10;

这样即使有合适的索引,依旧是个严重的问题,除了预先计算,缓存可以优化这列问题,令一个比较好的策略是使用延迟关联

通过使用覆盖索引查询返回需要的主键,再根据这写主键关联原表获得需要的行,这可以减少mysql扫描那些需要丢弃的行

1
2
3
4
select  <cols>  from  profiles  inner  join (
select  < primary  key  cols>  from  profiles
where  sex= 'M'  order  by  rating limit 100000,10)
as  x using(< primary  key  cols>);

接下来我们看这个例子:

1
2
3
4
5
6
7
8
9
10
11
12
CREATE  TABLE  `emp3` (
   `id`  int (11)  NOT  NULL  DEFAULT  '0' ,
   ` name varchar (100)  NOT  NULL ,
   `job`  varchar (100)  NOT  NULL ,
   `num1`  int (10)  DEFAULT  NULL ,
   `num2`  int (10)  DEFAULT  NULL ,
   `num3`  int (10)  DEFAULT  NULL ,
   `job_num`  int (10)  DEFAULT  NULL ,
   `d`  date  DEFAULT  NULL ,
   PRIMARY  KEY  (`id`),
   KEY  `num1` (`num1`,`job_num`)
) ENGINE=InnoDB  DEFAULT  CHARSET=utf8;

表里有100万记录,如图:

135142942.png


看如下2个语句的差别:

1
select  from  emp3  where  num1=1  order  by  job_num limit 100000,10;

135346285.png


1
select  from  emp3  inner  join  select  id  from  emp3  where  num1=1  order  by  job_num limit 100000,10)  as  x using(id);

135454250.png

可以明显看到时间上的差异,不是在一个量级的。

注意:这个差距在InnoDB里是很明显的,因为只有在InnoDB中,这样子查询的索引才能用到覆盖索引,如果是在MyISAM就不会有这么明显的效果了,如下图:

1
2
3
4
5
6
7
8
9
10
11
12
CREATE  TABLE  `emp4` (
   `id`  int (11)  NOT  NULL  DEFAULT  '0' ,
   ` name varchar (100)  NOT  NULL ,
   `job`  varchar (100)  NOT  NULL ,
   `num1`  int (10)  DEFAULT  NULL ,
   `num2`  int (10)  DEFAULT  NULL ,
   `num3`  int (10)  DEFAULT  NULL ,
   `job_num`  int (10)  DEFAULT  NULL ,
   `d`  date  DEFAULT  NULL ,
   PRIMARY  KEY  (`id`),
   KEY  `num1` (`num1`,`job_num`)
) ENGINE=MyISAM  DEFAULT  CHARSET=utf8 ;

20W的数据测试结果如下:

140231632.png






















本文转自shayang8851CTO博客,原文链接:http://blog.51cto.com/janephp/1313556,如需转载请自行联系原作者

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
4月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
160 4
|
2月前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
|
2月前
|
SQL 关系型数据库 MySQL
索引设计实战:如何创建高性能MySQL索引
本文深入解析MySQL索引设计的核心原则与实战技巧,涵盖索引选择性、复合索引、性能优化及常见陷阱等内容,通过实际案例帮助开发者创建高效索引,显著提升数据库查询速度,助你打造高性能数据库系统。
|
3月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
172 6
|
4月前
|
缓存 关系型数据库 MySQL
在MySQL中处理高并发和负载峰值的关键技术与策略
采用上述策略和技术时,每个环节都要进行细致的规划和测试,确保数据库系统既能满足高并发的要求,又要保持足够的灵活性来应对各种突发的流量峰值。实施时,合理评估和测试改动对系统性能的影响,避免单一措施可能引起的连锁反应。持续的系统监控和分析将对维护系统稳定性和进行未来规划提供重要信息。
239 15
|
4月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
123 2
|
3月前
|
缓存 关系型数据库 MySQL
MySQL数据库性能调优:实用技术与策略
通过秉持以上的策略实施具体的优化措施,可以确保MySQL数据库的高效稳定运行。务必结合具体情况,动态调整优化策略,才能充分发挥数据库的性能潜力。
170 0
|
2月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
109 3
|
2月前
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。

推荐镜像

更多