一、 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。按需查询。sql
ORACLE在解析的过程当中, 会将’*’ 依次转换成全部的列名, 这个工做是经过查询数据字典完成的, 这意味着将耗费更多的时间 。数据库
Q:一个sql屡次利用,能够省代码量啊,这矛盾了...编程
二、 避免使用不兼容的数据类型oracle
select emp_name form employee where salary > 3000;
在此语句中若salary是Float类型的,则优化器很难对其进行优化,由于3000是个整数,咱们应在编程时使用3000.0而不要等运行时让DBMS进行转化。函数
三、适当利用索引,where、order by、group by、表关联涉及的字段。可尽可能避免全表扫描。测试
在使用索引时必定要按索引对应字段的顺序进行引用优化
放弃使用索引而进行全表扫描的状况:orm
1)where子句中对字段进行null值判断,如:排序
select id from t where num is null;索引
能够在num上设置默认值0,确保表中num列没有null值,而后这样查询:
select id from t where num = 0;
--- 尽可能避免数据库存null,例如可设默认值0。
2)where子句中使用!=或<>操做符
3)or,用union或in代替or
如:
select id from t where num = 10 or num = 20;改成
select id from t where num = 10
union
select id from t where num = 20;
4)用union all代替 union
当SQL 语句须要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 而后在输出最终结果前进行排序. 若是用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会所以获得提升. 须要注意的是,UNION ALL 将重复输出两个结果集合中相同记录. 所以各位仍是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操做会使用到SORT_AREA_SIZE这块内存. 对于这块内存的优化也是至关重要的
5)in 和 not in,如:
Select id from t where num in (1, 2, 3);改成
Select id from t where num between 1 and 3;
对于连续数值,能用between就不要用in。
用exists替代in,not exists替代not in,由于exists引入的子查询只是测试是否存在符号子查询中指定条件的行,效率较高。Not in效率最低。
select num from a where num in(select num from b) ;
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num);
6)like ‘%abc%’,尽可能不要左边也用%,或者a%c
7)where字句中对字段进行函数操做,where子句中“=”左边进行函数/算术运算等,如:
select id from t where num/2 = 100;
select id from t where substring(name,1,3)='abc'; --name以abc开头的id
select id from t where datediff(day,createdate,'2005-11-30')=0; --'2005-12-1'生成的id
应改成:
select id from t where num = 100*2;
select id from t where name like 'abc%' ;
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1';
8)使用日期值做为索引,而为了实现比较操做,可能须要将这个日期值转换为字符串,这样将致使在查询过程当中没法用到这个日期索引值。
9)ORDER BY 子句只在两种严格的条件下使用索引.
ORDER BY中全部的列必须包含在相同的索引中并保持在索引中的排列顺序.
ORDER BY中全部的列必须定义为非空
四、选择最有效率的表名顺序(只在基于规则的优化器中有效)
ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最早处理,在FROM子句中包含多个表的状况下,你必须选择记录条数最少的表做为基础表。若是有3个以上的表链接查询, 那就须要选择交叉表(intersection table)做为基础表, 交叉表是指那个被其余表所引用的表。
五、WHERE子句中的链接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的链接必须写在其余WHERE条件以前, 那些能够过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
六、用Where子句替换HAVING子句,将不须要的记录在GROUP BY 以前过滤掉
避免使用HAVING子句, HAVING 只会在检索出全部记录以后才对结果集进行过滤。这个处理须要排序,总计等操做. 若是能经过WHERE子句限制记录的数目,那就能减小这方面的开销. (非oracle中)on、where、having这三个均可以加条件的子句中,on是最早执行,where次之,having最后,由于on是先把不 符合条件的记录过滤后才进行统计,它就能够减小中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,由于它过滤数据后 才进行sum,在两个表联接时才用on的,因此在一个表的时候,就剩下where跟having比较了。在这单表查询统计的状况下,若是要过滤的条件没有涉及到要计算字段,那它们的结果是同样的,只是where可使用rushmore技术,而having就不能,在速度上后者要慢若是要涉及到计算的字 段,就表示在没计算以前,这个字段的值是不肯定的,根据上篇写的工做流程,where的做用时间是在计算以前就完成的,而having就是在计算后才起做 用的,因此在这种状况下,二者的结果会不一样。在多表联接查询时,on比where更早起做用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表 后,再由where进行过滤,而后再计算,计算完后再由having进行过滤。因而可知,要想过滤条件起到正确的做用,首先要明白这个条件应该在何时起做用,而后再决定放在那里
七、使用表的别名(Alias)
当在SQL语句中链接多个表时, 请使用表的别名并把别名前缀于每一个Column上.这样一来,就能够减小解析的时间并减小那些由Column歧义引发的语法错误。
八、用EXISTS替换DISTINCT
当提交一个包含一对多表信息(好比部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 通常能够考虑用EXIST替换, EXISTS 使查询更为迅速,由于RDBMS核心模块将在子查询的条件一旦知足后,马上返回结果。
九、sql语句用大写的
由于oracle老是先解析sql语句,把小写的字母转换成大写的再执行 。
十、用>=替代>
高效: SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3 二者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录然后者将首先定位到DEPTNO=3的记录而且向前扫描到第一个DEPT大于3的记录。