今天面某家公司,然后问我SQL优化,感觉有点忘了,今天特此总结一下:

总结得是分两方面:索引优化和查询优化;

一. 索引优化:

1. 独立的列

在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法使用索引。

例如下面的查询不能使用 actor_id 列的索引:

#这是错误的
SELECT actor_id FROM sakila.actor WHERE actor_id + 1 = 5;

优化方式:可以将表达式、函数操作移动到等号右侧。如下:

SELECT actor_id FROM sakila.actor WHERE actor_id  = 5 - 1;

2. 多列索引

在需要使用多个列作为条件进行查询时,使用多列索引比使用多个单列索引性能更好。

例如下面的语句中,最好把actor_id 和 film_id 设置为多列索引。猿辅导有道题,详见链接,可以让理解更深刻。

SELECT film_id, actor_ id FROM sakila.film_actor
WHERE actor_id = 1 AND film_id = 1;

3. 索引列的顺序

让选择性最强的索引列放在前面。MySql最左前缀原则

索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,每个记录的区分度越高,查询效率也越高。

例如下面显示的结果中 customer_id 的选择性比 staff_id 更高,因此最好把 customer_id 列放在多列索引的前面。

SELECT COUNT(DISTINCT staff_id)/COUNT(*) AS staff_id_selectivity,
COUNT(DISTINCT customer_id)/COUNT(*) AS customer_id_selectivity,
COUNT(*)
FROM payment; #结果如下
staff_id_selectivity: 0.0001
customer_id_selectivity: 0.0373
COUNT(*): 16049

4. 前缀索引

对于 BLOB、TEXT 和 VARCHAR 类型的列,必须使用前缀索引,只索引开始的部分字符。

前缀长度的选取需要根据索引选择性来确定。

5. 覆盖索引

索引包含所有需要查询的字段的值。具有以下优点:

  • 索引通常远小于数据行的大小,只读取索引能大大减少数据访问量。

  • 一些存储引擎(例如 MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。

  • 对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。

以下为优先使用索引,避免全表扫描:

6. mysql在使用like进行模糊查询的时候把%放后面,避免开头模糊查询

因为mysql在使用like查询的时候只有使用后面的%时,才会使用到索引。

如:'%ptd_' 和 '%ptd_%' 都没有用到索引;而 'ptd_%' 使用了索引。

#进行全表查询,没有用到索引
EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_%';
EXPLAIN SELECT * FROM `user` WHERE username LIKE '%ptd_'; #有用到索引
EXPLAIN SELECT * FROM `user` WHERE username LIKE 'ptd_%';

再比如:经常用到的查询数据库中姓张的所有人:

SELECT * FROM `user` WHERE username LIKE '张%';

7. 在表中建立索引,优先考虑where、group by使用到的字段

8. 尽量避免使用in 和not in,会导致数据库引擎放弃索引进行全表扫描。

比如:

SELECT * FROM t WHERE id IN (2,3)

SELECT * FROM t1 WHERE username IN (SELECT username FROM t2)

优化方式:如果是连续数值,可以用between代替。如下:

SELECT * FROM t WHERE id BETWEEN 2 AND 3

如果是子查询,可以用exists代替。如下:

SELECT * FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.username = t2.username)

9. 尽量避免使用or,会导致数据库引擎放弃索引进行全表扫描

如:

SELECT * FROM t WHERE id = 1 OR id = 3

优化方式:可以用union代替or。如下:

SELECT * FROM t WHERE id = 1
UNION
SELECT * FROM t WHERE id = 3

10. 尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描

SELECT * FROM t WHERE score IS NULL

优化方式:可以给字段添加默认值0对0值进行判断。如下:

SELECT * FROM t WHERE score = 0

11. 尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描

同第1个,单独的列;

SELECT * FROM t2 WHERE score/10 = 9

SELECT * FROM t2 WHERE SUBSTR(username,1,2) = 'li'

优化方式:可以将表达式、函数操作移动到等号右侧。如下:

SELECT * FROM t2 WHERE score = 10*9

SELECT * FROM t2 WHERE username LIKE 'li%'

12. 当数据量大时,避免使用where 1=1的条件。通常为了方便拼装查询条件,我们会默认使用该条件,数据库引擎会放弃索引进行全表扫描

SELECT * FROM t WHERE 1=1

优化方式:用代码拼装sql时进行判断,没where加where,有where加and。

索引的好处:建立索引后,查询时不会扫描全表,而会查询索引表锁定结果。

索引的缺点:在数据库进行DML操作的时候,除了维护数据表之外,还需要维护索引表,运维成本增加。

应用场景:数据量比较大,查询字段较多的情况。

索引规则:

1.选用选择性高的字段作为索引,一般unique的选择性最高;

2.复合索引:选择性越高的排在越前面。(左前缀原则);

3.如果查询条件中两个条件都是选择性高的,最好都建索引;

参考:

1. 索引的特点和应用场景

2. SQL优化面试

二、查询优化

1. 使用Explain进行分析

Explain 用来分析 SELECT 查询语句,开发人员可以通过分析 Explain 结果来优化查询语句。

比较重要的字段有:

  • select_type : 查询类型,有简单查询、联合查询、子查询等;

  • key : 使用的索引;

  • rows : 扫描的行数;

