We have the following database schema in Oracle 10g Express Edition: Image
One of our queries looks like this:
select
*
from
torder_item oi_0
where
oi_0.id in
(
select
max(oi_1.id)
from
torder_item oi_1, torder o
where
oi_1.torder_id = o.id
group by
oi_1.tproduct_id
)
or oi_0.id in
(
select
max(oi_2.id)
from
torder_item oi_2, tproduct p
where
oi_2.tproduct_id = p.id
group
by p.group_id
);
The problem is, the query runs very slow. I currently have less than 4000 rows in each table, but the query execution time is above 6 seconds on my computer. And it is a simplified version. If I change 'or in' to 'union':
select
*
from
torder_item oi_0
where
oi_0.id in
((
select
max(oi_1.id)
from
torder_item oi_1, torder o
where
oi_1.torder_id = o.id
group by
oi_1.tproduct_id
)
union
(
select
max(oi_2.id)
from
torder_item oi_2, tproduct p
where
oi_2.tproduct_id = p.id
group
by p.group_id
));
it returns the same results, but executes instantly. Unfortunately, we are using Hibernate, which doesn't seem to support union, so I cannot just change the query like this. This is the trace of the original query:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.04 0.14 0 10 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 8 6.19 6.19 0 31136 0 96
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10 6.24 6.34 0 31146 0 96
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
96 FILTER (cr=31136 pr=0 pw=0 time=14041 us)
1111 TABLE ACCESS FULL TORDER_ITEM (cr=14 pr=0 pw=0 time=3349 us)
96 FILTER (cr=7777 pr=0 pw=0 time=1799577 us)
102096 HASH GROUP BY (cr=7777 pr=0 pw=0 time=1584153 us)
1234321 TABLE ACCESS FULL TORDER_ITEM (cr=7777 pr=0 pw=0 time=35809 us)
0 FILTER (cr=23345 pr=0 pw=0 time=4354068 us)
5075 HASH GROUP BY (cr=23345 pr=0 pw=0 time=4250913 us)
1127665 HASH JOIN (cr=23345 pr=0 pw=0 time=2716544 us)
1127665 TABLE ACCESS FULL TORDER_ITEM (cr=7105 pr=0 pw=0 time=38500 us)
3818430 TABLE ACCESS FULL TPRODUCT (cr=16240 pr=0 pw=0 time=22423 us)
I've tried to add indexes and perform analyze on the tables, but it didn't help.
Does anyone have an idea why it is so slow and how to improve it?
Here is the test data if anyone wants to reproduce the problem.
EXISTS. Does Hibernate allow that?tproducton(group_id)? And in tabletorder_item, indexes on(torder_ìd, id)and(tproduct_ìd, id)?torderrather thanoi_1.tproduct_id? Otherwise I think (a) the join totorderis redundant there, and (b) the 2nd subquery is also redundant, since themax(oi_2.id)values for product groups will be a subset of themax(oi_1.id)values for products won't they?