MYSQL之索引语法与使用

索引分类

分类               含义                                                     特点                                         关键字

主键索引    针对表中主键创建的索引                    默认自动创建,只能有一个          PRIMARY

唯一索引    避免同一个表中某数据列中的值重复  可以有多个                                   UNIQUE

常规索引    快速定位特定数据                               可以有多个        

全文索引    全文索引查找的是文本中的关键词      可以有多个                                   FULLTEXT

在InnoDB存储引擎中,根据索引的存储形式,又可分为以下两种:

分类                含义                特点            

聚焦索引    将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据    有且仅能有一个

二级索引    将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键    可以存在多个

聚焦索引选取规则

1、如果存在主键,主键索引就是聚焦索引

2、如果不存在主键,将使用第一个唯一索引作为聚焦索引

3、如果表没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚焦索引

select * form user where name=“Arm”;

利用二级索引找到对应聚焦索引(回表查询)然后找到对应数据

思考:

1、以下SQL语句,哪个执行效率高?为什么?

select * from user where id =10;

select * from user where name =‘arm’;

备注:id为主键,name字段创建的有索引

答:第一个语句执行效率高,因为执行第二个语句name字段是二级索引,还需要回表检索到聚焦索引,才能找到对应的数据。

2、InnoDB主键索引的B+Tree高度有多高?

假设:

一行数据的大小为1KB,一页(16K)中可以存储16行这样的数据。InnoDB的指针占用6个字节的空间,主键即使是bigint,占用的字节数为8。

树的高度为2可以存储的:

n*8+(n+1)*6=1024*16

主键:n = 1170

指针:n+1=1171

存储量(KB)1171*16=18736KB

树的高度为3可以存储:

1171*1171*16=21939856KB=21426MB=21GB

索引语法

创建索引

语法:

CREATE [UNIQUE|FULLTEXT]INDEX 索引名 ON 表名(被索引列名...);

案例

1、name字段为姓名字段,该字段的值可能会重复,为该字段创建索引

CREATE INDEX ON user1(name1);

2、phone手机号字段的值,是非空,且唯一,为该字段创建唯一索引

CREATE UNIQUE INDEX index_to_phone ON user1(phone);

3、为profession、age、status创建联合索引

CREATE INDEX idx_user_pro_age_sta  ON user1(profession,age,status);

4、为Email建立合适的索引来提升查询的效率

CREATE INDEX index_user_email ON user1(email);

查看索引

查看当前表所具有的索引:

show index from 表名;

删除索引

删除索引:

DROP INDEX 索引名 ON 表名;

SQL性能分析

1、SQL执行频率

MYSQL客户端连接成功后,通过show[session|global]status命令可以提供服务器状态信息。

通过如下指令可以查看当前数据库的insert,update,delete,select的访问频次:

SHOW GLOBAL STATUS LIKE 'Com_______';

2、慢查询日志

慢查询日志记录所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。MYSQL的慢查询日志默认并没有开启,需要在MYSQL的配置文件:

C:\ProgramData\MySQL\MySQL Server 8.0\my.ini

找到指定文件内,修改图下信息:

配置完成之后,通过以下指令重启MYSQL服务器进行测试,查看慢日志文件中记录的信息:C:\ProgramData\MySQL\MySQL Server 8.0\Data\**-slow.log

3、profiles详情

show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling参数,能够看到是否支持profiles,yes是支持。

select @@have_profiling;

默认profiling默认是关闭的,通过set语句在session/global级别开启profiling

查询是否开启:select

0关闭1开启

设置开启

set @@profiling=1;

然后执行一系列sql语句之后

通过

show profiles;

查看各个sql语句的耗时。

查询SQL语句在各个阶段执行耗时情况

show profiles for query query_id;

查询指定query_id的SQL语句CPU的使用情况

show profiles cpu for query query_id;

4、explain执行计划

explain执行计划各字段的含义:

explain sql语句

索引的使用

验证索引效率

在未创建索引之前,执行SQL语句查看SQL的耗时

select * from tb_sku where sn ='10000002258';

耗时20.03s

针对字段创建索引

create index idx_sku_sn on tb_sku(sn);

