如何在开发阶段就尽量避免写出慢SQL?

463 阅读4分钟

本文已参与掘金创作者训练营第三期「话题写作」赛道,详情查看:掘力计划|创作者训练营第三期正在进行,「写」出个人影响力

前言

顾名思义,慢SQL就是指执行时间过长的SQL语句,那如果我们的系统中存在大量执行时间过长的慢 SQL,不仅会导致请求RT过高,如果短时间内请求访问量增高,也会因为慢 SQL占据数据库连接时间过长,而导致新来的请求获取不到数据库连接而报错。

如果提到慢SQL,可能大家第一印象就是没使用索引索引失效explain看一下SQL执行计划等等,所以提到慢SQL基本都是与索引挂钩,所以本文就从索引分类、索引失效、SQL执行计划进行分类讨论如何在开发阶段避免写出慢SQL。

当然当如果数据量级达到了一定程度,并不是说找到合适高效的索引就能达到我们预期的执行时长,这时可能就要通过分库分表进行处理了。

索引及分类

索引是帮助MYSQL高效获取数据的数据结构-->排好序的快速查找数据结构。

image.png 浅蓝色的块--->磁盘块
黄色的块------>指针
深蓝色的块----->数据项

P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块
真实的数据库都存在与叶子节点,非叶子节点不存储真实的数据,只存储指引搜索方向的数据项

查找过程:
如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一个IO,在内存中用二分继续查找确定19在17和35之间,锁定磁盘块1的P2指针,内存实践相比磁盘IO可忽略不计。通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,二分确定29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时在内存中二分查找到29,结束,总计三次io

主键索引

创建方式如下:

ALTER table table_name add primary key(col_name);

唯一索引

创建方式如下:

CREATE UNIQUE INDEX index_name ON table_name(col_name);

普通索引

创建方式如下:

REATE INDEX index_name ON table_name(col_name);

联合索引

创建方式如下:

CREATE INDEX index_name ON table_name(col_name_1,col_name_2);

explain查看SQL执行计划

使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MYSQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。

explain sql;

索引失效场景

1.最佳左前缀法则:如果索引了多列(复合索引),要遵守最左前缀法则。指的是查询从复合索引的最左列开始并且不跳过复合索引中得列(防止索引失效)

2.不要再索引列上做任何操作(计算、函数、(自动or手动)类型转型),会导致索引失效而转向全表扫描

3.存储引擎不能使用索引中范围条件右边的列。即复合索引中若复合索引中某个列参与了范围条件则该列后的所有列都会索引失效

例:复合索引--->(column1,column2,column3),若有条件查询 where cloumn1 = value1 and cloumn2>1 and column3=values3 则column3将失效

4.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),避免select *

5..mysql在使用不等于(!= 或者<>)的时候会导致索引失效而全表扫描

6.is null 或者 is not null 都会导致索引失效

7.like以通配符开始('%abc%')MySQL索引会失效而导致全表扫描。但是通配符只在右边出现不会导致索引失效(即通配符不可以出现在最左边)

解决like '%字符串.....'索引失效问题:使用覆盖索引,或者查询复合索引中部分列

8.字符串不加单引号会导致索引失效