谈谈 InnoDB引擎中的一些索引策略

如果我们在工作能够更好的利用好索引,那将会极大的提升数据库的性能。

覆盖索引

覆盖索引是指在普通索引树中可以得到查询的结果,不需要在回到主键索引树中再次搜索

建立如下这张表来演示覆盖索引:

create table T (
    id int primary key,
    age int NOT NULL DEFAULT 0,
    name varchar(16) NOT NULL DEFAULT '',
    index age(age))
    engine=InnoDB;

我们执行select * from T where age between 13 and 25 语句,这条语句的执行流程大概为:

1、在 age 索引树中查找到 age = 13 的记录,取得 id 的值

2、根据 id 的值在主键索引上查找所需要的所有信息

3、在 age 索引树从上往下取,重复 1、2 两步操作,直到 age 不符合条件为止。

如果我们将语句换为 select id from T where age between 13 and 25,执行这条语句时,在 age 索引树上就可以查询到 id 的值,省去了上面的回表操作,这样就减少了搜索次数,提升了查询效率。

这时候的 age 索引树已经可以满足我们的查询需求,age 索引就称为覆盖索引。

覆盖索引是常用的数据查询优化技术,可以极大的提升数据库性能,有以下几个原因:

  • 减少树的搜索次数,显著提升查询性能
  • 索引是按照值的顺序存储,所以对于 I/O 密集型的范围查询比随机从磁盘中读取每一行的 I/O 要少很多
  • 索引的条目远小于数据的条目,在索引树上读取会极大的减小数据库的访问量

最左前缀原则

最左前缀原则是建立在联合索引之上的,如果我们建立了联合索引,我们不需要使用索引的全部定义,只要用到了索引中的最左边的那个字段就可以使用这个索引,这就是 B-tree 索引支持最左前缀原则。

建立如下这张表来解释最左前缀原则:

create table T (
    id int primary key,
    age int NOT NULL DEFAULT 0,
    name varchar(16) NOT NULL DEFAULT '',
    ismale tinyint(1) DEFAULT NULL,
    email varchar(64),
    address varchar(255),
    KEY `name_age` (`name`,`age`))
    engine=InnoDB;

我们建立了联合索引 name_age,现在,假设我们有以下三种查询情景:

1、查出用户名的第一个字是“张”开头的人的年龄。即查询条件子句为"where name like ‘张%‘"

2、查处用户名中含有“张”字的人的年龄。即查询条件子句为"where name like ‘%张%‘"

3、查出用户名以“张”字结尾的人的年龄。即查询条件子句为"where name like ‘%张‘"

在这三种情况中,第一种情况可以利用到 name_age 这个联合索引,加速查询,可以看出,我们并没有使用索引的全部定义,只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。

如果我们将索引的顺序调整为KEYname_age(age,name) ,那么上面三种情况都使用不到这个联合索引。

维护索引需要代价,所以有时候我们可以利用“最左前缀”原则减少索引数量。

索引下推

索引下推优化是 MySQL 5.6 引入的, 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

建立如下这张表来解释索引下推:

create table T (
    id int primary key,
    age int NOT NULL DEFAULT 0,
    name varchar(16) NOT NULL DEFAULT '',
    ismale tinyint(1) DEFAULT NULL,
    email varchar(64),
    address varchar(255),
    KEY `name_age` (`name`,`age`))
    engine=InnoDB;

在表中建立了 name、age 的联合索引,我们执行 select * from T where name like ‘张%‘ and age=10 and ismale=1;语句,「我们已经知道了B-tree 索引的最左前缀原则,所以将会用到 name_age 索引,因为索引下推优化,会在 name_age 索引树上判断 name 和 age 是否满足」。

根据我们上面的执行语句,会在 name_age 索引树上查找 name 以 ‘张‘ 开头的并且 age = 10 的数据,然后在回到主键索引树中查询所需要的信息,并不是所有 name_age 索引树上查找 name 以 ‘张‘ 开头的数据都回主键索引树中查询数据,这样就减少了一些不必要的查询。

假设我们的数据如下图所示:

在 name_age 索引树中有四条符合 name 以 ‘张‘开头的数据,如果没有索引下推,则需要回到主键索引树上判断 age 是否等于 10 ,这样就需要回表四次,而有了索引下推之后,在 name_age 索引树上就判断 age 是否等于 10 ,只需要回表两次,这样就减少了回表次数,提升了查询性能。

原文地址:https://www.cnblogs.com/kyoner/p/12252260.html

时间: 2024-10-11 07:11:02

谈谈 InnoDB引擎中的一些索引策略的相关文章

Innodb引擎中Count(*)

