工作中, 我们经常需要编写 SQL 脚本, 对数据库进行增, 删, 改, 查, 很少会考虑到 Sql 性能优化
1. 前言
大家好, 我是安果!
工作中, 我们经常需要编写 SQL 脚本, 对数据库进行增, 删, 改, 查, 很少会考虑到 Sql 性能优化
实际上, 从性能角度考虑, 有很多 Sql 关键字都有它们各自的使用场景; 如果使用恰当, 能大大地提升后端服务的响应效率
下面以 MySQL 为例, 罗列出几个比较实用的小 Tips
2. union,union all,or
union [all] 代表联合查询, 即: 将多个查询结果合并起来成一个结果并返回
PS:union 联合查询针对每一个查询结果, 必须保证列数量, 列数据类型及查询顺序一致
语法如下:
- # 以两张表的联合查询为例
- # table_one: 表一
- # table_two: 表二
- # 表一中的查询字段: table_one_field1,table_one_fileld2...
- # 表二种的查询字段: table_two_field1,table_two_field2...
- # 注意: 表一, 表二查询字段数目, 字段类型, 字段顺序应该保持一致
- select table_one_field1,table_one_fileld2...
- from table_one
- union [all]
- select table_two_field1,table_two_field2...
- from table_two;
其中, union,union all,or 三者的区别如下:
union
表链接后会利用字段的顺序进行排序, 以此筛选掉重复的数据行, 最后再返回结果
因此, 当数据量很大时效率很低
union all
相比 union,union all 在表链接时不会删除重复的数据行, 直接返回表联合后的结果
因此, union all 执行效率要高很多, 在不需要去重和排序时, 更推荐使用 union all
or
or 用于 SQL where 子句中, SQL 脚本可读性更高, 但是它会引起全表扫描, 根本不走索引查询
所以通常情况下, union [all] 查询会利用索引进行查询, 执行效率要高于 or; 但是当 or 条件中查询列相同, or 的执行效率要高于 union
3. group by + having,where
group by 分组查询, 根据一个或多个列对结果集进行分组, 一般配合聚合函数使用
语法如下:
# 查询字段: 多个查询字段
select 查询字段..., 聚合函数...
from table_one where 条件语句 group by 分组字段...having 分组条件;
- # 比如
- select red_num1,count(red_num1)
- from dlt where create_at>='2021-11-01' group by red_num1;
其中, having 和 where 使用上有下面区别:
where
在 group by 分组前执行, 将查询结果按照条件过滤数据
需要注意的是, where 无法与聚合函数一起使用
having
只能配合 group by 使用, 在分组之后执行, 用于过滤满足条件的组
需要注意的是, 分组是一个耗时的操作, 建议在分组前使用 where 对数据进行一次过滤, 然后再进行分组
比如, where 搭配 having 一起使用
- # 查询表 dlt
- # 首先, 使用 where 通过时间过滤数据
- # 然后, 使用字段 red_num1+group by 对数据进行分组
- # 最后, 使用 having 对分组后的数据再进行一次过滤
- select red_num1,count(red_num1)
- from dlt where create_at>='2021-10-01' group by red_num1 having count(red_num1)>=2;
- 4. exists,in
exists 用于 where 子句中, 一般用于判断子查询中是否会返回数据, 如果返回的数据不为空, 则为 True, 否则为 False
PS:exists 也可以搭配 not 使用, 查询出不满足子查询语句的数据
语法如下:
-- exists 使用
select *
from 表一 where exists(select * from 表二 where 条件判断语句);
-- not exists 使用
select *
from 表一 where not exists(select * from 表二 where 条件判断语句);
in 同样用于 where 子句中, 筛选出某个表字段存在于多个值中的所有数据
关键字 in 常见的 2 种使用方式如下:
-- in 使用
-- 方式一
select *
from 表名 where 字段 in(过滤字段 1, 过滤字段 2, 过滤字段 3...);
-- 方式二
select *
from 表名 1
where 字段 1 in (select 字段 2 from 表名 2 where condition)
由于 SQL 做子查询最优方案是小表驱动大表, 对于 in 来说是子查询表驱动外表, 当子查询表数据少于主表数据时推荐使用
而 exists 是外表驱动子查询表, 因此当外表数据少于子查询表时更推荐使用
来源: http://database.51cto.com/art/202111/692215.htm