“二八原理”是一个普遍的真理,特别是在计算机的世界中,那就是20%代码资源占用了80%的总资源消耗。SQL语句也是一种代码,因此它也符合这个原理。在进行SQL调优的时候应该把主要精力放到这20%最消耗系统资源的SQL语句中,不要想把所有的SQL语句都调整到最优状态。
基本功:
一、索引
索引是数据库调优最根本的优化方法。根据索引的顺序与数据表的物理顺序是否相同,可以把索引分成两种类型:聚簇索引和非
聚簇索引。
汉语字典的拼音目录是聚簇索引(按拼音排序)偏旁部首则是非聚簇索引(虽然有笔画数排,但有相同的笔画)每一个表只能有
一个聚簇索引,但费聚簇索引可以有多个。索引会占据一定量的存储空间,也会降低数据插入、更新和删除的速度,所以应该只
创建必要的索引。
索引也会造成存储碎片问题。当删除一条记录时会导致对应索引中该记录的对应项为空也不会被删除,长时间操作会出现大量的
存储碎片。这些碎片不仅占用了存储空间,而且降低了数据库运行的速度。可以重建索引解决主流的数据库管理系统(DBMS)有
reindex、rebuild等,也可手动重建。
二、SQL优化
1、抵消的where 1 = 1
使用1 = 1的过滤条件之后数据库系统就会无法使用索引等查询优化策略,系统会被迫对每行数据进行扫描也就是全表扫
描,等同于*查询
2、select语句中避免使用*
除非确定需要检索表里所有的列,否则将会检索出多余的列,增加网络的负载和资源消耗。即使要检索表内所有的列,也不
要使用select * ,因为这是一个低效的方法。DBMS在解析的过程中会将*依次转换成所有的列名,这意味着将消耗更多的
时间。
3、尽量使用参数化查询
这样不仅可以避免SQL注入漏洞攻击,最重要的是数据库会对这些参数化SQL执行预编译。这样查询重复语句时可以提升执
行速度
4、调整where子句中的连接顺序
DBMS一般采用自下而上的顺序解析where句子,根据这个原理,表连接最好写在其他where条件之前,那样可以过滤最
大数量记录
如:select * from T_Persion
where 25 < (select count(*) from T_Manager where FManagerid = 2)
and FSalary > 5000
and FPosotion = ‘Manager’
5、尽量将多余的SQL语句压缩到一句SQL中
现有20本书,重新放到书架上去,按编号放,每5本放一个柜子(柜子也按顺序放),如何更新?一条一条来更新?当然
不!update T_Book set BGroupId = BId/5
6、用where子句替换having
要避免使用having子句,因为having只会在检索所有记录之后才对结果集进行过滤
7、用Exists替代In,用表连接替换Exists。多表连接查询时可提高查询效率
8、避免在索引列上使用计算
如果索引列是计算或函数的一部分,DBMS将不会使用索引而使用全表扫描
如:select count(ID) from T_Person
9、用union all 替换 union
使用union合并两个结果集时,会尝试对重复的记录合并,即检索结果中不会有重复的记录。这样如果不希望它合并或结果
中不会有重复的记录,可以使用union all
10、避免隐式类型转换造成的全表扫描
如:select * from T_Person where level = 10
由于数值类型的优先级高于字符串类型,因此DBMS会解释成select * from T_Person where To_INT(level) = 10
从而是level(索引)进行了计算,索引失败
11、防止索引范围过宽
使用is not null 或者<>判断,可能造成记录数太多
使用like的时候'a%'会使用索引,而'a%c'和'%c'会使用全表扫描
12、需要null时怎么办?
null值出现在任何计算字段或字符串连接或普通函数中,那么结果永远是null
null值出现在聚合函数中,null值会被忽略
三、其他
开窗函数 函数名(列)OVER(选项)
开窗函数与聚合函数一样,对行集组进行聚合计算,不仅像普通聚合函数一样,每组返回一个值,开窗函数可以为每组返回
多个值
with语句
用于处理多次重复查询的子语句