моя текущая проблема в 11g, но меня также интересует, как это можно решить умнее в более поздних версиях.
Я хочу объединить две таблицы.Таблица A содержит 10 миллионов строк, таблица B огромна и содержит миллиард записей на тысяче разделов.Один раздел содержит около 10 миллионов записей.Я не присоединяюсь к ключу раздела.Для большинства строк таблицы A будет найдена одна или несколько строк в таблице B.Пример:
select * from table_a a
inner join table_b b on a.ref = b.ref
Приведенное выше вернет около 50 миллионов строк, тогда как результаты будут получены примерно из 30 разделов таблицы b.Я предполагаю, что хеш-соединение - это правильное соединение, хеш-таблица a и таблица FTSing / index-scan b.
Итак, 970 разделов были отсканированы без причины.И у меня есть третий запрос, который может сказать оракулу, какие 30 разделов нужно проверить на соединение.Пример третьего запроса:
select partition_id from table_c
Этот запрос дает ровно 30 разделов для запроса выше.
На мой вопрос:
В PL / SQL это можно решить
- выберите 30 partition_ids в переменную (будь это просто
select listagg(partition_id,',') ... into v_partitions from table_c
Выполните мой запрос следующим образом:
execute immediate 'select * from table_a a
inner join table_b b on a.ref = b.ref
where b.partition_id in ('||v_partitions||')' into ...
Допустим, это завершится за 10 минут.
Теперь, как я могу сделать это за такое же время с чистым SQL?
Простонаписание
select * from table_a a
inner join table_b b on a.ref = b.ref
where b.partition_id in (select partition_id from table_c)
, похоже, не дает результата, или я, возможно, нацеливаюсь на неверный план.
План, который, я думаю, мне нужен, -
hash join
table a
nested loop
table c
partition pruning here
table b
Но это не возвращается через 10 минут.
Итак, как это сделать в SQL и к какому плану выполнения стремиться? Один вариант, который я еще не пробовал, может быть решением:
nested loop
table c
hash join
table a
partition pruning here (pushed predicate from the join to c)
table b
Другое чувство, которое у меня возникает, заключается в том, что решение может состоять в том, чтобы соединить таблицу a с таблицей c (хотя не уверен, что), а затем соединить этот результат с табуляцией.le b.
Я не прошу вас напечатать все для меня.Просто общее представление о том, как это сделать (получить ограничение раздела из запроса) в SQL - к какому плану мне стремиться?
большое спасибо!Питер