一、索引的概念

我们知道,在查询过程中,如果被查询的表没有索引,数据库会进行全表扫描,而如果添加了相应的索引,数据库会根据索引直接查找符合条件的数据。因此,索引的存在会大大提高查询效率。而索引其实就是一个特殊文件(InnoDB中索引是表空间的一部分),它包含碰上对表中所有记录的引用指针。

二、索引的分类

索引可以分为两种:聚簇索引和非聚簇索引。

(一)聚簇索引

聚簇索引是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分,每张表只能拥有一个聚簇索引。

(二)非聚簇索引

非聚簇索引使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。查询先通过索引查找到符合条件的地址,然后通过地址查再找数据。

(三)两种索引的区别

1.聚簇索引是和数据在一起的,通过索引即可一次性查询出数据。
2.非聚簇索引索引文件和数据是独立的,查询会先查找到符合条件的索引,通过地址进行二次查找表中的数据。
3.聚簇索引的效率比非聚簇索引的高。
4.由于节子节点(数据页)只能按照一颗B+树排序,故一张表只能有一个聚簇索引。辅助索引的存在不影响聚簇索引中数据的组织,所以一张表可以有多个辅助索引。

(四) 应用

1.InnoDB存储引擎

1.1 主键索引

InnoDB存储引擎主键索引使用的是聚簇索引,如果没有定义主键,innodb会选择非空的唯一索引代替。如果没有这样的索引,innodb会隐式的定义一个主键来作为聚簇索引。
优点:
    1.数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
    2.聚簇索引对于主键的排序查找和范围查找速度非常快
缺点:
    1.插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
    2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。

1.2 辅助索引(又叫非聚簇索引)

InnoDB的所有辅助索引都引用主键作为data域。
InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一种非常快速的主键查找性能。不过,它的辅助索引(Secondary Index, 也就是非主键索引)也会包含主键列,所以,如果主键定义的比较大,辅助索引也将很大。如果想在表上定义 、很多索引,则争取尽量把主键定义得小一些。InnoDB 不会压缩索引。
  文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。
  不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白:
   1、为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,
   2、用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

2.MyISAM存储引擎

MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。
在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复
由此可知,MyISAM存储引擎的索引都是非聚簇索引。但是由于其主键索引和辅助索引存储的都是键的地址,两者是独立的索引树,因此与InnoDB不同的是,辅助索引不用依赖和访问主索引的索引树。

参考博客:https://www.cnblogs.com/jiawen010/p/11805241.html

三、索引的优缺点

(一)优点

1.唯一索引可以保证数据唯一性。
2.添加索引可以大大提高查询效率。
3.加速表与表之间的连接。
4.通过使用索引,可以在查询过程中,使用优化隐藏器提高系统性能。

(二)缺点

1.创建和维护索引要消耗时间,而且这种时间会随着数据量的增加而增加。
2.索引会占用物理空间,聚簇索引占用的空间会更大。在InnoDB中,由于辅助索引B+树的叶子上会存储主键数据,因此主键长度也要尽量定义小一些。
3.由于增、删、改操作的时候,索引也要动态维护,这样也就降低了数据维护的速度。

四、创建索引的注意事项

一般来说,以下字段适合创建索引:

1.经常查询的字段:可以提高查询速度。
2.主键字段:强调主键的唯一性,有助于组织表数据的排列结构。
3.经常使用的连接键:加快连接速度。
4.经常需要进行范围查询的列:因为索引是有序的,其指定的范围也是连续的。
5.经常使用的排序字段:因为索引是有序的,可以利用索引的排序加快查询速度。
6.常用的where语句过滤条件。

一般来说,以下字段不太适合创建索引:

1.查询中很少使用的列:额外的索引会增大磁盘的需求,也会额外增加维护成本。
2.有大量重复数据的字段:对查询并没有明显的效果。
3.对于text,image,bit数据类型字段:这些列的数据量太大,可是我们查询中一般只截取使用其中的一小段数据。
4.对于修改远远大于检索需求的列,不应该建立索引。即使创建索引会增加查询效率,但是大大降低修改的性能,增加维护成本。

五、Mysql索引的类型和创建

这里不在过多赘述,请自行百度。
要说明的两点是
1.组合索引根据最左前缀的规则,查询会从最左边的索引字段开始组合。如果查询中没有使用索引中最左侧的字段,将不会使用该组合索引。

