一、索引作用

提供了类似于书中目录的作用,目的是为了优化查询

(一)、索引种类

1、B树索引(Balance Tree)

作用

Btree的设计理念,就是让查询能够快速锁定范围,特别适合于范围查询。

种类

B树

B+树 相邻叶子节点上有双向指针

B*树 相邻非叶子节点上有双向指针

构建过程

1、数据排序

2、排序后的结构,均匀的落在各个leaf节点上

3、下层提取leaf节点的范围+指针构成No-leaf节点

5、下层提取No-leaf节点范围+指针构成root节点

2、Hash索引

3、R树

4、Full text

5、GIS

(二)、BTREE在MySQL中的应用

聚簇索引

1. 前提

a. 建表时有主键,主键选择为聚簇索引

b.没有主键,选唯一

c.都没有,生成6字节隐藏索引

建议:使用数字自增列创建为主键

2. 功能

a录入数据时,按照聚簇索引组织存储数据, 在磁盘上有序存储数据行

在一个区中,数据行从逻辑到物理都是有序的。

b. 加速查询

where id条件

辅助索引回表查询

3. 构建过程

a.Leaf节点:整表数据行所在的数据页

b. No-Leaf节点: 下层叶子节点ID范围+指针

c. ROOT节点:下层No-Leaf节点ID范围+指针

辅助索引

1. 前提

需要按照查询条件创建合理的辅助索引

2. 功能

加速查询:利用辅助索引作为查询条件是才能加速

3. 构建过程

a.Leaf节点:索引键值+主键ID,根据索引键值排序后生成

b. No-Leaf节点: 下层叶子节点键值范围+指针

c. ROOT节点:下层No-Leaf节点键值范围+指针

回表

查询完辅助索引之后,得到主键值,回聚簇索引树查询。

联合索引

联合索引应用要满足最左原则

1、联合索引构建:idx(a,b,c)

叶子结点

1. 提取a,b,c+id

2. 按照a,b,c进行排序

3. 生成叶子节点

枝节点

1.提取最左列的范围+指针

根节点

提取枝节点范围+指针

2、联合索引建立规范

a. 建立联合索引时,选择重复值最少的列作为最左列。

b. 使用联合索引时,查询条件中,必须包含最左列,才有可能应用到联合索引

3、索引应用注意问题

回表

影响:

IO量增多

IO次数增多(IOPS)

随机IO增多

减少方法:

使用联合索引联合索引

精细化查询条件

尽量使用唯一值多的列作为查询条件,并建立索引

优化器:MRR(Multi-Range-Read)

查看所有优化器

select @@optimizer_switch;

设置优化器状态

set global optimizer_switch='mrr=on';

功能:

1. 辅助索引查找后得到ID值,进行自动排序

2. 一次性回表,很有可能受到B+TREE中的双向指针的优化查找。

索引树高度

1、数据行

分表、归档、分布式

2、索引列值长度

前缀索引(字符串列)

3、主键过长

主键最好使用自增数字列

4、数据类型选择

合适的、简短的

(三)、索引管理操作

1、查询索引

①、desc 表名称;

例:desc t1;

PK(PRI) --> 主键(聚簇索引)

MUL --> 辅助索引

UK --> 唯一索引

②、show index from t1;

2、添加索引

alter table 表名 add index 索引名(列);

例:alter table t100w add index idx_k2(k2);

添加联合索引

alter table 表名 add index 索引名(列1名,列2名);

例:alter table t100w add index idx_k1_num(k1,num);

添加前缀索引

alter table 表名 add index 索引名(列名(取值位数));

例:alter table city add index idx_n(name(5));

判断前缀长度多少合适:

select count(distinct(left(列名,取值长度))) from city 表名;

select count(distinct(left(name,5))) from city ;

删除索引

alter table 表名 drop index 索引名;

(四)、执行计划

1、获取SQL语句执行计划

desc SQL

explain SQL

2、分析

select_type:查询类型

table:此次查询访问的表

partitions:分区表

type:索引查询的类型

ALL:没有使用到索引,全表扫描

查询条件没建立索引

有索引不走

index:全索引扫描

