波 的个人资料Never Give Up照片日志列表 工具 帮助

日志


    9月11日

    我要睡觉了

     

    ORACLESQL性能优化系列(二)

    4. 选择最有效率的表名顺序(只在基于规则的优化器中有效)
    ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. 在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并.

    例如:
    表 TAB1 16,384 条记录
    表 TAB2 1 条记录

    选择TAB2作为基础表 (最好的方法)
    select count(*) from tab1,tab2 执行时间0.96秒

    选择TAB2作为基础表 (不佳的方法)
    select count(*) from tab2,tab1 执行时间26.09秒

    如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.

    例如:

    EMP表描述了LOCATION表和CATEGORY表的交集.

    SELECT *
    FROM LOCATION L ,
    CATEGORY C,
    EMP E
    WHERE E.EMP_NO BETWEEN 1000 AND 2000
    AND E.CAT_NO = C.CAT_NO
    AND E.LOCN = L.LOCN

    将比下列SQL更有效率

    SELECT *
    FROM EMP E ,
    LOCATION L ,
    CATEGORY C
    WHERE E.CAT_NO = C.CAT_NO
    AND E.LOCN = L.LOCN
    AND E.EMP_NO BETWEEN 1000 AND 2000


    5. WHERE子句中的连接顺序.

    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

    例如:

    (低效,执行时间156.3秒)
    SELECT …
    FROM EMP E
    WHERE SAL > 50000
    AND JOB = ‘MANAGER’
    AND 25 < (SELECT COUNT(*) FROM EMP
    WHERE MGR=E.EMPNO);

    (高效,执行时间10.6秒)
    SELECT …
    FROM EMP E
    WHERE 25 < (SELECT COUNT(*) FROM EMP
    WHERE MGR=E.EMPNO)
    AND SAL > 50000
    AND JOB = ‘MANAGER’;


    6. SELECT子句中避免使用 ‘ * ‘
    当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.


    7. 减少访问数据库的次数
    当执行每条SQL语句时, ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量.

    例如,
    以下有三种方法可以检索出雇员号等于0342或0291的职员.

    方法1 (最低效)
    SELECT EMP_NAME , SALARY , GRADE
    FROM EMP
    WHERE EMP_NO = 342;

    SELECT EMP_NAME , SALARY , GRADE
    FROM EMP
    WHERE EMP_NO = 291;

    方法2 (次低效)

    DECLARE
    CURSOR C1 (E_NO NUMBER) IS
    SELECT EMP_NAME,SALARY,GRADE
    FROM EMP
    WHERE EMP_NO = E_NO;
    BEGIN
    OPEN C1(342);
    FETCH C1 INTO …,..,.. ;
    …..
    OPEN C1(291);
    FETCH C1 INTO …,..,.. ;
    CLOSE C1;
    END;

    方法3 (高效)

    SELECT A.EMP_NAME , A.SALARY , A.GRADE,
    B.EMP_NAME , B.SALARY , B.GRADE
    FROM EMP A,EMP B
    WHERE A.EMP_NO = 342
    AND B.EMP_NO = 291;


    注意:
    在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200

    评论 (7)

    请稍候...
    很抱歉,您输入的评论太长。请缩短您的评论。
    您没有输入任何内容,请重试。
    很抱歉,我们当前无法添加您的评论。请稍后重试。
    若要添加评论,需要您的家长授予您相应权限。请求权限
    您的家长禁用了评论功能。
    很抱歉,我们当前无法删除您的评论。请稍后重试。
    您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
    因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
    完成下面的安全检查,您提供评论的过程才能完成。
    您在安全检查中键入的字符必须与图片或音频中的字符一致。

    若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


    还没有 Windows Live ID 吗?请注册

    小西发表:
    路过~~~
    10 月 14 日
    SevenSpace发表:
    ...怎么都是oracle?下次整点db2吧
    11 月 14 日
    李慧发表:
    真努力,真努力,加油+U
    11 月 1 日
    Yang发表:
    咋从一文人变成技术大牛了???
    10 月 10 日
    HuGua发表:
    不错不错,以后要去参加什么笔试面试的直接到你的blog瞄上两眼就搞定所有数据库问题了! 
    9 月 14 日
    WangYazhou发表:
    哎~ 你已经抛弃了你的小说连载,改连载技术文章了啊……
    9 月 13 日
    papa发表:
    好样的,从你这能学到不少东西啊
    9 月 12 日

    引用通告

    此日志的引用通告 URL 是:
    http://renshijiangreen32.spaces.live.com/blog/cns!A92E36312F77F4DC!442.trak
    引用此项的网络日志