六、Mysql索引优化

优化不是一成不变的,版本不同,优化也有可能会不一样。以下仅供参考:

1.范围字段多使用聚簇索引:
因为聚簇索引只需要查找到所需数据的开头和结尾即可,而非聚簇索引要查到每一项数据对应的页码,再根据页码查找具体数据。
2.少数不同值的列推荐使用聚类索引;
3.频繁修改更新的列推荐使用非聚集索引;
4.where条件中,字段类型不匹配也不会使用索引;

比如SKU为8位数字组成的字符串,如果用 SKU='12345678’会使用索引,但是使用 SKU = 12345678 则不会使用索引。

5.LIKE模糊查询
索引根据最左前缀原则,右侧模糊查询可以使用索引,左模糊不行。例如:假设字段CLOUMN_1有索引,那么
CLOUMN_1 LIKE 'ABCD%' 可以使用索引;
CLOUMN_1 LIKE '%ABCD' 以及 CLOUMN_1 LIKE '%ABCD%' 不能使用索引。
6.使用短索引
如果列的值都比较长,如果前10或20个字符多数值是唯一的,就不需要对整个列的数据进行索引。短索引不仅可以提高查询速度,还可以节省磁盘和IO操作。
7.索引列排序
Mysql查询时只会使用一个索引,如果where条件中已经使用了索引,那么order by中的列是不会使用索引的。
因此如果默认排序可以符合要求的情况下,不要使用排序操作;
尽量不要包含多个列的排序,如果需要最好给这些列创建合适的复合索引。
8.where语句中,不要在索引列上使用函数或进行运算

如果对索引列进行运算或使用函数,会导致索引失效。

9.where条件中使用<> 或 != 也会做全表扫描,IS NULL/ IS NOT NULL 有时也会使索引失效

索引失效一般是由于mysql优化器会对查询的数据做一个数量的预估,如果我们用 is null,有空字段的索引一般是非聚簇索引。这种索引我们进行一次查询后,得到的是聚簇索引的主键,然后我们再进行回表,才能得到数据,这样优化器会根据空值的多少,自动选择开销比较小的方案进行优化。比如我们空值比较少,这时非聚簇索引查找的数据比较精准,开销也比较少,mysql就会使用索引进行查询。反之,如果空值比较多,这样我们如果使用聚簇索引先查询满足条件的主键,然后再通过大量的回表操作,才能得到我们想要的查询结果,频繁的IO就会造成性能开销较大,mysql就会选择不走索引的查询方式。也就是说能不能用到索引,mysql是根据具体情况来决定的。

10.尽量避免使用OR来连接条件,这样也会导致索引失效。

如果查询语句的条件中,我们必须使用OR,我们可以采用union all来代替,比如:

select cname from t where id = 10 or id = 20;
-- 我们可以改写为
select cname from t where id = 10
union all
select cname from t where id = 20;
11. in 和 not in 也要慎用;
12.如果过滤的数值是连续的,能用between就不要用in;
13.如果条件中使用了变量,mysql也会放弃索引,进行全表扫描;

因为sql只有在运行时,才会解析变量值,而优化器是在执行器之前运行的。这样优化器就无法获得变量的值,因而无法做为索引过滤输入项。不过,我们可以强制查询使用索引,比如:

select cname from t where id = $sid;
-- 可以使用下面的sql进行优化:
select cname from t with(index(索引名)) where id = $sid;
14.在使用复合索引时,必须使用到该索引的第一个字段做为条件才能保证查询过程使用该复合索引。尽量保持条件字段顺序与索引字段顺序一致。
15.在优化过程中,很多时候会用exists 代替in。
16.字段有大量重复数据的时候不建议建立索引,即使建立索引,mysql一般也不会使用索引,即使使用对性能也影响不大。如果数据量比较大,也会增加维护成本。
17.索引并不是越多越好,索引能提高查询效率,但也同时降低了增、删、改的效率,因为insert、select有时可能会重建索引。一个表的索引数一般不超过6个。

