一:索引基本描述
索引的定义:
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
数据库索引就像是一本书的目录一样,使用它可以让你在数据库里搜索查询的速度大大提升。而我们使用索引的目的就是,加快表中的查找和排序。
加快表与表之间的连接速度
在信息检索过程中,若使用分组及排序子句进行时,通过建立索引能有效的减少检索过程中所需的分组及排序时间,提高检索效率。
使用索引的缺点就是:
在创建索引的时候会占用存储空间。
在我们需要修改表中的数据时,索引还需要进行动态的维护,所以对数据库的维护带来了一定的麻烦。
1.1.1、create [unique|fulltext|spatial] index 索引名 on 表名(属性名);
eg:create index idx_age on test3(age)
eg:alter table test3 add index idx_id_name(id,name);
eg:drop index idx_age on test3;
4、索引的执行过程分析
+-----+-------+------+------+
| Sid | Sname | Sage | Ssex |
+-----+-------+------+------+
| 1 | zha | 20 | n |
| 2 | w | 22 | n |
| 3 | li | 21 | w |
| 4 | sun | 30 | n |
+-----+-------+------+------+
4 rows in set (0.00 sec)
mysql> select *from student where Sname='w';
+-----+-------+------+------+
| Sid | Sname | Sage | Ssex |
+-----+-------+------+------+
| 2 | w | 22 | n |
+-----+-------+------+------+
1 row in set (0.00 sec)
若表中数据在成千上万的数据,级该查询操作会影响上万条数据,效率比较低
key: idx_name在实际使用过程中用到了idx_name索引,整个查询影响了一行数据,
若查询表中存在上万的数据量,使用索引可以大大提高查询效率
使用索引之后(影响行数也变成了一行,根据索引搜索):
联合索引:可以创建两个联合索引
但是只可以命中第一个索引
因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
设计好MySql的索引可以让你的数据库飞起来,大大的提高数据库效率。设计MySql索引的时候有一下几点注意:
1,创建索引
对于查询占主要的应用来说,索引显得尤为重要。很多时候性能问题很简单的就是因为我们忘了添加索引而造成的,或者说没有添加更为有效的索引导致。如果不加
索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。
但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。
2,复合索引
比如有一条语句是这样的:select * from users where area=’beijing’ and age=22;
如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效
率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age,salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。
因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
3,索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
4,使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
5,排序的索引问题
mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
6,like语句操作
一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
7,不使用NOT IN和操作
NOT IN和操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替
三:索引底层原理
(借鉴文章:https://www.cnblogs.com/hollischuang/p/11987069.html)
B树是一种m阶平衡树,叶子节点都在同一层,由于每一个节点存储的数据量比较大,索引整个B树的层数是非常低的,基本上不超过三层。
就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写效率,主要集中在磁盘I/O上)。
问:除了上面这个范围查询的,还能说出其他的一些区别吗?(这个题不太了解后百度了一下)
科普时间:B+ Tree索引和Hash索引区别 哈希索引适合等值查询,但是不无法进行范围查询 哈希索引没办法利用索引完成排序 哈希索引不支持多列联合索引的最左匹配规则 如果有大量重复键值得情况下,哈希索引的效率会很低,因为存在哈希碰撞问题
上图为MyISAM主键索引的存储结构,我们能看到的不同是
1、主键索引树的叶子结点的数据区域没有存放实际的数据,存放的是数据记录的地址。
2、数据的存储不是按主键顺序存放的,按写入的顺序存放。
存储引擎:
MySQL最大的特点在于支持插拔式的存储引擎
MySQL中存储引擎使用比较多的MYISAM,InNoDB,memory存储引擎
myisam 引擎 ---- frm(定义的表结构) + myd(表中的数据记录) + myi(表中的索引) (数据与索引分离)
不支事物、外键,优势是访问速度快
innodb 引擎 --- frm(表的创建结构存储) + idb(表中数据和索引的存储) (数据+索引)
是mysql默认的存储引擎,具有事物特征,支持外键,支持自动增长列
mermory引擎 访问比较快,将数据存储在内存中,默认采用的是哈希结构存储(不适用于范围查询)一旦数据库关闭,表中的数据就会丢失
6 问:你们创建的那么多索引,到底有没有生效,或者说你们的SQL语句有没有使用索引查询你们有统计过吗?
这个还没有统计过,除非遇到慢SQL的时候我们才会去排查
7 问:那排查的时候,有什么手段可以知道有没有走索引查询呢?
可以通过explain查看sql语句的执行计划,通过执行计划来分析索引使用情况
8 问:那什么情况下会发生明明创建了索引,但是执行的时候并没有通过索引呢?
科普时间——查询优化器 一条SQL语句的查询,可以有不同的执行方案,至于最终选择哪种方案,需要通过优化器进行选择,选择执行成本最低的方案。 在一条单表查询语句真正执行之前,MySQL的查询优化器会找出执行该语句所有可能使用的方案,对比之后找出成本最低的方案。这个成本最低的方案就是所谓的执行计划。
优化过程大致如下: 1、根据搜索条件,找出所有可能使用的索引 2、计算全表扫描的代价
3、计算使用不同索引执行查询的代价 4、对比各种执行方案的代价,找出成本最低的那一个
1、B-树的每一个节点,存了关键字和对应的数据地址,而B+树的非叶子节点只存关键字,不存数据地址。
因此B+树的每一个非叶子节点存储的关键字是远远多于B-树的,B+树的叶子节点存放关键字和数据,
因此,从树的高度上来说,B+树的高度要小于B-树,使用的磁盘I/O次数少,
因此查询会更快一些。
2、B-树由于每个节点都存储关键字和数据,因此离根节点进的数据,查询的就快,离根节点远的数据,查询的就慢;
B+树所有的数据都存在叶子节点上,因此在B+树上搜索关键字,找到对应数据的时间是比较平均的,没有快慢之分。
3、在B-树上如果做区间查找,遍历的节点是非常多的;B+树所有叶子节点被连接成了有序链表结构,因此做整表遍历和区间查找是非常容易的。
B树:
B-树的特性:
1.关键字集合分布在整颗树中;
2.任何一个关键字出现且只出现在一个结点中;
3.搜索有可能在非叶子结点结束;
4.其搜索性能等价于在关键字全集内做一次二分查找;
5.自动层次控制;
B+树: B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在非叶子结点命中),其性能也等价于在关键字全集做一次二分查找;