1.索引的种类

  • 聚簇索引,非聚簇索引
  • 主键索引,唯一索引,普通索引(前缀索引),全文索引
  • 单值索引,复合索引
  • 二级索引
  • 覆盖索引

1.1 聚簇索引,非聚簇索引

参考文档:

https://www.cnblogs.com/jiawen010/p/11805241.html

https://learnku.com/articles/45521

总结(根据第二个博客):

  • 聚簇索引

    • 索引必须为唯一索引
    • 叶子节点存储的是整行数据
  • 非聚簇索引
    • 索引值不唯一
    • 叶子节点存储的是索引行和主键

Q:聚簇索引一定是主键吗?

A:不一定,但主键一定是聚簇索引。如果没有主键索引,InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引。

1.2.前缀索引

参考博客:https://blog.51cto.com/u_15144024/2860391

主要针对较长的varchar类型字段以及TEXT、BLOB类型类型。

通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。但这样也会降低索引的选择项。索引的选择性是指,不重复的索引值(也称为基数 cardinality)和数据表的记录总数(#T)的比值,范围从1/#T到1之间。索引的选择项越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。

对于BLOB、TEXT或者很长的varchar类型的列,必须使用前缀索引,因为mysql不允许索引这些列的完整长度。

诀窍在于要选择足够长的前缀以保证较高的选择性,同时又不能太长(以便节约空间)。前缀应该足够长,以使得前缀索引的选择性接近于索引整个列。换句话说,前缀的"基数"应该接近于完整列的"基数"

-- 计算完整列的选择性
select count(distinct city)/count(*) from city_demo;

mysql无法使用前缀索引做order by和group by,也无法使用前缀索引做覆盖索引

1.3.全文索引

参考博客:https://blog.csdn.net/mrzhouxiaofei/article/details/79940958

之前只能用myisam创建全文索引,5.6之后innodb也可以了

查找文本中的关键词,而不是直接比较索引中的值。它有许多需要注意的细节,如停用词、词干和复数、布尔搜索等。全文索引更类似于搜索引擎做的事情,而不是简单的where条件匹配。在相同的列上同时创建全文索引和基于值的B-Tree索引不会有冲突,全文索引适用于match against操作,而不是普通的where条件操作。

有时候后缀索引也有用途,mysql原生不支持反向索引,但是可以把字符串反转后存储,并基于此建立前缀索引。 姓名把名反转放前面,做名的右模糊查询,但中间的没法模糊查询

参考博客:https://blog.csdn.net/weixin_38106322/article/details/106583450

1.4.二级索引

主键索引之外的都可以统称二级索引

1.5.覆盖索引

:不需要回表查询;多字段创建一个索引,查询只需要返回覆盖索引包含的字段

2.索引的B+树如何生长的

3.索引优化

查询某张表有哪些索引:show index from tablename;

4.索引优化之explain

  • id:编号
  • select_type:查询类型
  • type:索引类型
  • table:表名
  • possible_keys:预测用到的索引
  • key:实际使用的索引
  • key_len:实际使用索引的长度
  • ref:表之间的引用
  • rows:被索引优化查询的数据个数
  • extra:额外信息

4.1 id

针对连表查询:

  • id值相同,从上往下,顺序执行
  • id值不同:id值越大越优先查询(在嵌套子查询时,先查内层,再查外层)
  • 数据小的表,优先查询(rows)
  • id值不同,id值越大越优先查询

4.2 select_type

  • primary:包含子查询SQL中的主查询(最外层)
  • subquery:包含子查询SQL中的子查询(非最外层)
  • simple:简单查询
  • derived:衍生查询(使用到了临时表)
    • 在from子查询中只有一张表
    • 在from子查询中,如果有table1 union table2,则table1就是derived

4.3 type

system > const > eq_ref > ref > range > index > all,要对type优化的前提是:有索引

system、const 理想情况

ref、range 实际能达到

  • system:只有一条数据的系统表,或衍生表只有一条数据的主查询

查询返回的字段有些有索引,有些没有

  • const:仅仅能查到一条数据的SQL,用于primary key或unique索引
  • eq_ref:唯一性索引,对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多、不能0)

    select ... from ...where name = ... 常见于唯一索引和主键索引
  • ref:非唯一性索引,返回匹配的所有行(0,多)
  • range:检索指定范围的行,where后面是一个范围查询(between..in,>,<=)

特殊:in有时候会失效,从而转为无索引all

  • index:查询全部索引中数据
  • all:查询全部表中数据

总结:

  • system/const:结果只有一条数据
  • eq_ref:结果多条,但是每条数据是唯一的
  • ref:结果多条,但是每条数据是0或是多条