2. 优化数据访问

  1. 减少请求的数据量

  • 只返回必要的列:最好不要使用 SELECT * 语句。

  • 只返回必要的行:使用 LIMIT 语句来限制返回的数据。

  • 缓存重复查询的数据:使用缓存可以避免在数据库中进行查询,特别在要查询的数据经常被重复查询时,缓存带来的查询性能提升将会是非常明显的。

  1. 减少服务器端扫描的行数

  • 最有效的方式是使用索引来覆盖查询。

3. 重构查询方式

1. 切分大查询

一个大查询如果一次性执行的话,可能一次锁住很多数据、占满整个事务日志、耗尽系统资源、阻塞很多小的但重要的查询。

  1. 分解大连接查询

将一个大连接查询分解成对每一个表进行一次单表查询,然后在应用程序中进行关联,这样做的好处有:

  • 让缓存更高效:对于连接查询,如果其中一个表发生变化,那么整个查询缓存就无法使用。而分解后的多个查询,即使其中一个表发生变化,对其它表的查询缓存依然可以使用。

  • 分解成多个单表查询,这些单表查询的缓存结果更可能被其它查询使用到,从而减少冗余记录的查询。

  • 减少锁竞争

  • 应用层进行连接,可以更容易对数据库进行拆分,从而更容易做到高性能和可伸缩。

  • 查询本身效率也可能会有所提升。例如下面的例子中,使用 IN() 代替连接查询,可以让 MySQL 按照 ID 顺序进行查询,这可能比随机的连接要更高效。

SELECT * FROM tab
JOIN tag_post ON tag_post.tag_id=tag.id
JOIN post ON tag_post.post_id=post.id
WHERE tag.tag='mysql'; SELECT * FROM tag WHERE tag='mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

SQL优化汇总的更多相关文章

  1. EntityFramework 知识点与sql优化汇总

    一.EntityFramework modelBuilder.Entity<Domain.UseOilPlanDetail>().HasRequired(x => x.MainOil ...

  2. ORACLE SQL性能优化汇总

    ORACLE SQL语句共享 Oracle SQL语句具备共享特性,为了不让ORACLE数据库重复解析相同的简单单表SQL语句,ORACLE在SGA系统共享区域内SBP共享池内存放的SQL语句将被所有 ...

  3. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  4. oracle sql优化笔记

    oracle优化一般分为:1.sql优化(现在oracle都会根据sql语句先进行必要的优化处理,这种应该用户不大了,但是像关联和嵌套查询肯定是和影响性能的) A.oracle的sql语句的条件是从右 ...

  5. SQL优化(zhuan)

    转自:http://www.jfox.info/SQL-you-hua 数据库的优化问题 一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出S ...

  6. SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  7. [SQL]SQL优化34条

    我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习.摘录.并汇总部分资料与大家分享! () 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE 的解析器按照从右到 ...

  8. SQL优化34条

    我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习.摘录.并汇总部分资料与大家分享! (1)      选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE 的解析 ...

  9. SQL优化(Oracle)

    (转)SQL优化原则 一.问题的提出 在应用系统开发初期.因为开发数据库数据比較少.对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,可是假设将应用系统提交实际应用后,随着数 ...

随机推荐

  1. mysql5.5 升级至5.7

    mysql5.5 升级至5.7 1.下载mysql5.7.32 官方下载地址 解压 tar xvf mysql.tar.gz mysql/ 2. 进入旧的mysql的bin目录下导出mysql的数据 ...

  2. STGAN: A Unified Selective Transfer Network for Arbitrary Image Attribute Editing 阅读笔记和pytorch代码解读

    一.论文采用的新方法 1.AttGan中skip connect的局限性 由于encoder中对特征的下采样实际上可能损失部分特征,我们在decoder中进行上采样和转置卷积也无法恢复所有特征,因此A ...

  3. 抓包一张tcpdump小抄就够了

    作者简介 李先生(Lemon),高级运维工程师(自称),SRE专家(目标),梦想在35岁买一辆保时捷.喜欢钻研底层技术,认为底层基础才是王道.一切新技术都离不开操作系统(CPU.内存.磁盘).网络等. ...

  4. https://www.cnblogs.com/wclwcw/p/7515515.html

    https://www.cnblogs.com/wclwcw/p/7515515.html

  5. HTTP/1HTTP/2HTTP/3

    https://mp.weixin.qq.com/s/fy84edOix5tGgcvdFkJi2w

  6. socket 的使用

    基于TCP协议的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 server端 import socket sk = socket.socket() sk.bind( ...

  7. 为什么在使用LESS 除法计算时会出问题

    hello,各位小伙伴们好,最近一直有小伙伴问我为什么写Less的时候,发现除法有了问题,在生成的css文件中,不给我们输出正确结果了. 直接抛结论: LESS 版本升级,EasyLess插件 新版本 ...

  8. 反射型XSS

    反射型XSS漏洞详解 http://www.ttlsa.com/safe/xss-description/ 一.原理 如果一个应用程序使用动态页面向用户显示错误消息,就会造成一种常见的XSS漏洞.通常 ...

  9. CS代理+proxychains+nmap进行内网扫描

    前提:拿下边界机之后,进入内网,想用nmap怎么办? CS可以开启代理,但是是socks4的代理,只能使用tcp协议,所以nmap使用的时候要使用-sT选择使用tcp_协议,要使用-Pn不使用ICMP ...

  10. 关于webservice实现web接口

    package service; import java.util.List; import javax.jws.WebMethod;import javax.jws.WebService; /** ...