【mysql学习三】——索引搜索优化

前言

索引是sql语句优化的一部分,在实际的应用中当我们存在大量的数据需要查询的时候,提升查询效率最好的方式就是建立有效的索引,那索引是什么,如何用,并且如何去建立一个有效的索引,这些问题本篇可以给你解惑!

索引的基本操作

1.查询表中所含有的索引:

show index from tb_item;
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
| tb_item |          0 | PRIMARY  |            1 | id          | A         |         914 |     NULL |   NULL |      | BTREE      |         |               | YES     |
| tb_item |          1 | cid      |            1 | cid         | A         |           2 |     NULL |   NULL |      | BTREE      |         |               | YES     |
| tb_item |          1 | status   |            1 | status      | A         |           1 |     NULL |   NULL |      | BTREE      |         |               | YES     |
| tb_item |          1 | updated  |            1 | updated     | A         |          46 |     NULL |   NULL |      | BTREE      |         |               | YES     |

2.创建索引:

create index idx_status on tb_item(status);

3.删除索引:

drop index idex_stautus on tb_item;

索引目的:

索引是对排好序的快速查找数据结构,对where和order by都有一定的影响。索引本身很大,不可能存放在内存中,索引是以文件的方式存储在磁盘上。目的是为了提高查找的效率。

索引分类:

  1. 单值索引:一个索引只包含单独的一个列,一个表中可以有多个单列索引(非聚集索引)
  2. 唯一索引:索引列的值必须唯一,但允许有空值(聚集索引)
  3. 复合索引:一个索引包含多个列

聚集索引:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。
非聚集索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。
更多具体的内容可以参考博客:聚集索引与非聚集索引的总结

索引数据结构:

1.btree树
2.hash树

MyISAM索引结构采用了b+tree,INNODB采用也是b+tree。虽然结构一致但是实现的方案确实不一样的。之前的学习中我们知道MyISAM数据库目录下存在了myi,myd,frm,innodb文件目录有idb,frm。这也就是说明MyISAM的索引文件和数据文件是分开存放的,
具体的实现方案:

  • .MyISAM叶节点的data域存放的是数据记录的地址,索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

  • 与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。如果是主键索引,那么记录的主键的值本身就是查询到的值,但是InnoDB的所有辅助索引都引用主键作为data域索引,辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录

索引适用范围:

1.主键自动建立唯一索引
2.频繁作为查询条件的字段应该创建索引
3.查询中与其他表管理字段,外键关系建立索引
4.不频繁更新,where条件中用到的字段创建创建索引
5.查询中排序的字段
6.数据量大,并且重复数据不多

索引注意事项:

1.在where条件为(><,!=,isnull,isnotnull)的条件之前写索引,因为范围以后的索引会导致索引失效;

explain select id,cid from tb_item where cid=76 order by updated;

展示结果是:

| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                                 |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+---------------------------------------+
|  1 | SIMPLE      | tb_item | NULL       | ref  | cid           | cid  | 8       | const |  213 |   100.00 | Using index condition; Using filesort |

explain分析计划中最重要的是id,type,key,extra,其中extra为using filesort是最糟糕的一种情况,所以优化方法是创建复合索引:

create index index_cu on tb_item(cid,updated);

再次执行分析结果如下:

| id | select_type | table   | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+---------+------------+------+---------------+----------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | tb_item | NULL       | ref  | cid,index_cu  | index_cu | 8       | const |  213 |   100.00 | Using where; Using index |
+----+-------------+---------+------------+------+---------------+----------+---------+-------+------+----------+--------------------------

发现extra指标变成了using index是最好的一种情况。
但是如果cid的条件不是一个const,变成范围值,执行的结果又会发生变化:

mysql> explain select id,cid from tb_item where cid>76  order by updated;
+----+-------------+---------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key      | key_len | ref  | rows | filtered | Extra                                    |
+----+-------------+---------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------------+
|  1 | SIMPLE      | tb_item | NULL       | range | cid,index_cu  | index_cu | 8       | NULL |  721 |   100.00 | Using where; Using index; Using filesort |
+----+-------------+---------+------------+-------+---------------+----------+---------+------+------+----------+------------------------------------------+
1 row in set, 1 warning (0.00 sec)

extra指标再次变成了using filesort,所以证明where条件是一个范围值那么会导致以后的索引失效;

2.不要在索引上进行任何操作(计算,函数,类型转换),否则失效

3.left join或者right join,建立索引位置相反,左连接索引建立在右边的表上,右连接建立在左边的表上;

4.减少使用select *,采用查询的列与索引列一致(即覆盖索引)

5.like通配符开头(‘%abc…’),这个条件索引和以后索引都会失效,而且like条件为(‘abc%’)要用覆盖索引

6.创建的复合索引,最左前缀索引不存在,后面的索引都会失效

献上索引优化的口诀:

全值索引我最爱,最左前缀要遵守
带头大哥不能死,中间兄弟不能断
索引列上少计算,范围之后全失效
like百分写最右,覆盖索引不写*
不等空值还有or,索引失效要少用
var引号不能丢,sql高级也不难

【参考博客】

https://www.cnblogs.com/zz-tt/p/6609828.html
https://blog.csdn.net/a379850992/article/details/55655495
https://www.kancloud.cn/kancloud/theory-of-mysql-index/41855

总结

关于索引的使用暂时讲解到这里,如果有疑问请及时联系我!感谢浏览!

你可能感兴趣的:(【mysql学习三】——索引搜索优化)