MySQL语句优化


文章目录

    • 1、MySQL的执行顺序
    • 2、基础SQL优化
      • 2.1建表优化
        • 使用varchar代替char
        • 使用**数值**代替**字符串**类型
        • 字段设置为not null
        • 批量插入性能提升
      • 2.2查询优化
        • select 具体字段
        • 避免在where子句中使用or来连接条件
        • 连续查询尽量用between
        • 多表查询用join
        • 使用like时能用只用**一个**%就不建议用%%
        • 精确属性类型匹配
        • 使用limit限制返回记录数
        • 不要有超过5个以上的表连接
        • inner 、left 、right join,优先使用inner join
        • 尽量使用union all替代union
        • 先过滤再分组


1、MySQL的执行顺序

  1. from 如果有笛卡尔积就会和另外一张表生成中间表Temp1
  2. on 筛选关联表符合表达式的数据,由Temp1生成Temp2
  3. where 过滤不符合条件的数据
  4. group by 分组
  5. having 对分组后的记录进行聚合
  6. select 属性筛选
  7. distinct 去重
  8. order by 排序
  9. limit 限制返回记录

2、基础SQL优化

2.1建表优化

使用varchar代替char

例:

#正例
 create table course(cname varchar(50));
#反例
 create table course(cname char(50));

理由:

  • varchar变长字段按数据内容实际长度存储,存储空间小,可以节省存储空间
  • char按声明大小存储,不足补空格
  • 其次对于查询来说,在一个相对较小的字段内搜索,效率更高
使用数值代替字符串类型
  • 主键(id):primary key优先使用数值类型如int
  • 性别(sex):0-代表女,1-代表男;
字段设置为not null

​ 尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。

批量插入性能提升
INSERT INTO student (id,name) VALUES(1,'lyf'),(2,'lyc');
  • 默认新增SQL有事务控制,导致每条都需要事务开启和事务提交;而批量处理是一次事务开启和提交。

2.2查询优化

select 具体字段
#正例
SELECT id,name FROM stu
#反例
SELECT * FROM stu
  • 只取需要的字段,节省资源
  • select * 查询时,可能不会用到索引,造成全表扫描
避免在where子句中使用or来连接条件
#正例
SELECT id,name FROM stu where id=1
SELECT id,name FROM stu where age=18
#反例
SELECT id,name FROM stu where age=18 or id=1
  • 使用or可能会使索引失效,从而全表扫描
  • 对于or没有索引的这种情况,假设它走了id的索引,但是走到查询条件时,它还得全表扫描。也就是说整个过程需要三步:全表扫描+索引扫描+合并。如果它一开始就走全表扫描,直接一遍扫描就搞定。虽然mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引还是可能失效的
连续查询尽量用between

​ 在连续数值的查询中,能使用between的情况下,尽量使用between,而不使用in。in和not in可能会导致全表查询。

多表查询用join

多表查询数据,使用inner join,left/right join来代替子查询。因为子查询需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。

使用like时能用只用一个%就不建议用%%

​ 双%查询会导致mysql引擎放弃使用索引而进行全表扫描查询,查询时尽量把%放后面,或者不适用%。

精确属性类型匹配

​ 例如:select id from user where id=‘3’;如果id 建立的varchar类型的走索引,如果写成select id from user where id=3不走索引。

使用limit限制返回记录数

​ 如果查询返回数据量很大,就会造成查询时间过长,网络传输时间过长。同时大量数据返回可能没有实际意义。如返回上千条甚至更多,用户也看不过来。就可以用limit进行分页。

不要有超过5个以上的表连接
  • 关联的表个数越多,编译的时间越大
  • 每次关联内存中都生成一个临时表
  • 应该把连接表拆开成较小的几个执行,可读性更高
  • 阿里规范中,建议多表联查三张表以下
inner 、left 、right join,优先使用inner join

三种连接如果结果相同,优先使用inner join,如果使用left join左边表尽量小

  • inner join是等值连接,返回的行数比较少,所以性能相对会好一点
  • 使用左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少。这是mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优
尽量使用union all替代union
SELECT * FROM ...
UNION ALL
SELECT * FROM ...
  • union和union all的区别是,union会自动去掉多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复
  • union:对两个结果集进行并集操作,去重不包括重复行,相当于distinct,同时进行默认规则的排序
先过滤再分组
select id,sex from stu 
where 表达式
group by sex;
  • 把不需要的记录过滤掉再分组

你可能感兴趣的:(SQL,mysql,数据库,sql)