range:索引范围扫描

> < >= <= betweed and like

in or

条件列值重复值少

改写union all

重复值多,没必要改写

ref:辅助索引等值查询

eq_ref:多表连接查询中,非驱动表的连接条件是主键或唯一键时

const(system):主键或唯一键等值查询

NULL

possible_keys:可能会应用的索引

key:最终选择的索引

key_len:

索引覆盖长度,主要是用来判断联合索引应用长度

列的key_len长度,按照每列的最大预留长度来做的计算

ref

rows:需要扫描的行数

filtered:过滤

extra:额外信息

using filesort:额外的排序操作

(五)、应用场景

1、数据库慢

①、应急性的慢

show full processlist; ----> 找到慢语句 ----> explain SQL ---> 优化索引、改写语句

查看正在运行命令 查看执行计划

②、间歇性慢

slowlog ----> 慢语句 ---> explain SQL ---> 优化索引、改写语句

(六)、索引应用规范

1、建立索引的原则(DBA运维规范)

说明

为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索

2、索引创建原则

①、建表时一定要有主键,一般是个无关自增列数字列,可以降低索引树高度

②、选择唯一键索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录

③、尽量使用前缀来索引

如果索引字段的值很长,最好使用值的前缀来索引

④、限制索引的数目

3、索引的数目不是越多越好索引条目过多所产生的问题

(1) 每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。

(2) 修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

(3) 优化器的负担会很重,有可能会影响到优化器的选择.

删除不再使用或者很少使用的索引(percona toolkit)

大表加索引,要在业务不繁忙期间操作

尽量少在经常更新值的列上建索引

4、不走索引的情况(开发规范)

①、没有查询条件,或者查询条件没有建立索引

②、查询结果集是原表中的大部分数据,应该是15-25%以上。

③、索引本身失效,统计信息不真实(过旧)

手动更新统计信息:

ANALYZE TABLE 库名.表名;

例:ANALYZE TABLE world.city;

④、查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等)

⑤、隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.

<> ,not in 不走索引(辅助索引)

like "%_" 百分号在最前面不走

(七)优化器针对索引的算法

1、自优化能力

①、MySQL索引的自优化-AHI(自适应HASH索引)

MySQL的InnoDB引擎,我们能够手动创建的只有Btree

AHI作用:

自动评估"热"的内存索引page,生成HASH索引表。

帮助InnoDB快速读取索引页。加快索引读取的效果。

相当与索引的索引

②、MySQL索引的自优化-Change buffer

比如insert,update,delete 数据。

对于聚簇索引会立即更新。

对于辅助索引,不是实时更新的。

在InnoDB 内存结构中,加入了insert buffer(会话),现在版本叫change buffer。

Change buffer 功能是临时缓冲辅助索引需要的数据更新。

当我们需要查询新insert 的数据,会在内存中进行merge(合并)操作,此时辅助索引就是最新的。

2、可选的优化器算法-索引

①、优化器算法查询

select @@optimizer_switch;

index_merge=on,

index_merge_union=on,

index_merge_sort_union=on,

index_merge_intersection=on,

engine_condition_pushdown=on,

index_condition_pushdown=on,ICP,索引下推

作用:

SQL层做完过滤后,只能用a,b的部分辅助索引,

将c列条件的过滤下推到engine层,进行再次过滤。

排除无用的数据页。

最终去磁盘上拿数据页。大大减少无用IO的访问。

mrr=on,mrr_cost_based=on,MRR : Multi Range Read

作用: 减少回表。减少随机IO。

开关方法:

set global optimizer_switch='mrr=on,mrr_cost_based=off';

SNLJ 普通嵌套循环连接伪代码:

for each row in A matching range {

block

for each row in B {

A.xx = B.yy ,send to client

}

}

block_nested_loop=on,作用

在 A和B关联条件匹配时,不再一次一次进行循环。采用块循环连接。

A表中需要关联的数据,现在join buffer缓冲

而是采用一次性将驱动表的关联值和非驱动表匹配.一次性返回结果

主要优化了CPU消耗,减少了一部分IO消耗。

触发条件:非驱动表的连接条件有辅助索引

