Распараллелить вопросы запроса oracle union
У меня есть запрос Oralce, как это:
Sub_query1
Union
Sub_query2;
Я хочу распараллелить запрос. Я искал в Интернете и обнаружил, что UNION нельзя распараллелить, потому что подзапросы выполняются последовательно, а UNION не будет работать, пока не будут выполнены два подзапроса. И они говорят, что СОЮЗ можно распараллелить. Мой вопрос:
(1) can a UNION query be parallezied? if yes, how? if no, why? (2) can I just parallelize the two sub queries?
Я использую Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64-разрядная версия
Спасибо!
3 ответа
Я думаю, что вы путаете выполнение двух запросов одновременно с параллельным выполнением запроса. SQL - это описательный язык, который переводится в код механизмом SQL / оптимизатором. Этот план запроса состоит из множества различных компонентов, предназначенных для извлечения данных из таблицы, выполнения объединения, агрегирования и т. Д.
Oracle создает план запроса для вашего запроса объединения. Каждый компонент плана запроса может использовать все доступные процессоры (при условии соблюдения правильных условий). Однако каждый компонент в основном запускается по одному (в разумном приближении). Таким образом, компоненты запроса распараллелены, хотя два подзапроса не выполняются одновременно.
Один совет. Всякий раз, когда вы думаете об использовании UNION
, вы должны спросить себя, является ли UNION ALL
также будет работать. UNION ALL
гораздо эффективнее, потому что не нужно удалять дубликаты в конечном наборе результатов.
Да, как вы уже обнаружили, запрос UNION может выполняться параллельно.
Чтобы полностью понять, что здесь происходит, вы можете прочитать о параллельном выполнении в VLDB и Руководстве по разделам.
Внутриоперационный параллелизм может произойти практически где угодно. Межоперационный параллелизм происходит только между производителями и потребителями. Что в данном случае означает, что UNION (потребитель) может выполняться параллельно все время. Каждый подзапрос (производители) будет выполняться параллельно, но не одновременно друг с другом.
Вы можете увидеть это в примере ниже, посмотрев на активный отчет по запросу.
--Create two simple tables
create table test1(a number);
create table test2(a number);
--Populate them with 10 million rows
begin
for i in 1 .. 100 loop
insert into test1 select level from dual connect by level <= 100000;
insert into test2 select level from dual connect by level <= 100000;
end loop;
end;
/
commit;
--Gather stats
begin
dbms_stats.gather_table_stats(user, 'TEST1');
dbms_stats.gather_table_stats(user, 'TEST2');
end;
/
--Run a simple UNION.
select /*+ parallel */ count(*) from
(
select a from test1 join test2 using (a) where a <= 1000
union
select a from test2 join test1 using (a) where a <= 1000
);
--Find the SQL_ID by looking at v$sql, then get the active report
--(which must be saved and viewed in a browser)
select dbms_sqltune.report_sql_monitor(sql_id => 'bv5c18gyykntv', type => 'active')
from dual;
Вот часть вывода. Трудно читать, но это показывает, как UNION, первые 11 шагов плана, работает все время. Первый подзапрос, следующие 9 строк, выполняется в течение первой половины запроса. Затем второй подзапрос, последние 9 строк, выполняется во второй половине запроса.
Проведя несколько тестов и сравнив планы выполнения, я наконец нашел способ распараллелить объединение следующим образом:
select/* +parallel (Result) */ * from
(Sub_query1
Union
Sub_query2) Result;
При этом время и процессор обойдутся почти в половину от серийной версии. Добавление параллельных подсказок к обоим подзапросам не меняет время и стоимость процессора.