Oracle SQL 查询运行缓慢

Posted

技术标签:

【中文标题】Oracle SQL 查询运行缓慢【英文标题】:Oracle SQL Query Running Slow 【发布时间】:2014-02-05 01:06:45 【问题描述】:

我在下面有一个用于搜索功能的 oracle SQL 查询,它包含在存储过程中。

它运行得很慢。

打开 p_cursor FOR 选择 表A.*, TB_S.someColumn, TB_S.SomeColumn ..

    FROM
        customer_site TableA
        LEFT JOIN TableB TB on TB.some_id = TableA.some_id
        LEFT JOIN TableC TB_S on TB_S.Bla_ID = TB.Bla_ID
        LEFT JOIN TableC TB_CS on TB_CS.Bla2_ID = TB.Bla2_ID
        LEFT JOIN TableC TB_1 on TB_1.Bla3_ID = TB.Bla3_ID
        LEFT JOIN TableC TB_2 on TB_DC.Bla4_ID = TB.Bla4_ID
        LEFT JOIN TableD SP on SP.SP_ID = TableA.SP_ID
        LEFT JOIN TableC TB_3 on TB_3.Bla5_ID = TB.Bla5_ID
        LEFT JOIN TableC TB_4 on TB_4.Bla6_ID = TB.Bla6_ID
        LEFT JOIN TableC TB_5 on TB_5.Bla7_ID = TB.Bla7_ID
    WHERE 
        (p_nmi IS NULL OR TableA.someid LIKE p_nmi)
        AND (p_last_name IS NULL OR TableA.last_name LIKE p_last_name)
        AND (p_full_address IS NULL OR
            UPPER(assemble_address(flat_number, street_number, street_name,
                street_suffix, apartment_number, building_name, suburb, state, postcode))
            LIKE p_full_address)
        AND (p_param1 IS NULL OR TB.owner = p_param1)
        AND (p_param2 IS NULL OR TB.status = p_param2)
        AND (p_param3 IS NULL OR TB.contact_stage = p_param3)
        AND (p_param4 IS NULL OR TB.no_access_code = p_param4)
        AND (p_param5 IS NULL OR TB.defect_code = p_param5)
        AND (p_param6 IS NULL OR TB.REFUSAL_RESOLUTION = p_param6)
        AND (p_param7 IS NULL OR TB.DEFECT_LEVEL = p_param7)
        AND (p_param8 IS NULL OR TB.AMI_CTR_STATUS = p_param8)
        AND (p_param9 IS NULL OR TableA.meter_route LIKE p_param9)
        AND (p_param10 IS NULL OR TableA.sp_id = p_param10)
        AND (p_inTBdent_date_from IS NULL OR TB.inTBdent_date >= p_inTBdent_date_from)
        AND (p_inTBdent_date_to IS NULL OR TB.inTBdent_date <= p_inTBdent_date_to)
        AND rownum < 1001
    ORDER BY
        TB.inTBdent_date;

数据库专家可以帮助我如何调整上述查询吗?

谢谢。

【问题讨论】:

assemble_address 似乎是一个函数。考虑在其上创建基于函数的索引。您也可以尝试更改AND 子句,如AND TB.owner = NVL(p_param1,TB.owner) 等。 如果您仅从tableA 中选择并仅通过tableAtableB 进行过滤,那么为什么其他表上有这么多连接?同样,您正在执行left joins,它不会过滤来自tableAtableB 的任何行。此外,如果您将过滤条件放在where 子句中,最好将inner jointableB 放在一起。您是否尝试过在过程之外使用硬编码参数运行此查询?如果您这样做并发布该查询的解释计划,将对我们有所帮助。 我的错,选择查询肯定需要从每个已连接的表中获取列。 请出示解释计划 【参考方案1】:

按照@Annjawn 的建议,将(p_param IS NULL or col = p_param) 的所有实例更改为col = nvl(p_param, col)。如this Jonathan Lewis article 所述,Oracle 可以优化这些条件。这可能会启用INDEX RANGE SCAN 而不是TABLE ACCESS FULL。但是,只有当列为 NOT NULL 时,该更改在逻辑上才等效,因为 null = null 不会返回 true。 (我个人更喜欢您编写条件的方式,但 Oracle 似乎讨厌 OR。)

如果这没有帮助,请发布解释计划以确定真正的问题。首先,修改程序,添加提示SELECT /*+ gather_plan_statistics */ TableA.*, ...。运行该过程,然后使用类似select * from v$sql where lower(sql_fulltext) like '%gather_plan_statistics%'; 的查询找到相关的SQL_ID。最后贴出结果 select * from table(dbms_xplan.display_cursor(sql_id =&gt; '&lt;sql_id from previous step&gt;', format =&gt; 'allstats last'));。这将告诉我们执行计划以及优化器做出的错误决策。

【讨论】:

我是 Oracle 新手,Oracle SQL Developer 有查询执行计划或类似计划吗?什么是解释计划? 解释计划显示了 Oracle 用于检索结果的步骤。解释计划有前端,但它们通常比文本格式差。获得解释计划的最简单方法是运行以下语句:explain plan for SELECT TableA.*,... 生成计划,然后运行 ​​select * from table(dbms_xplan.display); 显示计划。不幸的是,在您的情况下,有很多绑定变量,因此以这种方式生成解释计划可能不准确。获取计划统计数据比较棘手,但很有帮助,因为它告诉您实际数字,而不仅仅是估计值。

以上是关于Oracle SQL 查询运行缓慢的主要内容,如果未能解决你的问题,请参考以下文章

Oracle:连接两个快速、不相关的查询导致查询缓慢

SQL Developer 中没有参数的查询运行缓慢

SQL 命令运行缓慢。需要帮助识别缓慢

在运行非常缓慢的 SQL 的非常大的表上删除查询

oracle速度变慢,怎样解决

SQL 百分位数计算运行非常缓慢 - 需要帮助加快速度