(一)MySQL优化之索引优化相关推荐

  1. 读薄《高性能MySql》(三)索引优化

    读薄<高性能MySql>(一)MySql基本知识 读薄<高性能MySql>(二)Scheme与数据优化 读薄<高性能MySql>(三)索引优化 读薄<高性能M ...

  2. sql查询索引语句_sql优化总结--基于sql语句优化和索引优化

    概述 最近做查询,统计和汇总.由于数据量比较庞大,大部分表数据上百万,甚至有的表数据上千万.所以在系统中做sql优化比较多,特此写一篇文章总结一下关于sql优化方面的经验. 导致查询缓慢的原因 1.数 ...

  3. MySQL如何利用索引优化ORDER BY排序语句

    MySQL索引通常是被用于提高WHERE条件的数据行匹配或者执行联结操作时匹配其它表的数据行的搜索速度. MySQL也能利用索引来快速地执行ORDER BY和GROUP BY语句的排序和分组操作. 通 ...

  4. MySQL数据库:SQL优化与索引优化

    一.索引优化: 1.like语句的前导模糊查询不使用索引: select * from doc where title like '%XX':   --不能使用索引 select * from doc ...

  5. MySql ORDER BY 索引优化

    上一篇:MySql 索引优化 MySql 支持两种方式的排序,FileSort 和 Index ,Index 效率高,它指的是 MySql 扫描索引本身完成排序.FileSort 会对数据使用一个外部 ...

  6. Mysql 架构及优化之-索引优化

    索引基础知识 索引帮助mysql高效获取数据的数据结构 索引(mysql中叫"键(key)") 数据越大越重要 索引好比一本书,为了找到书中特定的话题,查看目录,获得页码 sele ...

  7. mysql 更新索引_MySQL索引优化

    MySQL支持的索引类型 B-tree索引的特点 1.B-tree索引以B+树的结构存储数据 2.B-tree索引能够加快数据的查询速度 3.B-tree索引更适合进行行范围查找 B-tree结构图 ...

  8. mysql存储引擎 索引优化_MySQL存储引擎,索引及基本优化策略

    存储引擎 与Oracle, SQL Server这些数据库不同,MySQL提供了多种存储引擎.什么是存储引擎?存储引擎其实就是一套对于数据如何存储,查询,更新,建立索引等接口的实现.不同存储引擎特性有 ...

  9. Mysql优化之索引优化

    创建表 CREATE TABLE staffs( id INT PRIMARY KEY AUTO_INCREMENT, `name` VARCHAR(24) DEFAULT NULL COMMENT' ...

最新文章

  1. 2018年人工智能将赋能所有行业,未来市场将超过400亿美元
  2. 企业 SOA 设计(1)–ESB 设计
  3. 002-docker17.06安装
  4. Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法
  5. 推荐搜索系统论文干货集锦(持续更新)
  6. 给WIN7安装盘添加双PE3.0
  7. Saltstack的pillar组件(6)
  8. PCL——4.深度图像
  9. 并行算法:如何利用并行处理提高算法的执行效率?
  10. QCon北京2015:移动开发最佳实践专题前瞻
  11. Linux 快捷键总结
  12. [雨松MOMO程序研究院]Unity3D研究院之构建游戏框架与导出IOS项目(一)
  13. 玩转多元化主播打法,扶持达人红出圈,火山小视频的运营方法论
  14. EXCEL VBA批量下载URL链接地址图片、URL链接地址图片转为图片
  15. 分享10个可免费使用的网站CDN加速服务
  16. php 易宝支付,易宝支付
  17. 用大数据“魔镜”照出电商假货
  18. docker安装gitea
  19. 国内新锐买手品牌BSiEE 本涩启动第三届品牌代言人招募活动
  20. 百度站长推送常见问题汇总,出现4xx,5xx等问题如何解决

热门文章

  1. python爬取js动态网页_Python 爬取网页中JavaScript动态添加的内容(一)
  2. Java LineNumberReader getLineNumber()方法及示例
  3. 工作几年了,原来我只用了数据校验的皮毛
  4. JDK15正式发布,新增功能预览!
  5. 安卓手机使用linux(含图形界面)——Aid Learning
  6. 带头节点循环链表实现队列
  7. 深入了解EntityFramework——Fluent API
  8. python elif可以单独使用_Celery在python中的单独使用
  9. linux fcntl 设置阻塞,Linux fcntl函数设置阻塞与非阻塞
  10. python 捕获鼠标点击事件,在Python中的wx.Frame外部捕获鼠标事件