4.4 possible_keys

如果possible_keys/key是null,则说明没用索引

4.5 key_len

:索引的长度,用于判断复合索引是否被完全使用

一个字符占3个字节,一个字节表示null,两个字节标识可变长度

4.6 extra

  • using filesort:性能消耗比较大,需要"额外"的依次排序(查询),常见于order by语句中
  • using tempoary:性能损耗大,用到了临时表,一般出现在groupby(已经有表了,但不适用,必须再来一张表)
  • using where:需要回原表
  • using index:性能提升,索引覆盖(覆盖索引)。原因,不读取原文件,只从索引文件中获取数据(不需要回表查询)
    • 如果用到了索引覆盖时,会对possible_keys和key造成影响

      • 如果没有where,则索引只出现在key中
      • 如果有where,则索引出现在key和possible_keys中
  • using join buffer:mysql主动优化,加了缓存
  • impossible where:WHERE子句始终为false,不能选择任何行 select ... from ... where 1 < 0;
  • using index condition:using index + 回表 + where 过滤

5.索引优化之慢日志查询

注:不要在生产环境测试(测试环境数据量最好和生产环境一致)

:mysql提供的一种日志记录,用于记录mysql中响应时间超过阈值(long_query_time 默认10s),默认是关闭的,最终部署是关闭。

查询mysql是否开启慢日志查询: show variables like'%slow_query_log%'



临时开启: set global slow_query_log = 1;

设置慢查询阈值:set global long_query_time = 5; (修改后,重新登录后起效,不需要重启服务)

在内存中开启;重启 mysql service restart mysql

永久开启:在 /etc/my.cnf 中追加配置:

slow_query_log=1
slow_query_log_file=/var/lib/mysql/localhost-slow.log
# 超时时间
long_query_time=3



查看超过阈值的sql:show global status like '%slow_queries%';

或者去指定的日志文件去看 /var/lib/mysql/localhost-slow.log

6.单表优化

  • 最佳左前缀,保持索引的定义和使用的顺序一致性
  • 索引需要逐步优化
  • 将含In的范围查询放where条件的最后,防止失效
  • 通过key_len证明in可以使索引失效

7.两表优化

teacher :tid,cid

course :cid,cname

索引往哪加?-小表驱动大表[一般情况下对于左外连接,给左表加索引;右外连接,给右表加索引]

8.三表优化

  • 小表驱动大表
  • 索引建立在经常查询的字段上

9.避免索引失效的一些原则

  • 复合索引,不要跨列或无序使用(最佳左前缀)
  • 复合索引,尽量使用全索引匹配
  • 不要在索引上进行任何操作(计算,函数,类型转换),否则索引失败
  • 对于复合索引,如果左边失效,右边全部失效
  • 复合索引不能使用不等于(!= <>)或is null(is not null),否则自身以及右侧所有全部失效;复合索引有 > ,则自身和右侧索引全部失效
  • %x% 会导致索引失效, x% 不会 ,或者用索引覆盖
  • 尽量不要使用类型转换(显式、隐式),否则索引失效
  • 尽量不要使用or,否则索引失效,将or左侧的索引失效

10.一些其他的优化方法

  • 如果主查询的数据集大,则使用in
  • 如果子查询的数据集大,则使用exist。 select...from table where exist/in (子查询);

exist: 将主查询的结果,放到子查询中进行条件校验,如果复合校验,则保留数据

  • order by 优化

    • using filesort:双路排序、单路排序(根据IO的次数)
    • 选择使用单路、双路;调整buffer的容量大小
    • 避免select * ...
    • 复合索引 不要跨列使用,避免using filesort
    • 保证全部的排序字段,排序的一致性(都是升序 或 降序)

mysql4.1 默认使用 双路排序(扫描两次磁盘 【1.从磁盘读取排序字段

{在buffer中进行的排序} 2.扫描其他字段】);4.1之后,默认使用单

路排序 (只读取一次【全部字段{在Buffer中进行排序}】),有一定

隐患,不一定是一次,可能是多次IO

原因:如果数据量特别大,则无法将所有字段的数据一次性读完,索引

会进行"分片读取"

注意:单路排序比双路排序,会占用更多的Buffer。如果数据大,可以

考虑调大buffer的容量大小:set max_length_for _sort_data = 1024

byte

如果max_length_for _sort_data太低(需要排序的列总大小超过了

max_length_for _sort_data定义的字节数),则mysql会自动从单路切

换到双路

