MySQL中的索引

什么是索引?有什么用?

相当于是一本书的目录,在MySQL中,可以快速定位到需要找到的数据
    在MySQL中查询一张表有两种方式可以来进行操作
    
    第一种:全表扫描,一条记录一条记录的扫描,直至扫描结束,扫描较慢
    
    第二种:索引检索(效率贼高),根本的原理是缩小了扫描的范围。
           虽然可以提高检索效率,但是也不能够随意的添加索引,因为数据库也需要不断的进行维护,表中的数据如果需要经常性的被修改
           索引需要重新进行排序,进行维护,需要成本。
         
         一本书比较少,没必要添加索引。但是数据量大的情况下,需要添加索引。
    	 添加索引的方式: 添加索引需要给某一个字段或者是某一些字段添加索引
    	select * from t_user where username = 'liguang';
        在对username没有添加索引的时候,会造成全表扫描。会扫描所有的字段,username的值是liguang的;
            

怎么创建索引对象?怎么删除索引对象?

什么时候需要考虑给字段加上索引?

1、数据量比较大的时候,需要考虑给所以来添加索引;(根据客户的需求和线上的要求)

​ 用户反映查询比较慢,所以来进行查询;

2、该字段经常出现在where字句中;(经常根据哪个字段来进行查询)

3、不经常发生改变的DML操作的字段;(因为字段经常进行修改,索引也需要进行维护)

注意:主键和具有unique约束的字段会自动加上索引,所以说根据主键来进行查询,效率较高;

查询SQL语句的执行计划,这个是使用于MySQL

mysql> explain select ename,job from emp where sal = 800;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
    
    观察这里的type字段的值为all,表示的是在进行全表扫描,扫了14行记录,extra表示的是各处使用;
    

会字段创建索引,再次使用explain计划;

// 在emp表的sal字段上创建sal索引。创建索引对象
create index emp_sal_index on emp(sal);

mysql> explain select ename,job from emp where sal = 800;
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra       |
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+
|  1 | SIMPLE      | emp   | ref  | emp_sal_index | emp_sal_index | 9       | const |    1 | Using where |
+----+-------------+-------+------+---------------+---------------+---------+-------+------+-------------+

再次查看对应的type,编程了ref,发现扫描的rows变成了1,只扫了1次;
    底层使用的是BTree这种数据结构,遵循着左小右大的原则;和TreeMap的遍历差不多,遍历是根据中序来进行查询的;
// 删除索引对象
drop index emp_sal_index on emp;

mysql> drop index emp_sal_index on emp;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

在对索引删除了之后,可以再次进行查询,看下结果

mysql> explain select ename,job from emp where sal = 800;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   14 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

索引底层采用的数据结构BTree

索引的实现原理:

mysql> select ename from emp;
+--------+
| ename  |
+--------+
| SMITH  |
| ALLEN  |
| WARD   |
| JONES  |
| MARTIN |
| BLAKE  |
| CLARK  |
| SCOTT  |
| KING   |
| TURNER |
| ADAMS  |
| JAMES  |
| FORD   |
| MILLER |
+--------+

现在有一条SQL语句:

select ename from emp where ename='smith';

当ename字段没有索引的时候,会进行全表扫描,效率上比较慢;给ename字段添加索引

create index emp_ename_index on emp(sal);

这句话一执行,会在内存或者是硬盘中生成索引。根据自己选择的存储引擎来进行判断到底是存储在硬盘中还是内存中去

如果是MYISAM存储引擎,那么将会存储在硬盘中去;如果是MEMORY,那么将会存储在内存中去;

// 用这种字符来进行模拟B树中的节点来进行排序
mysql> select ename from emp order by  ename asc; 
+--------+
| ename  |
+--------+
| ADAMS  |
| ALLEN  |
| BLAKE  |
| CLARK  |
| FORD   |
| JAMES  |
| JONES  |
| KING   |
| MARTIN |
| MILLER |
| SCOTT  |
| SMITH  |
| TURNER |
| WARD   |
+--------+

在内存或者是硬盘中生成对应的索引,这些索引会自动进行排序

索引分类:

单一索引:给一个字段添加索引;

复合索引:给多个字段联合添加索引;复合索引需要进行仔细分析,尽量考虑用单一索引来进行操作;

主键索引:主键上自动添加索引;

唯一索引:具有unique约束的字段自动添加索引;

索引什么时候失效:

1、模糊查询第一个通配符使用%会造成索引失效

select ename from emp where ename like '%A%'

这样子会让所以失效,不会走索引。因为不知道第一个索引到底是谁,不知道如何去进行查询;

所以一般模糊查询第一个不要添加%,但是还是需要根据具体的操作来进行决定。

2、索引列为null

3、查询的时候使用一个索引,不要使用多个索引,否则会造成后面的索引失效。

4、Not in 不走索引

5、进行函数操作不走索引

6、where条件是or的情况,不走索引

上一篇:where子句


下一篇:SQL的多表查询,Java外包是如何转正华为的