这是在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过滤器,但我不知道如何。 或者,也许我应该完全避免对连接的这种条件限制,如果是这样,那么我可以使用什么技术来实现我想要做的事情?
答案 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提示。