MySQL学习(十)索引的更多相关文章

  1. 【笔记】MySQL学习之索引

    [笔记]MySQL学习之索引 一 索引简单介绍 索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可. 普通 ...

  2. MySQL学习13 - 索引

    一.索引的介绍 二 .索引的作用 三.常见的几种索引: 3.1 普通索引 3.2 唯一索引 3.3 主键索引 3.4 组合索引 四.索引名词 五.正确使用索引的情况 什么是最左前缀呢? 六.索引的注意 ...

  3. Mysql学习笔记—索引

    一.什么是索引 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 在数据 ...

  4. MySQL学习(十五)

    索引的概念 索引是数据的目录,能快速定位数据的位置.索引提高了查询速度,降低了增删改的速度.并非加的越多越好. 一般在查询频率高的列上加,而且在重复度低的列上加效果更好.如在性别列上不用加索引,但是身 ...

  5. MySQL学习(十二)

    视图 view 在查询中,我们经常把查询结果当成临时表来看, view是什么?view可以看成一张虚拟表,是表通过某种运算得到的一个投影. 表的变化会影响到视图 既然视图只是表的某种查询的投影,所以主 ...

  6. MYSQL学习(三) --索引详解

    创建高性能索引 (一)索引简介 索引的定义 索引,在数据结构的查找那部分知识中有专门的定义.就是把关键字和它对应的记录关联起来的过程.索引由若干个索引项组成.每个索引项至少包含两部分内容.关键字和关键 ...

  7. MySQL学习笔记——索引和视图

    索引(index)和管理索引 模式中的一个数据库对象 作用:在数据库中用来加速对表的查询 创建:自动在主键和唯一键上面创建索引 通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O 与表独立存放, ...

  8. mysql学习之索引

    首先,看一个例子,有一张大表,记录数超过1000,SELECT * FROM student WHERE name='xinan'; 如果没有索引,查找程序就得从头查找,很费时间,表越大越费时间.建立 ...

  9. MySQL学习(十六)

    MySQL高级部分 触发器 触发器是一类特殊的事务,可以监视某种数据操作(insert/update/delete),并触发相关的操作(insert/update/delete) 触发器创建语法之4要 ...

  10. MySQL学习(十四)

    utf8的bom问题 在xp下,用记事本创建utf8文件的时候,前面多了3个字节,这3个字节不用来显示,是用来辨识编码用的,EF BB BF告诉记事本,这是utf8编码. 存储引擎和事务简单介绍 引擎 ...

随机推荐

  1. 记事本默认编码改为UTF-8

    前端时间发现用记事本直接创建的记录目标信息的TXT文本再用sublime打开变成了乱码,才发现编码有问题,记事本直接创建的文本编码竟然是ANSI编码. 于是动手将记事本默认编码改为UTF-8. 记事本 ...

  2. Unity WebGL与JS脚本交互

    1.Unity调用JavaScript脚本方法 官网文档 老版本方法 之前Unity提供的Application.ExternalCall方法现在已经被设为过时弃用.(但是现在还能用,但是不知道什么时 ...

  3. 【Docker】基本使用

    服务 启动docker systemctl start docker 重启docker systemctl restart docker 停止docker systemctl stop docker. ...

  4. 启动anaconda的报错:There is an instance of anaconda navigator already running error

    首先调出控制台(win+r,输入cmd),然后在控制台输入 tasklist | findstr "pythonw" 在显示出pythonw.exe后,找到其后面的pid(数字), ...

  5. Mysql学习:4、DML命令(增删改查)及密码修改

    1.查询表中所有数据: select * from students; 2.插入数据: insert into students (id,name,email,address) values(1,'张 ...

  6. Ubuntu16.04配置网卡

    设置步骤: 1.路由器插电后,电脑使用网线,连接无线路由器任一LAN口,注意两者单独连接,先不要连接宽带网线.打开电脑浏览器,在地址栏输入192.168.100.1. 在路由器的管理界面,输入路由器的 ...

  7. Doris与mysql语法对照,差异篇

    ## SQL语法差异:### doris中不支持分组列再使用distinctMSYQL:```SQLselect DISTINCT mid from order_card_detail GROUP B ...

  8. Vue中nextTick的时序问题

    前言 Vue.$nextTick这个API相信很多人都用过,按照文档的解释,"在下次DOM更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM".我们通 ...

  9. PTA1003 我要通过! (20 分)

    PTA1003 我要通过! (20 分) "答案正确"是自动判题系统给出的最令人欢喜的回复.本题属于 PAT 的"答案正确"大派送 -- 只要读入的字符串满足下 ...

  10. 创建vue项目时所发送错误

    该错误的造成可能是以下情况: 1.所需插件可能没有安装齐全: 2.网络不好,更换网络可能会解决: 3.github无法访问,导致无法下载所需模板: (由于github是外网网站,该网站并不是每次访问都 ...