数据库-索引基础

参考文章:https://blog.csdn.net/u012954706/article/details/81241049
https://blog.csdn.net/suixinsuoyu12519/article/details/79526616

课外知识explain

MySQL Explain详解
在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。所以我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。

例如

// 实际SQL,查找用户名为Jefabc的员工
select * from emp where name = 'Jefabc';
// 查看SQL是否使用索引,前面加上explain即可
explain select * from emp where name = 'Jefabc';

在这里插入图片描述

1,定义

索引是表的目录,在查找内容前可以在目录中查找索引位置,以此快速定位查询数据。

1.1,索引应该选取什么样的类型

  1. 较小的数据类型通常会比较好,占用空间小,处理起来会比较快。
  2. 简单的数据类型更好,例如int比string,int元素之间的比较更为容易
  3. 避免null(最好将索引列设置为not null),null会使索引的统计信息以及比较运算更加复杂/

1.2,什么场景不适合创建索引

  1. 对于那些在查询中很少使用或者参考的列不应该创建索引。
  2. 对于那 些只有很少数据值的列也不应该增加索引。因为本来结果集合就是相当于全表查询了,所以没有必要。
  3. 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
  4. 当修改性能远远大于检索性能时,不应该创建索 引。

1.3,索引优缺点

  1. 优点:
    提高检索数据的速度
  2. 缺点:
    会减慢写入速度(insert及update的时候可能会重建索引)

2,索引分类

2.1,普通索引

explain create index index_name on user_info(name);

2.2,唯一索引

与普通索引类型不同的时:加速查询+列值唯一

CREATE UNIQUE INDEX  mail  on user_info(name)  ;

