左外部联接的条件谓词评估得较晚,从而导致性能问题。 Oracle 8i

时间:2018-12-03 21:06:45

标签: php oracle oracle8i

这是在Oracle 8i(很抱歉,对此无法控制)和PHP 7上。

我正在构建搜索工具。这是一个简单的表单,具有3个字段,使用HTTP Post方法。然后,PHP对3个字段的值进行一些检查,确定它们是否有效,然后将这些值发送给SQL查询。查询看起来像这样;记住它的8i,所以这里没有ANSI连接:

SELECT
reports_table.*, documents_table.*, cases_table.*

FROM
reports_table, documents_table, cases_table

WHERE
reports_table.report_id = documents_table.report_id
AND reports_table.report_id = cases_table.report_id(+)

-- Report Number filtering

    AND reports_table.report_no = 
        CASE
            WHEN $report_no_isvalid = 1
            THEN '$report_no'       -- Oracle expects datatype varchar2
            ELSE reports_table.report_no
        END

-- Document Number filtering

    AND documents_table.document_no = 
        CASE
            WHEN $doc_no_isvalid = 1
            THEN $doc_no        -- Oracle expects datatype number
            ELSE documents_table.document_no
        END

-- Case Number filtering

    AND cases_table.case_no = 
        CASE
            WHEN $case_no_isvalid = 1
            THEN '$case_no'     -- Oracle expects datatype varchar2
            ELSE cases_table.case_no
        END

要求用户至少输入一个报告号或案例号。必须提供完整的数字,即不允许使用通配符搜索。 reports_table非常大。 当按报告编号搜索时,数据库会花费很长时间,就像对报告编号的有效性起作用的CASE评估一样,即此处的这段代码

AND reports_table.report_no = 
    CASE
        WHEN $report_no_isvalid = 1
        THEN '$report_no'       -- Oracle expects datatype varchar2
        ELSE reports_table.report_no
    END
在连接操作之后评估

。但是,它似乎确实得到了评​​估,因为如果我在WHERE子句中添加另一个简单的谓词来限制“报告编号”的范围,则数据库将以预期的结果非常快速地响应。例如可以说,我要搜索的报告号是'R123456',如果我在CASE语句之外添加AND reports_table.report_no LIKE 'R1234%'作为谓词,则性能很好。否则,它会非常慢,就好像Oracle在尝试进行整个联接时正在扫描整个reports_table

我想找到一种方法来告诉Oracle确保在执行连接时确保它在报表编号上查看条件CASE过滤器,但我不知道如何。 或者,也许我应该完全避免对连接的这种条件限制,如果是这样,那么我可以使用什么技术来实现我想要做的事情?

1 个答案:

答案 0 :(得分:0)

已经有一段时间了,因为我一直在处理这个问题:而且在黑暗中总射击...是否重新安排了限制,以便在外部连接工作之前就强加了这些限制?

WHERE
(reports_table.report_id = documents_table.report_id
-- Report Number filtering

    AND reports_table.report_no = 
        CASE
            WHEN $report_no_isvalid = 1
            THEN '$report_no'       -- Oracle expects datatype varchar2
            ELSE reports_table.report_no
        END
-- Document Number filtering
    AND documents_table.document_no = 
        CASE
            WHEN $doc_no_isvalid = 1
            THEN $doc_no        -- Oracle expects datatype number
            ELSE documents_table.document_no
        END)
AND 
(reports_table.report_id = cases_table.report_id(+)
-- Case Number filtering
    AND cases_table.case_no = 
        CASE
            WHEN $case_no_isvalid = 1
            THEN '$case_no'     -- Oracle expects datatype varchar2
            ELSE cases_table.case_no
        END)

我在ANSI中知道,如果我在使用外部联接的表的where中使用AND,则我的外部联接的行为就像是内部联接。我想知道是否通过重新安排引擎是否可以更好地进行优化;或是否需要实际的SQL提示。

相关问题