batched_key_access=off,作用,使用来优化非驱动表的关联列有辅助索引。

BNL+ MRR的功能。

开启方式:

mysql> set global optimizer_switch='mrr=on,mrr_cost_based=off';

mysql> set global optimizer_switch='batched_key_access=on';

重新登陆生效

materialization=on,

semijoin=on,

loosescan=on,

firstmatch=on,

duplicateweedout=on,

subquery_materialization_cost_based=on,

use_index_extensions=on,

condition_fanout_filter=on,

derived_merge=on

②、修改优化器算法

方法一:配置文件中修改

PS:重启生效

vim my.cnf

optimizer_switch='batched_key_access=on'

#优化器='算法=开/关'

方法二:命令行中修改

PS:重新登录生效

set global optimizer_switch='batched_key_access=on';

set global optimizer_switch='算法=开/关';

方法三:执行命令时修改(hints)

SELECT /*+ NO_RANGE_OPTIMIZATION(t3 PRIMARY, f2_idx) */ f1

FROM t3 WHERE f1 > 30 AND f1 < 33;

SELECT /*+ BKA(t1) NO_BKA(t2) */ * FROM t1 INNER JOIN t2 WHERE ...;

SELECT /*+ NO_ICP(t1, t2) */ * FROM t1 INNER JOIN t2 WHERE ...;

SELECT /*+ SEMIJOIN(FIRSTMATCH, LOOSESCAN) */ * FROM t1 ...;

EXPLAIN SELECT /*+ NO_ICP(t1) */ * FROM t1 WHERE ...;

3、8.0 版本索引的新特性

①、不可见索引。invisable/visable index

针对优化器不可见。但是索引还在磁盘存在,还会自动维护。

对于索引维护时,不确定索引是否还有用。这时可以临时设定为invisable。

②、倒序索引

select * from t1 where c = order by a ASC , b desc ;

idx(c,a, b desc )

(八)、优化器默认优化规则

1、选择驱动表

默认选择方式(非驱动表):

按照on的条件列,是否有索引,索引的类型选择。

1. 在on条件中,优化器优先选择有索引的列为非驱动表。

2. 如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。

2、关于驱动表选择的优化思路

理论支撑:

mysql> desc select * from city join country on city.countrycode=country.code ;

mysql> desc select * from city left join country on city.countrycode=country.code ;

查询语句执行代价:

mysql> desc format=json select * from city join country on city.countrycode=country.code ;

mysql> desc format=json select * from city left join country on city.countrycode=country.code ;

实践检验: (可以通过 left join 强制驱动表)

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

默认驱动表

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

(九)、多表连接优化总结

1、驱动表选择

①、让优化器自己决定

(1). 在on条件中,优化器优先选择有索引的列为非驱动表。

(2). 如果两个列都有索引,优化器会按照执行的代价去选择驱动表和非驱动表。

②、自主选择

left join强制驱动表

查询语句执行代价:

mysql> desc format=json select * from city join country on city.countrycode=country.code ;

mysql> desc format=json select * from city left join country on city.countrycode=country.code ;

关于驱动表选择的优化思路

理论支撑:

mysql> desc select * from city join country on city.countrycode=country.code ;

mysql> desc select * from city left join country on city.countrycode=country.code ;

实践检验: (可以通过 left join 强制驱动表)

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city left join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

默认驱动表

