马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622 。
您需要 登录 才可以下载或查看,没有帐号?注册
x
个人简介: 毕业三年,主要在某港资企业从事Oracle EBS的开发工作
连载主题:分享成长路上的阳光雨露(Oracle EBS,Oracle Database和心情等等)
开贴日期: 希望8月中旬
计划发布在那个板块:不确定
更新周期(每天/每周/每两周/每月):希望每周一贴
本连载的亮点是:优化
其他要说的话:只是个人在开发过程中使用一些方法,希望和大家分享、学习(这是我在2012年工作中总结的一些方法)
PKM_OracleOptmize_David_2012112
优化的方法很多,而且也由于每个人的使用习惯不同,因此,在平时的开发过程中,所想所思都是有所不同。在平时的工作中,也经常的出现数据量很大的报表开发,因此,对于程序开发过程中的优化,也是考虑得最多的事情。
1. 在组织表集合(From)的时候,尽可能的把记录行数少的放到后边。 2. 在过滤条件(Where)中,能够最大程的过滤掉的条件放到最后。 3. 尽可能的使用索引(包括函数索引),学会使用PLSQL,TOAD查看其是否使用索引(当然有些时候在真正执行的时候,也许也没能真正的走所想要的索引)。 4. 学会使用Exists,In,Or等,以及之间的不同、性能等。 5. 在开发报表的过程中,可以使用临时表(Global Temporary Table),这种表在平时的开发过程中很有益处,可建立索引而优化,可使用Truncate命令而代替Delete,也是会话级别的表,在并发多用户应用程序中也是很好的选择(当然Truncate也不是所有表都可以使用)。 6. 有时候可以考虑使用ROWID来解决一些问题,算是最快的一种方法吧。 7. 有时候,如果可以的话(如从一个表中只是查询出一个栏位等),不用关联表的方式,而是直接作为一子Select查询放在Select和From之间,即可以当作函数来使用,这样做有时候反而更快(select colum1,columb,…(select column_c from table_name) columc fromtable_list)。 8. 使用批量处理方法,尤其是循环执行相同的动作的时候,可以考虑这种方法(Bulk Bind批量绑定) 8.1 Input Collection,Use the FORALLstatement. 一般用来改善DML(INSERT,UPDATE和DELETE)操作。 8.2 Output Collection,Use the BulkCollect。一般用来提高查询性能(SELECT)的性能。这种方法在处理大量数据的时候,效果还很明显的。
以下是Bulk Bind的一个例子:(Insert,Update,Delete都是一样的使用方法) --Global Type TYPE num_type IS TABLE OF NUMBER(20, 10) INDEX BY BINARY_INTEGER; TYPE num_type2 IS TABLE OF NUMBER(20) INDEX BY BINARY_INTEGER; TYPE var_type IS TABLE OF VARCHAR2(2000); TYPE date_type IS TABLE OF DATE;
v_sql VARCHAR2(100) := 'TRUNCATETABLE VCPC_COMM_TEMPORARY_TABLE'; customer_id num_type2; customer_desc var_type; product_code var_type; scm_month_id num_type2; month_id num_type2; half_year_desc var_type; fcst_qty num_type; fcst_amt num_type; BEGIN -- EXECUTE IMMEDIATE v_sql; -- SELECT --/*+index(c index_name)*/ b.customer_id, b.customer_desc, a.product_code, c.fiscal_month_id scm_month_id, substr(c.fiscal_month_id, 5, 2) month_id, CASE WHEN 4 <= substr(c.fiscal_month_id, 5, 2) AND substr(c.fiscal_month_id,5, 2) <= 9 THEN 'LAST_HALF_YEAR' ELSE 'NEXT_HALF_YEAR' END half_year_desc, SUM(a.closed_qty) fcst_qty, SUM(a.closed_amt * a.exchange_rate *e.exrate) fcst_amt BULK COLLECT INTO customer_id, customer_desc, product_code, scm_month_id, month_id, half_year_desc, fcst_qty, fcst_amt FROM table_name_a a, Talbe_name_b b, Table_name_c c, Table_name_d d, Table_name_e e WHERE 1 = 1 AND a.customer_billto_id =b.customer_billto_id …………………………………… GROUP BY b.customer_id, b.customer_desc, a.product_code, c.fiscal_month_id; IF SQL%ROWCOUNT> 0 THEN FORALL i IN customer_id.first .. customer_id.last INSERT INTO vcpc_comm_temporary_table itable (itable.batch, -- v_batch_org, itable.floor_id, --a_rec.customer_id, itable.floor_desc, --a_rec.customer_name, itable.line_desc, --a_rec.product_code, itable.num1, --a_rec.scm_month_id, itable.num2, --a_rec.month_id, itable.str1, --half_year_desc, itable.num3, --a_rec.fcst_qty, itable.num4 --a_rec.fcst_amt ) VALUES ('Billing_Actual_Data', customer_id(i), customer_desc(i), product_code(i), scm_month_id(i), month_id(i), half_year_desc(i), fcst_qty(i), fcst_amt(i)); END IF; 当然我想也可以通过Record_Type来简化些,如: Procedure Test_Bulk_Bind_With_Record Is Type Rec_Type Is Record( Item_Id Number(10), Prod_m_Code Varchar2(100), Hs Number(10), Bs Number(10), Headset Number(10)); Type Rec_Type_Tab Is Table Of Rec_Type Index By Pls_Integer; v_Rec_Tab Rec_Type_Tab; Begin Select Lp.Inventory_Item_Id, Nvl(Lp.Product_Model_Code, ' '), Nvl(Lp.Num_Of_Handsets, 0), Nvl(Lp.Num_Of_Base, 0), Nvl(Lp.Headset, 0) Bulk Collect Into v_Rec_Tab From Lu_Product Lp Where Lp.Company_Id = 84 And Upper(Lp.Product_Status) <> 'INACTIVE' And Not Exists (Select Distinct Inventory_Item_Id From Lu_Product Xt Where Xt.Company_Id = 84 And Num_Of_Base = 0 And Num_Of_Handsets = 0 And Headset = 0 AndXt.Inventory_Item_Id = Lp.Inventory_Item_Id); Forall i In 1 .. v_Rec_Tab.Count Insert Into Vcpc_Comm_Temp_Table (Item_Id, Floor_Desc, Num1,Num2, Num3) Values (v_Rec_Tab(i).Item_Id, v_Rec_Tab(i).Prod_m_Code, v_Rec_Tab(i).Hs, v_Rec_Tab(i).Bs, v_Rec_Tab(i).Headset); Commit; End Test_Bulk_Bind_With_Record; 这个数量有近20万,0.3s可以完全处理了。
|