select count(*)是MySQL中用于统计记录行数最常用的方法,count方法可以返回表内精确的行数. 在某些索引下是好事,但是如果表中有主键,count(*)的速度就会很慢,特别在千万记录以上的大表. 所以.如果是用Innodb引擎的时候,使用select count(*)语句时,建议采用二级索引速度会比用主键索引更快. 在InnoDB引擎中,当我们通过二级索引统计数据的时候,无需扫描数据文件(二级索引存储指定字段的索引,实际的指向位置是主键索引.):而通过主键索引统计数据时,由于主

为啥select count(_) from t,在InnoDB引擎中比MyISAM 慢

感谢参考原文-http://bjbsair.com/2020-04-01/tech-info/18472.html 统计一张表的总数量,是我们开发中常有的业务需求,通常情况下,我们都是使用 select count(*) from t SQL 语句来完成.随着业务数据的增加,你会发现这条语句执行的速度越来越慢,为什么它会变慢呢? 为什么会变慢?想要得到答案就需要知道 MySQL 是如何统计总数量的,先说一个前提吧,count() 的具体实现是由存储引擎实现的,也就是说不同的存储引擎实现的方式不一

MySQL下InnoDB引擎中的Memcached插件

安装 为了让文章更具完整性,我们选择从源代码安装MySQL,需要注意的是早期的版本有内存泄漏,所以推荐安装最新的稳定版,截至本文发稿时为止,最新的稳定版是5.6.13,我们就以此为例来说明,过程很简单,只要激活了WITH_INNODB_MEMCACHED即可: ?123456789101112131415 shell> groupadd mysql shell> useradd -r -g mysql mysql shell> tar zxvf mysql-5.6.13.tar.gz s

InnoDB引擎索引大观

InnoDB是mysql处理OLTP(online transcation process)类型业务的存储引擎.为了加快数据查询速度,InnoDB引擎提供了丰富的索引实现. 1. 索引的分类 索引可以分为聚集索引和非聚集索引,聚簇索引(cluster) index)是指索引中键值的逻辑顺序和相应行的物理顺序一致,简单说就是索引中键值存储的是对应的行数据.非聚簇索引中索引的键值中存储的只是相应行的引用,并不代表行实际的存储.索引是在数据库的存储引擎中实现,不同的存储引擎索引的实现不一样.举例来说,

MySQL5使用Innodb引擎时如何设置数据文件按表存储

在Innodb引擎中,数据库的表可以共享存储空间也可以按表单独存储,共享存储空间虽然看起来简洁干净,但是从管理和运维的角度的看这种方式不可取.首先在同一个MySQL服务器下得不通数据库的表都会被存放于一个文件中,这个文件不会以为数据库某个表或者某些数据的删除二进行收缩,当数据库很多并且插入操作频繁的情况下,共享存储文件会增长的很快很大.如果数据库要做迁移,架构比较简单,但是存储于共享空间的中的数据就不太容易分离出来. 如果使用按表单独存储则可以很好的解决上述问题,遗憾的是MySQL5中使用Inn

MySQL5.5索引数在InnoDB引擎内与索引数在mysql中定义的数量是不一致问题

在查看MySQL错误日志的时候发现这样的错误,如下: 160322 21:42:59 [ERROR] Table baby/baby_order contains 12 indexes inside InnoDB, which is different from the number of indexes 11 defined in the My SQL 大概意思是说表baby_order的索引数在InnoDB引擎内与索引数在mysql中定义的数量是不一致的 为什么会出现这样的错误呢? 参考了这

mysql中innodb和myisam对比及索引原理区别(转)

InnoDB和MyISAM是很多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,5.7之后就不一样了 1.事务和外键 InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修复能力和多版本并发的事务安全,包括ACID.如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能 MyISAM管理非事务表.它提供高速存储和检索,以及全文搜索能力.如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择 2.全文索引 I

InnoDB引擎的索引和存储结构

InnoDB引擎的索引和存储结构 在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的.而MySql数据库提供了多种存储引擎.用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎. 1.MySQL主要存储引擎的区别 MySQL默认的存储引擎是MyISAM,其他常用的就是InnoDB,另外还有MERGE.MEMORY(HEAP)等. (1)主要的几个存储引擎 MyISAM管理非事务表,提供高速存储和检索,以及全文搜

MySQL 温故而知新--Innodb存储引擎中的锁

近期碰到非常多锁问题.所以攻克了后,细致再去阅读了关于锁的书籍,整理例如以下:1,锁的种类 Innodb存储引擎实现了例如以下2种标准的行级锁: ? 共享锁(S lock),同意事务读取一行数据. ?  排它锁(X lock).同意事务删除或者更新一行数据. 当一个事务获取了行r的共享锁.那么另外一个事务也能够马上获取行r的共享锁,由于读取并未改变行r的数据.这样的情况就是锁兼容. 可是假设有事务想获得行r的排它锁,则它必须等待事务释放行r上的共享锁-这样的情况就是锁不兼容.二者兼容性例如以下表