У нас есть следующая схема базы данных в Oracle 10g Express Edition:
Изображение
Один из наших запросов выглядит так:
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
);
Проблема в том, что запрос выполняется очень медленно. В настоящее время в каждой таблице меньше 4000 строк, но время выполнения запроса на моем компьютере превышает 6 секунд. И это упрощенная версия. Если я поменяю 'или in' на '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
));
возвращает те же результаты, но выполняется мгновенно. К сожалению, мы используем Hibernate, который, похоже, не поддерживает union, поэтому я не могу просто изменить запрос следующим образом. Это след исходного запроса:
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)
Я пытался добавить индексы и выполнить анализ таблиц, но это не помогло.
У кого-нибудь есть идея, почему он такой медленный и как его улучшить?
Вот данные теста, если кто-то хочет воспроизвести проблему.