索引
什么是索引?
索引是在数据库表的字段上添加的,是为了提高查询效率存在的一种机制。
一张表的一个字段可以添加一个索引,当然,多个字段联合起来也可以添加索引。
索引相当于一本书的目录,是为了缩小扫描范围而存在的一种机制。
在mysql数据库当中索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同。
索引的实现原理
- 在任何数据库当中主键都会自动添加索引对象。
- 在mysql中,一个字段上如果有unique约束的话,也会自动创建索引对象。
- 在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都有一个硬盘的物理存储编号。
- 在mysql中,索引是一个单独的对象,不同的存储引擎以不同的形式存在,不管索引存储在哪里,索引在mysql中都是一个树的形式存在。(自平衡二叉树)
建议不要随意添加索引,因为索引也是需要维护的,太多的话反而会降低系统的性能。
建议通过主键查询,建议通过unique约束的字段进行查询,效率比较高。
索引怎么创建?怎么删除?语法是什么?
创建索引
//给emp表的ename字段添加索引,起名:emp_ename_index
create index emp_ename_index on emp(ename);
删除索引
//将emp表上的emp_ename_index索引对象删除
drop index emp_ename_index on emp;
索引失效
失效第一种情况
select * from emp where ename like '%T';
ename上即使添加了索引,也不会走索引
原因:是因为模糊匹配当中以%开头了。
尽量避免模糊查询的时候以%开始。
这是一种优化的手段/策略。
失效第二种情况
使用or的时候会失效,如果使用or那么要求or两边的条件字段都要有索引,才会走索引,如果其中一条边有一个字段没有索引,那么另一个字段上的索引也会失效。所以这就是为什么不建议使用or的原因。
可以使用union替代or
失效第三种情况
使用复合索引的时候,没有使用左侧的列查找,索引失效。
什么是复合索引?
两个字段,或者更多的字段联合起来添加一个索引,叫做复合索引。
mysql> create index emp_job_sal_index on emp(job,sal);
Query OK, 0 rows affected (0.34 sec)
Records: 0 Duplicates: 0 Warnings: 0
//使用了索引
mysql> explain select * from emp where job ='MANAGER';
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | emp | NULL | ref | emp_job_sal_index | emp_job_sal_index | 30 | const | 3 | 100.00 | NULL |
+----+-------------+-------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------+
1 row in set (0.13 sec)
//没有使用索引
mysql> explain select * from emp where sal=800;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 14 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.12 sec)
失效的第四种情况
在where当中索引列参加了运算,索引失效。
mysql> create index emp_sal_index on emp(sal);
Query OK, 0 rows affected (0.55 sec)
Records: 0 Duplicates: 0 Warnings: 0
//该查询表示查询出sal等于799的数据
mysql> explain select * from emp where sal+1=800;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 14 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.03 sec)
失效的第五种情况
在where中索引列使用了函数
mysql> explain select * from emp where lower(ename) ='smith';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | emp | NULL | ALL | NULL | NULL | NULL | NULL | 14 | 100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.03 sec)
索引是各个数据库进行优化的重要手段,优化的时候优先考虑的因素就是索引。
索引在数据库当中分了很多类:
-
单一索引:一个字段上添加索引
-
复合索引:两个字段或者多个字段添加索引
-
主键索引:主键添加索引
-
唯一性索引:具有unique约束的字段上添加索引
…
注意:唯一性比较弱的字段上添加索引用处不大。