然后再次执行相同的SQL语句,再次查看SQL的耗时情况。

select * from tb_sku where sn ='10000002258';

耗时0.00s

使用原则

索引失效
最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳过某一列,索引将部分失效(后面的字段索引失效)。

create full_text index idx_pro_age_sta on tb_user(profession,age,status);
# 走索引
explain select * from tb_user where profession="软件工程" and age=31 and status="0";
# 走索引
explain select * from tb_user where profession="软件工程" and age=31;
# 走索引
explain select * from tb_user where profession="软件工程";
# 走索引 status失效
explain select * from tb_user where profession="软件工程" and status="0";
# 不走索引
explain select * from tb_user where age=31 and status="0";
# 不走索引
explain select * from tb_user where status="0";
范围查询

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效(规避办法加上>=)

# age后索引失效
explain select * from tb_user where profession="软甲工程" and age>60 and status='0';
# 规避办法
explain select * from tb_user where profession="软甲工程" and age>=60 and status='0';
索引列运算操作

不要在索引列进行运算操作,索引将失效

explain select * from tb_user where substring(phone,10,2)='15';
字符串类型不加引号

字符串类型的字段使用时,不加引号,索引将失效

explain select * from tb_user where profession="软甲工程" and age>=60 and status='0';
# status索引失效
explain select * from tb_user where profession="软甲工程" and age>=60 and status=0;
模糊查询

如果仅仅是尾部模糊匹配,索引不会失效,如果是头部模糊匹配,索引失效。

# 走索引
explain select * from tb_user where profession="软甲工程";
# 走索引
explain select * from tb_user where profession like "软甲%" ;
# 不走索引
explain select * from tb_user where profession like "%工程";
or连接的条件

用or分隔开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引豆瓣不会被用到。

解决办法:针对or条件后的字段建立索引

数据分布影响

如果MYSQL评估使用索引比全表更慢,则不使用索引

# 数据总量 190000000-1900000020
# 走全表扫描
select * from tb_user where phone>='190000005'
# 走索引
select * from tb_user where phone>='190000015'
SQL提示

SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

use index(给个建议)

explain select * from tb_user use index(idx_user_pro) where profession="软件工程";
 

ignore index(忽略)

explain select * from tb_user ignore index(idx_user_pro) where profession="软件工程";
 

force index(强制)

explain select * from tb_user force index(idx_user_pro) where profession="软件工程";
 
覆盖索引

覆盖索引:指的是查询字段在索引中全部能找到。

尽量使用覆盖索引(查询使用了索引,并且要返回的列能在该索引中全部找到),减少select*(要回表查询,使性能下降)

注意:

using index condition:查找使用了索引,但需要回表查询数据

usingwhere;using index:查找使用了索引,但需要的数据在索引列能找到,不需要回表查询

思考题:

建立一个包含 username和password的联合索引

前缀索引

当字段类型为字符串(varchar、text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时浪费很大的磁盘IO空间,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

创建语法
create index 索引名 on 表名(列名(选取长度n));
前缀长度计算

根据索引的选择性来决定,选择性指的是不重复的索引值和数据表中的记录总数的比值,索引选择性越高查询效率越高,唯一索引的选择性是1

select count(distinct email)/count(*)/ from tb_user;

select count(distinct substring(email,1,5))/count(*) from tb_user;
单列索引和联合索引

单列索引:一个索引包含一个列

联合索引:一个索引包含多个列

在业务场景中,如果存在多个查询条件,考虑针对查询字段建立索引时,建立联合索引,而非单列索引。

单列索引可能会回表查询

联合索引情况

设计原则

1、针对数据量较大,且查询较频繁的表建立索引。

2、针对于常作为查询条件、排序条件、分组操作的字段建立索引。

3、尽量选择分区度高的列作为索引,尽量建立唯一索引,区分度越高、使用索引的效率越高。

4、如果字符串类型是字段,字段的长度较长,可以根据字段特点建立前缀索引。

5、尽量使用联合索引、减少使用单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。

6、要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。

7、如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它,当优化器知道每列是否包含NULL值时,它可以更好的确定哪个索引最有效的用于查询。

  • 26
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值