Sql 调优总结

1前言

Sql 语句调优对应用性能非常重要,看了几篇文章,总结了一下数据库优化的方法。

2 数据库 Sql 优化

1 对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

关于索引请看我的这篇文章 https://www.cnblogs.com/mhq-martin/p/8184328.html

SELECT sid
FROM Student
WHERE Gradeid=1

执行时间:17.609s (多次执行,在17s左右徘徊)

优化后:给Gradeid字段添加索引后

执行时间为:11.377s(多次执行,在11s左右徘徊)

备注:我们一般在什么字段上建索引?

这是一个非常复杂的话题,需要对业务及数据充分分析后再能得出结果。主键及外键通常都要有索引,其它需要建索引的字段应满足以下条件:

a、字段出现在查询条件中,并且查询条件可以使用索引;

b、语句执行频率高,一天会有几千次以上;

c、通过字段条件可筛选的记录集很小,那数据筛选比例是多少才适合?

这个没有固定值,需要根据表数据量来评估,以下是经验公式,可用于快速评估:

小表(记录数小于10000行的表):筛选比例<10%;

大表:(筛选返回记录数)<(表总记录数*单条记录长度)/10000/16

单条记录长度≈字段平均内容长度之和+字段数*2

2 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。

select sid from Student where num is null

最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库.

备注、描述、评论之类的可以设置为 NULL,其他的,最好不要使用NULL。

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select sid from Student where num = 0

3 应尽量避免在 where 子句中使用 != 或 <> 操作符,否则引擎可能放弃使用索引而进行全表扫描。

4 应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描。(用union all 代替)

GRADE_ID字段有索引,QUESTION_TYPE没索引

SELECT sid
FROM Student
WHERE Gradeid=15
OR Gradetype=1

优化方案:

SELECT sid
FROM Student
WHERE Gradeid=15
union all
SELECT sid
FROM Student
WHERE Gradetype=1

通过union all 方式,把有索引字段和非索引字段分开。索引字段就有效果了。

5 in 和 not in 也要慎用,否则会导致全表扫描

注:在mysql数据库中where 子句中对索引字段使用 in 和 not in操作符,引擎不会放弃使用索引。

注:在mysql数据库中where 子句中对不是索引字段使用 in 和 not in操作符,会导致全表扫描。

6 负向查询不能使用索引

select name from user where id not in (1,3,4);

应该修改为:

select name from user where id in (2,5,6);

7 前导模糊查询不能使用索引

如:

select name from user where name like '%zhangsan'

非前导则可以:

select name from user where name like 'zhangsan%'

建议可以考虑使用 Lucene 等全文索引工具来代替频繁的模糊查询。

8 数据区分不明显的不建议创建索引

如 user 表中的性别字段,可以明显区分的才建议创建索引,如身份证等字段。

9 在字段上进行计算不能命中索引

select name from user where FROM_UNIXTIME(create_time) < CURDATE();

应该修改为:

select name from user where create_time < FROM_UNIXTIME(CURDATE());

10 最左前缀问题

如果给 user 表中的 username pwd 字段创建了复合索引那么使用以下SQL 都是可以命中索引:

Java编程思想 数据库SQL语句的 优化总结

但是使用

select username from user where pwd ='axsedf1sd'

是不能命中索引的。

11 如果明确知道只有一条记录返回

select name from user where username='zhangsan' limit 1

可以提高效率,可以让数据库停止游标移动。

12 不要让数据库帮我们做强制类型转换

select name from user where telno=18722222222

这样虽然可以查出数据,但是会导致全表扫描。

需要修改为

select name from user where telno='18722222222'

13 如果需要进行 join 的字段两表的字段类型要相同

不然也不会命中索引。

原文地址:https://www.cnblogs.com/mhq-martin/p/9317010.html