MYSQL之索引语法与使用

发布时间:2024年01月22日

索引分类

分类?????????????? 含义???????????????????????????????????????????????????? 特点???????????????????????????????????????? 关键字

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

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

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

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

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

分类??????????????? 含义??????????????? 特点????????????

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

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

聚焦索引选取规则:

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

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

如果表没有主键,或没有合适的唯一索引,则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性能分析

SQL执行频率

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

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

SHOW GLOBAL STATUS LIKE 'Com_______';

慢查询日志

慢查询日志记录所有执行时间超过指定参数(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

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;

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评估使用索引比全表更慢,则不使用索引

# 走全表扫描
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的联合索引

前缀索引

单列索引和联合索引

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

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

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

单列索引可能会回表查询

联合索引情况

设计原则

文章来源:https://blog.csdn.net/qq_44709053/article/details/135725972
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。