[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='world' --query="select * from city join country on city.countrycode=country.code ;" engine=innodb --number-of-queries=2000 -uroot -p123 -verbose

不管是优化单表或多表,重点是在于索引和语句本身优化。

mysql设置id值为索引值_MySQL 索引相关推荐

  1. MySQL设置当前时间为默认值的方法

    方法一.是用alert table语句: 复制代码代码如下: use test_db1;  create table test_ta1(  id mediumint(8) unsigned not n ...

  2. mysql设置主键初始默认值

    mysql设置主键默认开始值 在Navicat 中输入一下命令(默认以1000开始) List itemalter table resource AUTO_INCREMENT=1000; 如果报错输入 ...

  3. mysql设置id重新从1开始自增

    mysql设置id重新从1开始自增 在测试程序时,通常会把id变得非常大,而且也会导致id不连续,我们可以让id从1开始重新自增 首先我们应该先清空表中数据 新建查询,然后执行一条 sql语句,再插入 ...

  4. mysql索和使用引的创建_MySQL索引的创建与使用

    索引有很多,且按不同的分类方式,又有很多种分类.不同的数据库,对索引的支持情况也不尽相同. 声明:本人主要简单示例MySQL中的单列索引.组合索引的创建与使用. 索引的创建 建表时创建 CREATE ...

  5. mysql 索引 原理_MySQL索引实现原理分析

    目前大部分数据库系统及文件系统都采用B-Tree(B树)或其变种B+Tree(B+树)作为索引结构.B+Tree是数据库系统实现索引的首选数据结构.在MySQL中,索引属于存储引擎级别的概念,不同存储 ...

  6. mysql查询索引位置_mysql索引在什么位置

    mysql索引的位置在[数据库安装目录\data\databasename].索引是存储引擎用于快速找到记录的一种数据结构.索引对于良好的性能非常关键. MySQL中索引的简介 (视频教程推荐:mys ...

  7. MySQL建立的索引看_MYSQL索引问题:索引在查询中如何使用?看了很多资料都只说索引的建立。是否建立了就不用再理会?...

    # 有这样一个表 P mysql> create table P (id int primary key, name varchar(10) not null, sex varchar(1), ...

  8. mysql查询id为5的数据类型_MySql学习05---数据类型

    MySql支持多种数据类型,主要有数值类型.日期/时间类型和字符串类型. 数值数据类型:包括整数类型TINYINT.SMALLINT.MEDIUMINT.INT.BIGINT.浮点小数数据类型FLOA ...

  9. mysql 索引 二_MySql索引(二)

    所有MySQL列类型可以被索引.根据存储引擎定义每个表的最大索引数和最大索引长度. 所有存储引擎支持每个表至少16个索引,总索引长度至少为256字节.大多数存储引擎有更高的限制. 索引的存储类型目前只 ...

最新文章

  1. Python Numpy 教程(使用 Jupyter 和 Colab)
  2. ubuntu虚拟机卡住开机_虚拟机Ubuntu开机问题及解决方法
  3. S5PV210裸机之Nandflash
  4. thinkphp漏洞_【组件攻击链】ThinkCMF 高危漏洞分析与利用
  5. 文本框换行_word的段落标记与换行,你真的知道么?
  6. 5G时代下的移动边缘计算(MEC)探索系列之四
  7. 什么是 CNC?什么是电脑锣?学 CNC主要学什么?
  8. ESP32黑客帝国数字雨动画,矩阵它来了,ESP32+ST7789V液晶屏Arduino
  9. oracle sql 实现三张表左连接查询
  10. 2021最后一个月了,你找到带回家的那个她了吗?送你999朵玫瑰。
  11. Scala基础:类和构造器
  12. SQL连接MYSQL出现对象名无效_SQL数据库时提示对象名'XXX' 无效
  13. 基于电商直播SDK快速实现一个淘宝直播APP【内附源码】
  14. 人工智能+大数据+云计算
  15. 数据库的事务ACID特性以及MySQL如何保持事物特性
  16. 计算机图形学中的常用模型
  17. 软件安全建设【学习笔记】
  18. 曼谷梦幻世界主题公园有什么好玩的
  19. 【Excel--高级筛选】学习总结
  20. 运维(1) Jenkinsfile+Dockerfile+Nginx实现前端Vue自动化部署

热门文章

  1. 深度学习在目标检测中的应用及其tensorflowAPI实践(三)
  2. 微信公众账号开发框架总结
  3. 保障4-0321任务打卡
  4. 搜索引擎已死?ChatGPT访问量创新高:面前只剩三家
  5. Python:openpyxl这一篇就够了
  6. 网络上整理的google baidu 搜索框嵌入网页代码
  7. 4月21号软件更新资讯合集.....
  8. 使用tinyxml读xml文件信息到结构体
  9. python range()函数循环效果
  10. python学习笔记-结构化