小村庄

村夫之家

Oracle性能优化与Delphi代码 <转>

Oracle性能优化与Delphi代码 <转>


刚学了点oracle方面的知识,感觉以前写代码只凭喜好写,完全没有深究缘由,导致在内行人看来,写的都是垃圾代码,现在就把学到的一些东西写出来,也算是给刚入门的朋友一点帮助吧。

以前,写数据库访问代码,感觉很简单,不就是sql语句嘛,所以什么语句都是这样写:
A:
  qry1.Close;
  qry1.SQL.Text := edt1.Text ;
  qry1.Open ;
感觉挺好,语句自己拼,拼好了,直接执行。

还有另外一种写法:
B:
  qry1.Close;
  qry1.SQL.Text := edt1.Text ;
  qry1.Parameters.ParamByName('vvv').Value := edt2.Text ;
  qry1.Open ;
感觉这样写也是达到一样的结果,而用参数的方法,感觉很麻烦,多余,edt1.Text里变量还都得写成参数,所以从来不这样写,似乎也看不出和A方法有什么区别,只是更多了些麻烦。

最近学了点oracle性能优化方面的知识,知道了oracle的共享池,及其对性能的影响。共享池保存的是最近使用的sql语句,如果有相同的sql语句在共享池中,就不会再做分析、生成执行计划,效率就会提高很多,但是select * from tableA where aa='a'和select * from tableA where AA='a',会被认为是不同的sql语句,oracle会检查共享池里有没有完全相同的语句,没有则分别做分析、生成执行计划,虽然实质上是一样的sql语句。

所以,可以通过绑定变量的方式,使这些只是条件不同的语句,可以使oracle能够重复利用执行计划。

测试一下。

在pl/sql里的sql windows里,执行语句:
select sql_text from v$sqlarea where sql_text like '%select * from abc where%'
查看共享池中的sql语句,返回的结果只有一行:
select sql_text from v$sqlarea where sql_text like '%select * from abc where%'

然后执行语句:
select * from abc where ff = 1234
然后再查看共享池中的sql语句,看到了,这回结果集有两行返回:
select sql_text from v$sqlarea where sql_text like '%select * from abc where%'
select * from abc where ff = 1234

执行:
select * from abc where ff = 345
然后再查看共享池中的sql语句,看到了,这回结果集有三行返回:
select sql_text from v$sqlarea where sql_text like '%select * from abc where%'
select * from abc where ff = 1234
select * from abc where ff = 345

可见,当条件ff的值在变化时,同一条sql语句会被认为是不同的语句,而每次都去分析执行计划,导致的结果就是,就这一条sql语句,反复执行,就可以吃光共享池,导致oracle性能下降。

通过绑定变量,可以解决这个问题。

在command windows窗口中执行:
SQL> variable vvv number;
SQL> exec :vvv :=999;
SQL> select * from abc where ff = :vvv;
SQL> exec :vvv :=888;
SQL> select * from abc where ff = :vvv;

ok,然后再查看共享池中的sql语句,结果以上两行,只有一条记录:
select * from abc where ff = :vvv
可见,虽然ff值不同了,但oracle仍然把这两句当做相同sql语句,就可以利用已经生成的执行计划。

说了这么多,和delphi有什么关系呢?delphi怎么利用绑定变量的方法去提高sql语句的执行效率呢?其实就是用参数。

回到最初的A、B两种写法,执行的结果是不同的,A写法,条件如果发生变化,每次执行都会在oracle共享池中生成新的记录,并分析执行计划,执行多了,会对整个数据库的性能造成影响,而B写法,ado驱动会按绑定变量的代码去后台执行,会提高oracle的执行效率。

所以,结论就是,能用参数方法去执行sql语句就用参数的方法,而尽量少用写好的sql语句去执行,写好的sql语句其实就是垃圾代码,当用的多时,会降低整个数据库的执行效率。

可以在delphi写的数据库访问程序中用select * from abc where ff = 做个测试,当使用A方法,把ff变量值拼成语句执行时,ff值发生变化,共享池中就会多出相应的sql语句执行计划,而使用select * from abc where ff = :vvv的方法(也就是B写法),无论:vvv代入的值怎么变化,在共享池中始终就只有一条记录。

ms和oracle在这里的区别:
ms的oracle ADO驱动,生成的语句是:select * from abc where ff = :V00001
而oracle的ADO驱动,生成的语句是:select * from abc where ff = :1

 

 

---
本文章使用“国华软件”出品的博客内容离线管理软件MultiBlogWriter撰写并发布

posted on 2010-01-25 10:57 村夫 阅读(221) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。

My Links

Blog Stats

常用链接

留言簿

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