您的位置:首页 > 数据库 > Oracle

sql 少用系列+推荐系列(oracle)【持续积累】

2017-11-27 10:37 309 查看
少用系列

1.From子句中写在最后的表(driving table基础表(就是谁写在前面))将被最先处理,所以选个记录条数最少的表作为基础表。

Eg: tab1有N条数据

   tab2有10条数据

select count(*) from tab1,tab2 ………….//不佳

select count(*) from tab2,tab1 …………//最佳

2.不要把交叉表放后面。交叉表放前面,即from的第一个表最好是交叉表

3.Where条件中不要把表间的连接放后面

表之间的连接必须写在其他where条件之前。

可以过滤掉最大数据记录的条件必须写在where子句的末尾

4.如果表A和B存在 多对一 或者 一对一 的关系如下:

//高效

Select A.* from A,B where A.city=B.city

//低效

Select * from A where A.city in (select B.city from B)

5.全表删除用truncate代替delete

6.不用*代替所有列名,因为oracle中会查询数据字典把*转变为表的所有列名

7.少用动态语句、like、commit、order by、视图嵌套(理论上可嵌套16层,但是3层就会使性能下降的非常严重)

8.定义trunc(sysdate)时尽量在声明的时候用,同时不推荐使用sysdate

9.Mod的开销很大

10.使用不等于操作符(<> 、 != )

下面的查询即使在cust_rating 列有一个索引,查询语句仍然执行一次全表扫描。

select cust_Id,cust_name from customers where  cust_rating <> 'aa';

把上面的语句改成如下的查询语句,这样,在采用基于规则的优化器而不是基于代价的优化器(更智能)时,将会使用索引。

select cust_Id,cust_name from customers where cust_rating < 'aa' or cust_rating > 'aa'; 

  特别注意:通过把不等于操作符改成 OR 条件,就可以使用索引,以避免全表扫描。 

11.使用 IS NULL  或 IS NOT NULL 

使用 IS NULL  或 IS NOT NULL 同样会限制索引的使用 。因为 NULL 值并没有被定义。在 SQL 语句中使用 NULL 会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成  NOT NULL 。如果被索引的列在某些行中存在 NULL 值,就不会使用这个索引(除非索引是一个位图索引,关于位图索引在稍后在详细讨论)。 

12.使用函数 

   如果不使用基于函数的索引,那么在SQL 语句的 WHERE 子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。 

  下面的查询不会使用索引(只要它不是基于函数的索引) 

 select empno,ename,deptno from emp where trunc(hiredate)='01-MAY-81'; 

   把上面的语句改成下面的语句,这样就可以通过索引进行查找。 

select empno,ename,deptno from emp where hiredate<(to_date('01-MAY-81')+0.9999);

13.比较不匹配的数据类型        

注意下面查询的例子,account_number 是一个 VARCHAR2 类型 , 在 account_number 字段上有索引。

下面的语句将执行全表扫描 :

 select bank_name,address,c
f38d
ity,state,zip from banks where account_number = 990354; 

  Oracle可以自动把 where 子句变成 to_number(account_number)=990354 ,这样就限制了索引 的使用 , 改成下面的查询就可以使用索引: 

 select bank_name,address,city,state,zip from banks where account_number ='990354';

特别注意:不匹配的数据类型之间比较会让Oracle 自动限制索引的使用 , 即便对这个查询执行 Explain Plan 也不能让您明白为什么做了一次 “ 全表扫描 ” 。

14.union操作符

union在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表union。如:

select * from gc_dfys

union

select * from ls_jg_dfys

这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。

推荐方案:采用union ALL操作符替代union,因为union ALL操作只是简单的将两个结果合并后就返回。

select * from gc_dfys

union all

select * from ls_jg_dfys

15.采用函数处理的字段不能利用索引,如:

substr(hbs_bh,1,4)=’5400’,优化处理:hbs_bh like ‘5400%’ 

trunc(sk_rq)=trunc(sysdate),优化处理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)

进行了显式或隐式的运算的字段不能进行索引,如:

   ss_df+20>50,优化处理:ss_df>30

   ‘X’||hbs_bh>’X5400021452’,优化处理:hbs_bh>’5400021542’ 

   sk_rq+5=sysdate,优化处理:sk_rq=sysdate-5

   hbs_bh=5401002554,优化处理:hbs_bh=’ 5401002554’,注:此条件对hbs_bh 进行隐式的

   to_number转换,因为hbs_bh字段是字符型。 

   条件内包括了多个本表的字段运算时不能进行索引,如:

   ys_df>cx_df,无法进行优化 

   qc_bh||kh_bh=’5400250000’,优化处理:qc_bh=’5400’ and kh_bh=’250000’

16.

推荐使用

1.推荐使用decode函数,oracle所有版本都支持,同时decode比if和then高效

Eg:select DECODE(command, 0, ‘none’, 2, ‘insert’, 3, ‘select’, 6, ‘update’, 7, ‘delete’, 8, ‘drop’, ‘other’)command from …………………..

2.Oracle里的rowid可立即确定行当位置, ROWID为该表行的唯一标识,是一个伪列,可以用在SELECT中,但不可以用INSERT, UPDATE来修改该值。如Rowid可以作为判断条件与用户id相等

3.避免定义的变量类型与表中列的类型不一样,造成转换问题。同时不要定义了变量又不去使用。新变量类型:用BINARY_DOUBLE/BINARY_FLOAT代替Number型

4.自制临时表。可能因为关联表的数据分散冗杂致使效率低下,所以将关联的东东创建到一个新的表中存储在新表空间里,用这个临时表进行关联查询。

5.中间结果中会话中使用时,不要采用永久表,自己搞个临时表就行了

6.推荐结果不大的时候,用exits而不用in,in返回的是结果集,而exists返回的是布尔值。

7.当子查询结果较大时,用minus代替not in/ NOT exists 

//见笔记(点击打开)

8.用instr代替like           Eg: instr(字段名/列名, ‘查找字段’)

有的时候会需要进行一些模糊查询比如

select*from contact where username like ‘%yue%’

关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要否则不要在关键词前加%

Eg: Select * From employee Where instr(last_name,'linton')>0;

9.在进行多表关联时,多用 Where 语句把单个表的结果集最小化,多用聚合函数汇总结果集后再与其它表做关联,以使结果集数据量最小化

10.在两张表进行关联时,应考虑可否使用左/右连接。以提高查询速度

11.使用 where 而不是 having ,where是用于过滤行的,而having是用来过滤组的,因为行被分组后,having 才能过滤组,所以尽量用户 WHERE 过滤
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql oracle
相关文章推荐