My question is similar to To subselect or not to subselect? but I would like keep using the two existing views (hence I don't want to move the subselect directly into the view logic).
Slow (1.5 seconds)
SELECT h.n
FROM v_headers h
WHERE h.n >= (select 3000 from dual);
The query is fast when using the value from the subselect directly:
SELECT h.n
FROM v_headers h
WHERE h.n >= 3000;
A little more details: n is not unique, it has values between 0 and 4000; for each n exists about 50 rows. 11 values from different rows are pivoted into columns along the n.
Is there a solution without extracting the selects behind the views (or modifying the tables)? Optimizer hints maybe?
First is the slow one, the second is the fast one:
LE: I've simplified the queries.
The simplified queries work fast thanks to @nop77svk. The more complex query does not (yet):
Fast:
with xyz$ as (select 3986 as n from dual)
SELECT h.hw_number
FROM xyz$ X
JOIN v_headers h
ON h.hw_number >= x.n
Slow (and still somewhat simplified):
with xyz$ as ((SELECT nvl(MAX(n), 0) AS n
FROM (SELECT h.hw_number AS n,
Rank() OVER(ORDER BY h.hw_number DESC) rnk
FROM x_data h
GROUP BY h.hw_number)
WHERE rnk = 50))
SELECT h.hw_number
FROM xyz$ X
JOIN v_headers h
ON h.hw_number >= x.n;
A little more details about the view v_headers:
WITH s AS
(
SELECT a.n,
b.col_name,
a.value,
b.col_id
FROM qa_data a
JOIN column_def b
ON b.col_id = a.col_id
WHERE b.master_dynamic_data = 'M' )
SELECT "n","c1","c2","c3","c4","c4","c5","c6","c7","c8","c9","c10"
FROM s PIVOT( Max(value)
keep(dense_rank first ORDER BY col_id) FOR col_name IN (
'c1' c1,
'c2' c2,
'c3' c3,
'c4' c4,
'c5' c5,
'c6' c6,
'c7' c7,
'c8' c8,
'c9' c9,
'c10' c10,
'c11' c11) )
column_def
- 72 rows
- 57 rows with master_dynamic_data = 'M'
- column_def.col_id: unique 1..100 (with gaps)
- column_def.col_name: c1, c2, c3,... (20 chars actually instead of 'cx')
qa_data:
- 450k rows
- the average number of lines for each qa_data.n is 112 rows. (n is from 1 to 4000)
- the average length of qa_data.value is 18 chars