常见的10个SQL语句性能优化策略

SQL语句性能优化策略

1. 为 WHERE 及 ORDER BY 涉及的列上建立索引

对查询进行优化,应尽量避免全表扫描,首先应考虑在 WHERE 及 ORDER BY 涉及的列上建立索引

2. where中使用默认值代替null

应尽量避免在 WHERE 子句中对字段进行 NULL 值判断,创建表时 NULL 是默认值,但大多数时候应该使用 NOT NULL,或者使用一个特殊的值,如 0,-1 作为默认值。
为啥建议where中使用默认值代替null,四个原因:

  1. 并不是说使用了is null或者 is not null就会不走索引了,这个跟mysql版本以及查询成本都有关;
  2. 如果mysql优化器发现,走索引比不走索引成本还要高,就会放弃索引,这些条件 !=,<>,is null,is not null经常被认为让索引失效;
  3. 其实是因为一般情况下,查询的成本高,优化器自动放弃索引的;
  4. 如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思也相对清晰一点;

3. 慎用 != 或 <> 操作符。

MySQL 只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的 LIKE。所以:应尽量避免在 WHERE 子句中使用 != 或 <> 操作符, 会导致全表扫描。

4. 慎用 OR 来连接条件

使用or可能会使索引失效,从而全表扫描; 应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。

5. 慎用 IN 和 NOT IN

IN 和 NOT IN 也要慎用,否则会导致全表扫描。对于连续的数值,能用 BETWEEN 就不要用 IN:select id from t where num between 1 and 3。

6. 慎用 左模糊like ‘%…’

模糊查询,程序员最喜欢的就是使用like,like很可能让索引失效。比如:

select id from t where name like%abc%select id from t where name like%abc’

而select id from t where name like‘abc%’才用到索引。
所以:

  1. 首先尽量避免模糊查询,如果必须使用,不采用全模糊查询,也应尽量采用右模糊查询, 即like ‘…%’,是会使用索引的;
  2. 左模糊like ‘%…’无法直接使用索引,但可以利用reverse + function index的形式,变化成 like ‘…%’;
  3. 全模糊查询是无法优化的,一定要使用的话建议使用搜索引擎,比如 ElasticSearch。

7. WHERE条件使用参数会导致全表扫描。

如下面语句将进行全表扫描:

select id from t where num=@num

因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推 迟到 运行时;

它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。

所以, 可以改为强制查询使用索引:

扫描二维码关注公众号,回复: 14941714 查看本文章
select id from t with(index(索引名)) where num=@num

8. 应避免WHERE 表达式操作/对字段进行函数操作

任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,
应尽量避免在 WHERE 子句中对字段进行表达式操作,应尽量避免在 WHERE 子句中对字段进行函数操作。

如:

select id from t where num/5=100
应改为:
select id from t where num=100*5

应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。 如:

select id from t where substring(name,1,3)=‘abc’

select id from t where datediff(day,createdate,2022-11-30)=0

应改为:

select id from t where name like ‘abc%select id from t where createdate>=2022-11-30and createdate<2022-12-1

9. 用 EXISTS 代替 IN 是一个好的选择

很多时候用exists 代替in 是一个好的选择

select num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)

10. 查询SQL尽量不要使用select *,而是具体字段

最好不要使用返回所有:select * from t ,用具体的字段列表代替 “*”,不要返回用不到的任何字段。select *的弊端:

(1)增加很多不必要的消耗,比如CPU、IO、内存、网络带宽;

(2)增加了使用覆盖索引的可能性;

(3)增加了回表的可能性;

(4)当表结构发生变化时,前端也需要更改;

(5)查询效率低;

猜你喜欢

转载自blog.csdn.net/qq_44936392/article/details/130491564