http://lzfhope.blog.163.com/blog/static/6363992200919101257971/?suggestedreading&wumii
程序越编越多,忽然发现,可以利用with语句提高部分性能和工作效率,这是上周对oracle的一个比较大发现。
oracle会把这个oracle语句当成一个内建视图或者临时表使用。
有的时候,例如写过程,需要先用临时表存储一些预先计算好的数据,比较传统的方式就是直接使用临时表或者一个视图。但是这样做在某些情况下是由局限性或者不足的地方的,例如:
1)如果使用临时表,那么每次都需要truncate下,编写过程的语句增加,当然你可以忽略这种增加。但是当许多类似的情况存在的时候,大量的临时表存在也是个麻烦的事情,作为人和服务器在管理这些临时表的时候都显得有点麻烦。这样的情况虽然不多,但是存在。
2) 如果使用常规的视图,虽然能够省掉临时表的麻烦,但是同样存在另外一个问题:在某些场合,类似或者同样的SQL可能不得不写一次以上,例如以下结构的语句(为了方便,不写出v的具体内容):
select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
也许有人说,为什么x,y不合并在一起,这样视图v只要出现一次就可以了。不研究这个,总之有这个存在的理由和必要性。
如果这样来写,那么不但写起来比较麻烦,其次对于性能没有任何好处,对于这样的视图,oracle并不会自动地只执行一次扫描,所以就这个方面也需要多浪费一些时间。
但至少在在以上的情形下,with语句的子查询,可以体现出优势来。例如使用with子句上文的sql可以这么写:
with v as (select * from xxx where xx )
select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
前面说过了,oracle会把这种子查询当作内建视图或者临时表,不过是内建视图还是临时表,都可以在一个地方定义,一次产生,并处处引用(自生除外,这个应该很好理解)。如果是以内建视图存在,效率明显又会更快一些,因为是内存上;如果是临时表,则省却了管理临时表的麻烦。最关键的是省掉了常规视图的多次查询导致效率下降的问题。
目前唯一不确定的是:当数据量比较大的时候,这个方式会不会比较低效。我的想法是不会。
几种情况下的with语句位置.
1) insert into 语句
insert into
with v as ( )
... select * from v
2) select into 语句
with v as ()
select .. into .. from v..
3)open cursor 语句
open c
with v as ()
select .... from v
4) update 语句
update a set ()=(
with v as ()
select .. from v
);
但这个看起来,好像只能针对更新一个列的情况,如果列的个数>=2,那么会提示语法错误.
oracle会把这个oracle语句当成一个内建视图或者临时表使用。
有的时候,例如写过程,需要先用临时表存储一些预先计算好的数据,比较传统的方式就是直接使用临时表或者一个视图。但是这样做在某些情况下是由局限性或者不足的地方的,例如:
1)如果使用临时表,那么每次都需要truncate下,编写过程的语句增加,当然你可以忽略这种增加。但是当许多类似的情况存在的时候,大量的临时表存在也是个麻烦的事情,作为人和服务器在管理这些临时表的时候都显得有点麻烦。这样的情况虽然不多,但是存在。
2) 如果使用常规的视图,虽然能够省掉临时表的麻烦,但是同样存在另外一个问题:在某些场合,类似或者同样的SQL可能不得不写一次以上,例如以下结构的语句(为了方便,不写出v的具体内容):
select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
也许有人说,为什么x,y不合并在一起,这样视图v只要出现一次就可以了。不研究这个,总之有这个存在的理由和必要性。
如果这样来写,那么不但写起来比较麻烦,其次对于性能没有任何好处,对于这样的视图,oracle并不会自动地只执行一次扫描,所以就这个方面也需要多浪费一些时间。
但至少在在以上的情形下,with语句的子查询,可以体现出优势来。例如使用with子句上文的sql可以这么写:
with v as (select * from xxx where xx )
select x.* from (select * from a,v where ...) x,(select * from b,v where ....) y where x.col=y.col .......
前面说过了,oracle会把这种子查询当作内建视图或者临时表,不过是内建视图还是临时表,都可以在一个地方定义,一次产生,并处处引用(自生除外,这个应该很好理解)。如果是以内建视图存在,效率明显又会更快一些,因为是内存上;如果是临时表,则省却了管理临时表的麻烦。最关键的是省掉了常规视图的多次查询导致效率下降的问题。
目前唯一不确定的是:当数据量比较大的时候,这个方式会不会比较低效。我的想法是不会。
几种情况下的with语句位置.
1) insert into 语句
insert into
with v as ( )
... select * from v
2) select into 语句
with v as ()
select .. into .. from v..
3)open cursor 语句
open c
with v as ()
select .... from v
4) update 语句
update a set ()=(
with v as ()
select .. from v
);
但这个看起来,好像只能针对更新一个列的情况,如果列的个数>=2,那么会提示语法错误.