SQL 性能优化 二
联表查询与临时表使用
1、不要有超过 5 个以上的表连接(JOIN),考虑使用临时表或表变量存放中间结果。少用子查询,视图嵌套不要过深,一般视图嵌套不要超过 2 个为宜;
2、避免使用临时表,除非却有需要,否则应尽量避免使用临时表,相反,可以使用表变量代替。大多数时候,表变量驻扎在内存中,因此速度比临时表更快,临时表驻扎在 TempDb 数据库中,因此临时表上的操作需要跨数据库通信,速度自然慢;
3、将需要查询的结果预先计算好放在表中,查询的时候再Select;
4、选择最有效率的表名顺序;
Oracle 的解析器按照从右到左的顺序处理 FROM 子句中的表名,FROM 子句中写在最后的表(基础表 driving table)将被最先处理,在 FROM 子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。
如果有 3 个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。
5、别名的使用,别名是大型数据库的应用技巧,就是表名、列名在查询中以一个字母为别名,查询速度要比建连接表快 1.5 倍;
关键字的使用
1、用 OR 的字句可以分解成多个查询,并且通过 UNION 连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用 UNION all 执行的效率更高。多个 OR 的字句没有用到索引,改写成 UNION 的形式再试图与索引匹配。一个关键的问题是否用到索引;
2、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数;
3、尽量使用 EXISTS 代替 select count(1) 来判断是否存在记录。count 函数只有在统计表中所有行数时使用,而且 count(1) 比 count(*) 更有效率;
4、提高 GROUP BY 语句的效率,可以通过将不需要的记录在 GROUP BY 之前过滤掉。下面两个查询返回相同结果,但第二个明显就快了许多;
低效:
SELECT position, AVG(salary) FROM payroll
GROUP BY position
HAVING position = 'assistant'
OR position = 'manager'
高效:
SELECT position, AVG(salary) FROM payroll
WHERE position = 'assistant'
OR position = 'manager'
GROUP BY position
存储过程与触发器
1、尽量将数据的处理工作放在服务器上,减少网络的开销,如使用存储过程;
存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的 SQL 语句,是控制流语言的集合,速度当然快。反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在 Tempdb 中。
2、在所有的存储过程中,能够用 SQL 语句的,就不要使用循环去实现;
3、最好不要使用触发器;
触发一个触发器,执行一个触发器事件本身就是一个耗费资源的过程;
如果能够使用约束实现的,尽量不要使用触发器;
不要为不同的触发事件(Insert、Update 和 Delete)使用相同的触发器;
不要在触发器中使用事务型代码。