oracle查询优化的方法:1、union操作符,在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果;2、大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化。
oracle查询优化的方法:
1、in 操作符
用 in 写出来的 sql的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
但是用 in 的 sql 性能总是比较低的,从 oracle 执行的步骤来分析用 in 的 sql 与不用 in 的 sql有以下区别:
oracle 试图将其转换成多个表的连接,如果转换不成功则先执行in里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用in 的 sql 至少多了一个转换的过程。一般的sql都可以转换成功,但对于含有分组统计等方面的 sql 就不能转换了。
相关学习推荐:oracle数据库学习教程
2、not in 操作符
此操作是强列推荐不使用的,因为它不能应用表的索引。
推荐方案:用not exists 或(外连接+ 判断为空)方案代替
3、a8093152e673feb7aba1828c43532094 操作符(不等于)
不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
推荐方案:用其它相同功能的操作运算代替,如
aa8093152e673feb7aba1828c435320940 改为 a>0 or a''
4、> 及 4c6228038bc1fc33a5363e6e290a86622 与 a>=3的效果就有很大的区别了,因为 a>2 时 oracle 会先找出为 2 的记录索引再进行比较,而 a>=3 时 oracle 则直接找到 =3 的记录索引。
5、is null 或 is not null 操作(判断字段是否为空)
判断字段是否为空一般是不会应用索引的,因为b 树索引是不索引空值的。
推荐方案:
用其它相同功能的操作运算代替,如
a is not null 改为 a>0 或 a>'' 等。
不允许字段为空,而用一个缺省值代替空值,如业扩申请中状态字段不允许为空,缺省为申请。
建立位图索引(有分区的表不能建,位图索引比较难控制,如字段值太多索引会使性能下降,多人更新操作会增加数据块锁的现象)
6、union 操作符
union 在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表union 。如:
select * from gc_dfys union select * fromls_jg_dfys
这个 sql在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
推荐方案:采用union all 操作符替代union ,因为 union all操作只是简单的将两个结果合并后就返回。
7、where 后面的条件顺序影响
where 子句后面的条件顺序对大数据量表的查询会产生直接的影响,如
select * from zl_yhjbqk where dy_dj =‘1kv以下‘ and xh_bz=1 select * from zl_yhjbqk where xh_bz=1 and dy_dj =‘1kv以下‘
以上两个sql 中 dy_dj (电压等级)及 xh_bz(销户标志)两个字段都没进行索引,所以执行的时候都是全表扫描,第一条sql 的 dy_dj = ‘1kv以下‘ 条件在记录集内比率为 99% ,而 xh_bz=1 的比率只为 0.5% ,在进行第一条 sql 的时候 99% 条记录都进行 dy_dj及xh_bz 的比较,而在进行第二条 sql 的时候 0.5% 条记录都进行 dy_dj及xh_bz 的比较,以此可以得出第二条 sql 的 cpu 占用率明显比第一条低。
8、目标方面的提示:
cost (按成本优化)
rule (按规则优化)
choose (缺省)(oracle自动选择成本或规则进行优化)
all_rows (所有的行尽快返回)
first_rows (第一行数据尽快返回)
9、执行方法的提示:
use_nl (使用 nested loops 方式联合)
use_merge (使用 merge join 方式联合)
use_hash (使用 hash join 方式联合)
10、索引提示:
index ( table index)(使用提示的表索引进行查询)
11、其它高级提示(如并行处理等等)
oracle 的提示功能是比较强的功能,也是比较复杂的应用,并且提示只是给oracle执行的一个建议,有时如果出于成本方面的考虑 oracle也可能不会按提示进行。根据实践应用,一般不建议开发人员应用oracle提示,因为各个数据库及服务器性能情况不一样,很可能一个地方性能提升了,但另一个地方却下降了,oracle 在 sql执行分析方面已经比较成熟,如果分析执行的路径不对首先应在数据库结构(主要是索引)、服务器当前性能(共享内存、磁盘文件碎片)、数据库对象(表、索引)统计信息是否正确这几方面分析。
12、in和exists
有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。
第一种格式是使用in操作符:
... where column in(select * from ... where...);
第二种格式是使用exist操作符:
... where exists (select 'x' from ...where...);
我相信绝大多数人会使用第一种格式,因为它比较容易编写,而实际上第二种格式要远比第一种格式的效率高。在oracle中可以几乎将所有的in操作符子查询改写为使用exists的子查询。
第二种格式中,子查询以'select 'x'开始。运用exists子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器就不必遍历整个表而仅根据索引就可完成工作(这里假定在where语句中使用的列存在索引)。相对于in子句来说,exists使用相连子查询,构造起来要比in子查询困难一些。
通过使用exist,oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。oracle系统在执行in子查询时,首先执行子查询,并将获得的结果列表存放在在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用exists比使用in通常查询速度快的原因。
同时应尽可能使用not exists来代替not in,尽管二者都使用了not(不能使用索引而降低速度),not exists要比not in查询效率更高。
任何在where子句中使用is null或is notnull的语句优化器是不允许使用索引的。
13、order by语句
order by语句决定了oracle如何将返回的查询结果排序。orderby语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在orderby语句的非索引项或者有计算表达式都将降低查询速度。
仔细检查orderby语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写orderby语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在orderby子句中使用表达式。
14、not
我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。not可用来对任何逻辑运算符号取反。下面是一个not子句的例子:
... where not (status ='valid')
如果要使用not,则应在取反的短语前面加上括号,并在短语前面加上not运算符。not运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入not词,not仍在运算符中,见下例:
... where status <>'invalid';
再看下面这个例子:
select * from employee where salary<>3000;
对这个查询,可以改写为不使用not:
select * from employee where salary<3000 orsalary>3000;
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许oracle对salary列使用索引,而第一种查询则不能使用索引。
全表扫描就是顺序地访问表中每条记录.oracle采用一次读入多个数据块(databaseblock)的方式优化全表扫描。
15、使用decode函数来减少处理时间
使用decode函数可以避免重复扫描相同记录或重复连接相同的表。例如:
select count(*),sum(sal)from empwhere dept_no = 0020and ename like ‘smith%’;
你可以用decode函数高效地得到相同结果.
select count(decode(dept_no,0020,’x’,null)) d0020_count,count(decode(dept_no,0030,’x’,null)) d0030_count,sum(decode(dept_no,0020,sal,null)) d0020_sal,sum(decode(dept_no,0030,sal,null)) d0030_salfrom emp where ename like ‘smith%’;
类似的,decode函数也可以运用于group by 和order by子句中.
16、用where子句替换having子句
避免使用having子句, having只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过where子句限制记录的数目,那就能减少这方面的开销.例如:
低效:
select region,avg(log_size)from locationgroup by regionhaving region region != ‘sydney’and region != ‘perth’
高效:
select region,avg(log_size)from locationwhere region region != ‘sydney’and region != ‘perth’group by region
17、减少对表的查询
在含有子查询的sql语句中,要特别注意减少对表的查询.例如:
低效:
select tab_namefrom tableswhere tab_name = ( select tab_namefrom tab_columnswhere version = 604)and db_ver= ( select db_verfrom tab_columnswhere version = 604)
高效:
select tab_namefrom tableswhere (tab_name,db_ver)= ( select tab_name,db_ver)from tab_columnswhere version = 604)update 多个column 例子:
低效:
update empset emp_cat = (select max(category) from emp_categories),sal_range = (select max(sal_range) from emp_categories)where emp_dept = 0020;
高效:
update empset (emp_cat, sal_range)= (select max(category) , max(sal_range)from emp_categories)where emp_dept = 0020;
18、通过内部函数提高sql效率.
select h.empno,e.ename,h.hist_type,t.type_desc,count(*)from history_type t,emp e,emp_history hwhere h.empno = e.empnoand h.hist_type = t.hist_typegroup by h.empno,e.ename,h.hist_type,t.type_desc;
通过调用下面的函数可以提高效率.
function lookup_hist_type(typ in number) return varchar2astdesc varchar2(30);cursor c1 isselect type_descfrom history_typewhere hist_type = typ;beginopen c1;fetch c1 into tdesc;close c1;return (nvl(tdesc,’?’));end;function lookup_emp(emp in number) return varchar2asename varchar2(30);cursor c1 isselect enamefrom empwhere empno=emp;beginopen c1;fetch c1 into ename;close c1;return (nvl(ename,’?’));end;select h.empno,lookup_emp(h.empno),h.hist_type,lookup_hist_type(h.hist_type),count(*)from emp_history hgroup by h.empno , h.hist_type;
以上就是oracle如何查询优化?的详细内容。