2.3 全文索引(更详细可以看https://blog.csdn.net/mrzhouxiaofei/article/details/79940958)

几个注意点

  1. MySQL 5.6 以前的版本,只有 MyISAM 存储引擎支持全文索引;
    MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引;
  2. 只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
  3. 对于中文,可以使用 MySQL 5.7.6 之后的版本,或者第三方插件。
  4. 如果需要全文索引的是大量数据,建议先添加数据,再创建索引;

2.3.1,为什么使用全文索引

你可能会说,用 like + % 就可以实现模糊匹配了,为什么还要全文索引?like + % 在文本比较少时是合适的,但是对于大量的文本数据检索,是不可想象的。全文索引在大量的数据面前,能比 like + % 快 N 倍,速度不是一个数量级,但是全文索引可能存在精度问题。

2.3.2,例子

create table test (
    id int(11) unsigned not null auto_increment,
    content text not null,
    primary key(id),
    fulltext key content_index(content)
) engine=MyISAM default charset=utf8;

insert into test (content) values ('a'),('b'),('c');
insert into test (content) values ('aa'),('bb'),('cc');
insert into test (content) values ('aaa'),('bbb'),('ccc');
insert into test (content) values ('aaaa'),('bbbb'),('cccc');

查询

select * from test where match(content) against('a');
select * from test where match(content) against('aa');
select * from test where match(content) against('aaa');
select * from test where match(content) against('aaaa');

我们会发现只有最后一个搜索有数据,这是因为最小搜索长度导致的,MySQL 中的全文索引,有两个变量,最小搜索长度和最大搜索长度,对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。(最小搜索长度,MyISAM 引擎下默认是 4,InnoDB 引擎下是 3)

2.4:组合索引

将几个列作为一条索引进行检索,使用最左匹配原则。

2.4.1,为什么使用组合索引

利用索引中的附加列,您可以缩小搜索的范围。组合索引的结构与电话簿类似,人名由姓和名构成,电话簿首先按姓氏对进行排序,然后按名字对有相同姓氏的人进行排序。如果您知 道姓,电话簿将非常有用;如果您知道姓和名,电话簿则更为有用,但如果您只知道名不姓,电话簿将没有用处(最左匹配原则)

所以说创建复合索引时,应该仔细考虑列的顺序。对索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引非常有用;仅对后面的任意列执行搜索时,复合索引则没有用处。

2.4.2最左匹配原则

各种不同条件下的结果(少数举例)

1.对于创建的多列索引,只要查询的条件中用到了最左边的列,索引一般就会被使用(查询的条数较少可能不会使用)

2. 对于使用 like 的查询,如果第一位是常量并且只有%号不在第一个字符,索引才可能会被使用:

//会使用索引
select * from company2 where name like '3%'\G;
//不会使用索引
select * from company2 where name like '%3'\G;

3、如果列名,记得是列的名字,是索引,使用 column_name is null 将使用索引

 select * from company2 where name is null\G;

4、用 or 分割开的条件,如果 or 前的条件中的列有索引,而后面的列中没有索引,那么涉及到的索引都不会被用到,例如:,必须or前后都有索引才能被使用,而且必须是单独索引

5,如果列是字符型,,传入的是数字,则不上‘’不会使用索引

6.联合查询(非范围的,就是没有查>多少这样的范围的数值)

//创建一个3列索引(a,b,c,d)

//查询条件为a :用到了索引a (长度为5)
explain  SELECT * from d001_index WHERE a = 1 ;

//查询条件为 b 、 c或者b :未用到索引

//查询条件为 a 、 b:用到了联合索引 a 、b (长度为10)
explain  SELECT * from d001_index WHERE a = 1 and b = 2 ;

//查询条件为 a、c :用到了联合索引a (长度为5)
explain  SELECT * from d001_index WHERE a = 1 and c = 3 ;

//查询条件为 a 、b、c、c:用到了联合索引a b c d (长度为20)
explain  SELECT * from d001_index WHERE a = 1 and b = 2 and c = 3  and d = 4 ;

//查询条件为 a or b :未用到索引
explain  SELECT * from d001_index WHERE a = 1 or b = 2;

7.联合范围查询

解释范围查询使用到第几列,则联合索引该列后面的字段的不能使用索引

特殊情况
不要取极端值测试,因为mysql优化器会通过索引查找的数量造成一定的影响,即使使用了索引,但是索引却没能生效 ,比如下的 3 变成 1 会受到影响,因为我的数据量中a最小就是 1

  1. explain SELECT * from d001_index WHERE a > 1 ; 没有使用索引,因为数据均匀分布在1 以上 (有1,但是和1比较了,所以也算在了里面)
  2. explain SELECT * from d001_index WHERE a > 3 ; 使用到了索引

创建了(a,b,c)的索引

//a > 3 使用了索引 a (长度为 5 )

//a = 1 and b > 1 :使用了联合索引 a、b(长度为10)
explain SELECT * from d001_index WHERE a = 1 and  b > 1 ;


//a = 5 AND b > 6 AND c = 7 :使用了联合索引 a、b(长度为10)
explain SELECT * from d001_index WHERE a = 5 AND b > 6 AND c = 7

小总结:

参考文章:https://www.cnblogs.com/forcheryl/p/7389798.html

如果有一个2列的索引(col1,col2),则已经对(col1)、(col1,col2)上建立了索引;
如果有一个3列索引(col1,col2,col3),则已经对(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;

总结:
1、b+树的数据项是复合的数据结构,比如(name,age,sex)的时候,b+树是按照从左到右的顺序来建立搜索树的,比如当(张三,20,F)这样的数据来检索的时候,b+树会优先比较name来确定下一步的所搜方向,如果name相同再依次比较age和sex,最后得到检索的数据;但当(20,F)这样的没有name的数据来的时候,b+树就不知道第一步该查哪个节点,因为建立搜索树的时候name就是第一个比较因子,必须要先根据name来搜索才能知道下一步去哪里查询。

2、比如当(张三,F)这样的数据来检索时,b+树可以用name来指定搜索方向,但下一个字段age的缺失,所以只能把名字等于张三的数据都找到(只用到name一个索引)(这种情况无法用到联合索引)

发布了36 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/s_xchenzejian/article/details/102530312