MySQL性能优化(三):索引


索引原理mysql


若是一本新华字典假如没有目录,想要查找某个字,就不得不从第一页开始查找,一直找到最后一页(若是要找的字在最后一页),这个过程很是耗时,这种场景至关于数据库中的全表扫描的概念,也就是循环表中的每一条记录看看该记录是否知足条件,扫描次数为表的总记录数。sql


新华字典中都会有目录都有查找方法(好比按拼音查找、按部首查找),假如按拼音查找,咱们根据拼音就能瞬速定位到要找的汉字,而这个汉字后面还有这个汉字对应的页数,咱们直接翻到该页就能找到,整个查找过程很是快,用时很是短。这个原理就是数据库中索引的原理。这里的按拼音查找、按部首查找是两种不一样的查找方式,经过每种方式都能快速找到,在数据库中也有不少查找方式,称之为索引方法,有BTREE、HASH两种方式数据库

图片

BTREE:一颗倒立的树,每一个节点都有父节点,父节点下面的节点称之为子节点(叶子节点),比父节点值小的位于父节点下面的左方,比父节点值大的子节点放置在父节点下面的右下方。ide

记录索引列的值和对应的记录所在的磁盘位置,每次排除掉一半, 检索一次至关排除掉2的n次幂,使用二叉树排除30次至关于全表排除10亿次。好比查询id=11的值,首先和6比,比6大就排除掉左边的,继续和9比较,11比9大,又排除掉左边的通常,和11进行比较,相等就找到告终果。当数据量很大的时候,每次都排除掉一半,排除的数据量是很是惊人的。工具

Hash:Hash索引只能等值匹配,想范围查询,左前缀查询都不适用, 其他大部分场景spa

为何要使用索引?code

  • 索引大大减小了存储引擎须要扫描的数据量orm

  • 索引能够帮助咱们进行排序以免使用临时表blog

  • 索引能够把随机IO变为顺序IO排序

索引类型


  • 主键索引(primary key):添加了主键就有了主键索引,能够在建立表的时候指定主键,也能够在建立成功以后再增长

  • 惟一索引(unique):添加了惟一约束就有了惟一索引,惟一索引能够有多个null

  • 普通索引(normal):通常是先建表,后面再建立索引,普通索引使用的最多

  • 全文索引(fulltext):主要针对文本段落等,全文索引只能应用MyISAM引擎

  • 空间索引(spatial): 使用较少,而且mysql支持的还很差

关于惟一性有两种作法:

  • 经过程序来保证数据的惟一性

  • 业务上具备惟一特性的字段,即便是多个字段的组合,也必须建成惟一索引。说明:不要觉得惟一索引影响了 insert 速度,这个速度损耗能够忽略,但提升查找速度是明显的;另外即便在应用层作了很是完善的校验控制,只要没有惟一索引,根据墨菲定律,必然有脏数据产生。(来自阿里巴巴Java开发手册)

关于全文索引:

全文索引只能用于MyISAM引擎,一般若是用到全文索引通常经过Elasticsearch、Solr、Lucene等技术来实现。

索引语法


建立索引

①语法

-- 建立普通索引:
create index 索引名 on 表(列1ASC|DESC】, 列2 ASC|DESC】) 

-- 建立惟一索引
create unique index on 表名(列名)
②索引命名规则
  • 主键索引名为 pk_字段名,pk即 primary key

  • 惟一索引名为 uk_字段名; uk即 unique key

  • 普通索引名则为 idx_字段名;idx即index的简称。

③索引字段

一个索引能够针对一个字段进行建立,也能够指定多个字段建立复合索引。

④在哪些列上适合添加索引

  • 频繁做为查询条件的列或者链接条件的列适合建立索引,即Where中的列或者是链接子句指定的列

  • 惟一性太差的字段不适合建立索引,如性别

  • 更新很是频繁的字段不适合建立索引

  • 不做为where条件的字段不要建立索引

  • 选用NOT NULL的列

  • 尽可能使用字段长度小的列做为索引

  • 使用数据类型简单的列(int 型,固定长度)

⑤索引顺序

ASC | DESC 选项 除非显式指定降序 (DESC),不然列以升序 (ASC) 排序。无论索引是升序排列仍是降序排列,在执行升序或降序 ORDER BY 操做时都会使用索引。可是若是经过混合的升序和降序属性来执行 ORDER BY,则仅当索引是用一样的升序和降序属性建立的时才使用索引。

-- 能够显式指定索引字段的顺序,默认为升续
CREATE INDEX idx_username ON tbl_user(username ASC);

-- 对于较长的字符内容能够指定前N个字节建立索引,不必为整个值都建立索引
CREATE INDEX idx_username ON tbl_user(contnet(20ASC);

-- 复合索引:基于多个字段共同建立索引(区分度最大的字段放在前面,常常会被使用到的列在前面)
CREATE INDEX idx_username_email ON tbl_user(username, email);

-- 删除索引
DROP INDEX idx_username ON tbl_user;

-- 查看某个表的索引,两种方式效果同样
SHOW INDEX FROM tbl_user;
SHOW KEYS FROM tbl_user;

⑥注意
  • 若是是先建表,表中有比较多的数据,此时再建立索引,建立完索引须要等一会,让索引在后台建立完再使用

  • 索引数量控制,单张表中索引数量不该超过5个,单个索引中的字段数不超过5个。

  • 索引存储的位置位于mysql安装的/xxx/data目录下, 索引能提升查询速度,但对update/delete/insert变慢,由于还要从新维护索引文件,通常状况下查询次数远大于增删改

查询索引

show index from 表名;
show keys from 表名;

修改索引

通常是先删除再建立

删除索引

- 删除重复和冗余的索引(第三方工具须要额外安装)
pt-duplicate-key-checker h=127.0.0.1

-- 更新索引统计信息及减小索引碎片
ANALYZE TABLE <table_name>

-- 清理碎片(注意会锁表)
OPTIMIZE table <table_name>
相关文章
相关标签/搜索