以下查询返回 3 行:
SELECT ffv.flex_value
FROM fnd_flex_value_sets ffvs, fnd_flex_values ffv, fnd_flex_values_tl ffvtl
WHERE ffvs.flex_value_set_name = 'XXXXXXXX'
AND ffv.flex_value_set_id = ffvs.flex_value_set_id
AND ffv.flex_value_id = ffvtl.flex_value_id
AND ffv.enabled_flag = 'Y'
AND ffv.summary_flag <> 'Y'
AND ffvtl.language = USERENV ('LANG')
只要我添加了下面的 EXISTS 子句,就会永远返回相同的 3 行或 1 或 2 行。我无法修改此函数或创建它的副本,因为它是一个云,我们没有任何选项来创建/修改这些函数。 存在子句中的下表大约有 159330 行
AND EXISTS
(SELECT 1
FROM gl_code_combinations gcc
WHERE gcc.segment1 = ffv.flex_value
AND fnd_flex_xml_publisher_apis.process_kff_combination_1 (
'FLEX_SECURE',
'GL',
'GL#',
gcc.chart_of_accounts_id,
NULL,
gcc.code_combination_id,
'ALL',
'Y',
'SECURITY') = 'Y')
是否有任何可能的最佳方法来提高 Oracle SQL 中此查询的性能?
答案 0 :(得分:2)
正如@pmdba 上面指出的,WHERE 子句中的函数对性能来说是一个大问题。对组合数据集中的每一行都评估 EXISTS 条件,因此可以调用数十万次云函数。
如果您只想在主查询的结果集(3 行)上调用您的函数,您可以尝试几种技巧。
首先是将您的主查询移动到内联视图中,并将 WHERE 条件和函数放在它之外。这对我来说并不总是有效 - 有时优化器会重写这些查询以删除内联视图 - 但它通常会有所帮助。
select flex_value
from (
SELECT ffv.flex_value
FROM fnd_flex_value_sets ffvs, fnd_flex_values ffv, fnd_flex_values_tl ffvtl
WHERE ffvs.flex_value_set_name = 'XXXXXXXX'
AND ffv.flex_value_set_id = ffvs.flex_value_set_id
AND ffv.flex_value_id = ffvtl.flex_value_id
AND ffv.enabled_flag = 'Y'
AND ffv.summary_flag <> 'Y'
AND ffvtl.language = USERENV ('LANG')
) ffv
where EXISTS (SELECT 1 from g1_code_combinations gcc ... )
第二种方法是将您的函数移动到 SELECT 子句中。 SELECT 子句是被评估的查询的最后一部分,因此对于返回的每一行,该函数只会被调用一次。在这种情况下,最多 3 次。
select flex_value
from (
SELECT ffv.flex_value,
fnd_flex_xml_publisher_apis.process_kff_combination_1 (
'FLEX_SECURE',
'GL',
'GL#',
gcc.chart_of_accounts_id,
NULL,
gcc.code_combination_id,
'ALL',
'Y',
'SECURITY') func_result
FROM fnd_flex_value_sets ffvs
JOIN fnd_flex_values ffv
ON ffv.flex_value_set_id = ffvs.flex_value_set_id
JOIN fnd_flex_values_tl ffvtl
ON ffv.flex_value_id = ffvtl.flex_value_id
JOIN gl_code_combinations gcc
ON gcc.segment1 = ffv.flex_value
WHERE ffvs.flex_value_set_name = 'XXXXXXXX'
AND ffv.enabled_flag = 'Y'
AND ffv.summary_flag <> 'Y'
AND ffvtl.language = USERENV ('LANG')
) v
where func_result = 'Y'
答案 1 :(得分:0)
向内联视图添加 ROWNUM
谓词以停止优化器转换并强制函数在最后运行,在内联视图的所有过滤完成后。
SELECT ...
(
...
--Prevent optimizer transformations so that the function will run *after* all filtering.
AND ROWNUM >= 1
)
WHERE fnd_flex_xml_publisher_apis.process_kff_combination_1(...) = 'Y';
简单地将查询重新编写为不同的顺序几乎不会改变执行计划。添加 ROWNUM
使 Oracle 认为这是一个 Top-N 报告查询,其中顺序很重要,这将阻止所有谓词推送、视图合并和其他转换。实现此目的的一种更正式的方法是使用优化器提示,但很难获得正确的提示。