我有一个非常复杂的查询,该查询基于将多个表联合在一起。目前,我们正在使用视图来对所需的所有行执行操作,因此视图和查询如下所示:
CREATE VIEW
V_VIEW
(
COL1, COL2, COL3, COL4
) AS
SELECT
"COL1", "COL2", "COL3", "COL4"
FROM
TABLE1
UNION ALL
SELECT
"COL1", "COL2", "COL3", "COL4"
FROM
TABLE2;
SELECT
COL1, COL2
FROM
( SELECT
COL1, COL2
FROM
V_VIEW
WHERE
COL1 like 'val%'
AND COL2 =
(
SELECT
MAX(COL3)
FROM
V_VIEW
WHERE
COL4 = 'Y' ) part1
UNION ALL
SELECT
COL1, COL2
FROM
( SELECT
COL1, COL2
FROM
V_VIEW
WHERE
COL1 like 'sth%'
AND COL2 =
(
SELECT
MIN(COL3)
FROM
V_VIEW
WHERE
COL4 = 'N' ) part2;
我正在寻找一种提高此查询性能的方法,不幸的是,目前无法创建由Table1和Table2的所有行组成的新表(我们不允许干预其中插入行的方式) )。我尝试使用WITH子句代替视图,因此看起来有点像:
WITH TEMP_TABLE AS (
SELECT
COL1, COL2, COL3, COL4
FROM
TABLE1
UNION ALL
SELECT
COL1, COL2, COL3, COL4
FROM
TABLE2 )
SELECT
COL1, COL2
FROM
( SELECT
COL1, COL2
FROM
TEMP_TABLE
WHERE
COL1 like 'val%'
AND COL2 =
(
SELECT
MAX(COL3)
FROM
TEMP_TABLE
WHERE
COL4 = 'Y' ) part1
UNION ALL
SELECT
COL1, COL2
FROM
( SELECT
COL1, COL2
FROM
TEMP_TABLE
WHERE
COL1 like 'sth%'
AND COL2 =
(
SELECT
MIN(COL3)
FROM
TEMP_TABLE
WHERE
COL4 = 'N' ) part2
在较小的数据量(表1和表2具有约2万行)上,这可以很好地提高性能。但是,这些表最终将塞满数百万行。我不完全了解WITH子句的处理方式,所以我想知道:使用WITH闭包的查询是否有可能在大量数据上失败(由于缺少内存?),而没有它的查询会不会失败?会工作缓慢,但会很好吗?
答案 0 :(得分:1)
您可以尝试使用以下内容:
WITH main_res AS (SELECT col1,
col2,
MAX(CASE WHEN col4 = 'N' THEN col3) OVER () col3_n_max,
MAX(CASE WHEN col4 = 'Y' THEN col3) OVER () col3_y_max
FROM v_view
WHERE col1 LIKE 'val%'
OR col1 LIKE 'sth%')
SELECT col1,
col2
FROM main_res
WHERE (col1 LIKE 'val%' AND col2 = col3_y_max)
OR (col1 LIKE 'sth%' AND col2 = col3_n_max);
这使用条件最大解析函数返回所有行中的最大值(取决于col4值)。
一旦您知道了这些信息,就可以对其进行适当的过滤。这样可以减少查询每个表的次数,通常比原始查询要快(但不总是如此!)。我建议您测试一下该查询,并确定它是否比原始查询(以及其他任何答案)更快,然后再选择要使用的查询。
答案 1 :(得分:1)
WITH子句是一种动态创建的VIEW,使用时不会将其代码存储在DB中。但是,它消耗主内存来存储与游标有关的信息,该游标用于从WITH SELECT查询中检索行。你是对的;对具有大量数据的表进行查询将减慢数据库速度。
我不知道: a)TABLE1和TABLE2是否保存完整的数据集,或者这些表是增量更新的。 b)此表中是否有日期列? c)这些表以什么间隔填充或更新?
基于上述问题的答案: 与您的DBA讨论之后:
这些建议基于一组假设和您共享的信息量。
如果该数据上正在运行任何UI或报表,则需要保留此数据。
底线:
答案 2 :(得分:0)
在花费大量时间进行重写之前,确保优化器有做好工作的机会是有帮助的。确保表格具有良好的统计信息和适当的索引。
针对您的查询运行说明计划,以查看Oracle在每种情况下实际在做什么。您可能会发现那些UNION ALL语句正在发生意外情况。优化器有时会做出愚蠢的决定,您可能需要通过索引或策略性应用提示来帮助它。
WITH子句非常方便,并且与独立视图或在表列表中内联定义的视图执行相同的工作,但有一个关键的例外:Oracle在独立视图,WITH子句视图和内联视图中对独立视图的处理略有不同。优化过程。 Oracle可以选择实现在WITH子句中定义的视图的结果,而如果是内联定义的,它可以合并视图。
问题在于,在查询中的这三种视图之间进行更改将导致优化器的细微差别开始显示。
最后,您使用的是什么版本的Oracle?优化器是版本真正重要的领域。