duckkeeper
duckkeeper
采纳率0%
2015-12-04 01:25

【求助】ORACLE中的SQL优化,涉及到用OR该怎么优化?

  • sql

各位大神,小弟最近在执行以下sql时发现执行时间超长,跑完一次差不多要十小时,看执行计划就是卡在OR那里,现在想请教大神下面语句中的OR该做何种优化?补充说明:涉及到的各个字段已有索引,D表数据量在4200左右,T表全量在1000W左右,在子查询里做筛选后的TT数据量在300W左右。
已无分可用~跪求好人~

 SELECT
  D.ADDRESS_LEVEL_CODE
, COUNT(TT.UUID) AS BE_CHECK_WOMEN
FROM DIM_ADDRESS D
LEFT JOIN
(
SELECT T.UUID,T.HOUSEHOLD_LEVEL_CODE,T.RESIDENCE_LEVEL_CODE
FROM DIM_RESIDENT T
WHERE FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) >= 15
AND FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) <= 50
AND T.GENDER_CODE = '2' 
AND T.IS_ACTIVE = '1'
) TT ON TT.HOUSEHOLD_LEVEL_CODE LIKE CONCAT(D.ADDRESS_LEVEL_CODE,'%') OR TT.RESIDENCE_LEVEL_CODE LIKE CONCAT(D.ADDRESS_LEVEL_CODE,'%')
WHERE D.LEVEL_DEPTH <> '6'
AND D.IS_ACTIVE = '1'
GROUP BY D.ADDRESS_LEVEL_CODE
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

4条回答

  • duckkeeper duckkeeper 6年前

    回复:masterlaoding
    感谢你的回答,但现在仍有问题,求指导~
    1、是我表述有误,小表全量有100W,是添加了筛选条件后的数据量在4200左右,且该表索引在其他地方使用较多,不能删除;
    2、执行语句的服务器配置还算可以,可用内存还有40G+(见下图),这个原因也可排除;
    图片说明
    3、改走hash join这条,我试着hint了几个索引,看执行计划结果都是一样的(见下图),与未hint之前的cost并无差别,不知应该以哪个字段的索引来hint?
    图片说明

    点赞 评论 复制链接分享
  • masterlaoding masterlaoding 6年前

    按你说的数据量可能存在以下两个问题:
    1. 小表数据量只有4200,使用索引的效率提升有限,建议删除
    2. 表关联执行计划是Nest loop,用hint改成走hash join 试试
    3. 执行语句的机器不够强劲,正常服务器这个数据量nest loop应该也要不了这么久

    点赞 评论 复制链接分享
  • duckkeeper duckkeeper 6年前

    回复:_BenChen

    我已经按照你的意见作出修改,但是跑了仍有十小时之久。通过查看执行计划,发现你的语句与我之前的语句在执行计划里所需的COST相差不大,下面贴图:
    这是我之前的语句的执行计划图一
    这是你给的语句的执行计划图二
    图一是修改前的执行计划,图二是按你的意见修改后的执行计划~~~
    各位大牛,不吝赐教!

    点赞 评论 复制链接分享
  • u011661028 _BenChen 6年前

    SELECT ADDRESS_LEVEL_CODE
    , COUNT(UUID) AS BE_CHECK_WOMEN
    FROM
    ( SELECT
    D.ADDRESS_LEVEL_CODE
    , TT.UUID
    FROM DIM_ADDRESS D
    LEFT JOIN
    (
    SELECT T.UUID,T.HOUSEHOLD_LEVEL_CODE,T.RESIDENCE_LEVEL_CODE
    FROM DIM_RESIDENT T
    WHERE FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) >= 15
    AND FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) <= 50
    AND T.GENDER_CODE = '2'
    AND T.IS_ACTIVE = '1'
    ) TT ON TT.HOUSEHOLD_LEVEL_CODE LIKE CONCAT(D.ADDRESS_LEVEL_CODE,'%')
    WHERE D.LEVEL_DEPTH <> '6'
    AND D.IS_ACTIVE = '1'
    UNION ALL
    SELECT
    D.ADDRESS_LEVEL_CODE
    , TT.UUID
    FROM DIM_ADDRESS D
    LEFT JOIN
    (
    SELECT T.UUID,T.HOUSEHOLD_LEVEL_CODE,T.RESIDENCE_LEVEL_CODE
    FROM DIM_RESIDENT T
    WHERE FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) >= 15
    AND FLOOR(MONTHS_BETWEEN(SYSDATE, T.BIRTH_DATE) / 12) <= 50
    AND T.GENDER_CODE = '2'
    AND T.IS_ACTIVE = '1'
    ) TT ON TT.RESIDENCE_LEVEL_CODE LIKE CONCAT(D.ADDRESS_LEVEL_CODE,'%')
    WHERE D.LEVEL_DEPTH <> '6'
    AND D.IS_ACTIVE = '1'
    ) tmp
    GROUP BY ADDRESS_LEVEL_CODE

    点赞 评论 复制链接分享

相关推荐