加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Oracle Performance Tuning 几个做法样例

(2007-04-17 16:27:34)
分类: Oracle DB
1) 建立Index & Alter Index(慎重)
虽然加索引要慎重,可是根据用户的查询条件,可以想办法使原来不走索引的View去走索引。如果非要建索引,记得你要有DBA权限。
2) 使用with clause
--样例
CREATE OR REPLACE VIEW ZZ_TEST_VIEW
AS
  WITH ou AS (SELECT * FROM apps.hr_operating_units)
SELECT h.*
  FROM apps.oe_order_headers_all h,
        ou
 WHERE h.org_id = ou.organization_id
--样例(
CREATE OR REPLACE VIEW ZZ_TEST_VIEW
AS
WITH ou AS (SELECT * FROM apps.hr_operating_units)
SELECT l.*
  FROM apps.oe_order_lines_all  l,
       ou
 WHERE l.org_id = ou.organization_id

3) 动态SQL+绑定变量

--样例
EXECUTE IMMEDIATE 'SELECT NVL( SUM( NVL( fulfilled_quantity, )), )
FROM apps.oe_order_lines_all
WHERE NVLline_set_id, :p_line_set_id
AND line_number :p_line_number
AND header_id :p_header_id
'
INTO v_shipped_quantity
USING p_line_set_id, p_line_number, p_header_id;
--游标变量绑定样例
(1)把游标声明成 Reference Cursor 类型,即所谓的“游标变量”,声明的时候是不需要指定 SELECT 语句的。
(2)在 Open 的时候,才指定 SELECT 语句,这时候就可以套用动态 SQL 了。
OPEN cur_test
     FOR 'SELECT name FROM apps.xx_test_d_sql WHERE id >= :id' USING v_id;
4) 使用分区表
若的确因为数据量太大而达到瓶颈,可以依时间进行分区,不过这招只能在建立表的时候使用,要有DBA权限,同时分区表不能因时间而自动增加分区。
--样例
(1)创建分区表
CREATE TABLE zz_test
(   id      NUMBER,
    NAME    VARCHAR2(30),
    mdate   DATE
)
PARTITION BY RANGE ( mdate )
(
    PARTITION p1 VALUES less than (TO_DATE('2004-01-01','yyyy-mm-dd')) TABLESPACE XX_TEST_1,
    PARTITION p2 VALUES less than (TO_DATE('2005-01-01','yyyy-mm-dd')) TABLESPACE XX_TEST_2,
    PARTITION p3 VALUES less than (MAXVALUE                          TABLESPACE XX_TEST_3
);
 
(2)将已存在的普通表转换成分区表(DBA权限)
<1>原表 T1 (未分区);中间表 T1_TEMP(分区);Package DBMS_REDEFINITION
<2>创建好中间表后,执行如下PL/SQL
BEGIN
    -- 1. Make the table 'T1' available for redefinition
    DBMS_REDEFINITION.CAN_REDEF_TABLE( 'APPS',
                                       'T1',
                                       DBMS_REDEFINITION.cons_use_pk );
 
    -- 2. Start the redefinition
    DBMS_REDEFINITION.START_REDEF_TABLE( 'APPS',
                                         'T1',
                                         'T1_TEMP',
                                         'id, name, mdate',
                                         DBMS_REDEFINITION.cons_use_pk );
 
    -- 3. Synchronize the interim table
    DBMS_REDEFINITION.SYNC_INTERIM_TABLE( 'APPS',
                                          'T1',
                                          'T1_TEMP' );
 
    -- 4. Finish the redefinition
    DBMS_REDEFINITION.FINISH_REDEF_TABLE( 'APPS',
                                          'T1',
                                          'T1_TEMP' );
END;
<3>删除中间表
(3)使用分区表
SELECT * FROM zz_test PARTITION(p1);
SELECT * FROM zz_test WHERE mdate > TO_DATE('2004-01-01', 'yyyy-mm-dd');
(4)不同分区间移动数据
ALTER TABLE zz_test ENABLE ROW MOVEMENT;
5) 使用提示Hints,强制改变执行计划路径
说明:这种方法通常不一定奏效,因为Oracle CBO执行计划生成的是不无道理的。
只有特定情况下,才会强制HINT。
以下举几种强制索引的方式:
<方式一>
FULL hint 告诉ORACLE使用全表扫描的方式访问指定表.
例如:
   SELECT *
   FROM EMP
   WHERE EMPNO = 7893;
   ROWID hint 告诉ORACLE使用TABLE ACCESS BY ROWID的操作访问表.
   通常, 你需要采用TABLE ACCESS BY ROWID的方式特别是当访问大表的时候, 使用这种方式, 你需要知道ROIWD的值或者使用索引.
<方式二>
   如果一个大表没有被设定为缓存(CACHED)表而你希望它的数据在查询结束是仍然停留在SGA中,你就可以使用CACHE hint 来告诉优化器把数据保留在SGA中. 通常CACHE hint 和 FULL hint 一起使用.
例如:
SELECT *
FROM WORK;
<方式三>
   索引hint 告诉ORACLE使用基于索引的扫描方式. 你不必说明具体的索引名称
例如:
   SELECT LODGING
   FROM table_name
   WHERE fiel_name = ‘XXX’;
   如果该索引的重复值过多而你的优化器是CBO, 优化器就可能忽略索引. 在这种情况下, 你可以用INDEX hint强制ORACLE使用该索引.
又例如:
   SELECT LODGING
   FROM table_name
   WHERE fiel_name = ‘XXX’;
   当Block数比较多时,全表扫描效果会更好,这时可以强制其不走索引。
<方式其他>
   ORACLE hints 还包括ALL_ROWS, FIRST_ROWS, RULE,USE_NL, USE_MERGE, USE_HASH 等等.
6) 加上时间的限制条件
--样例
mmt.transaction_date BETWEEN gps.start_date AND( TRUNC( gps.end_date ) + 0.99999 )

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有