Требуется совет по настройке SQL - PullRequest
1 голос
/ 28 марта 2019

У меня есть PL / SQL, который работает и «работает». Мне было интересно, смогу ли я написать его более эффективно?

Как фон, таблица метаданных содержит информацию, которую можно использовать для построения запросов, выполняемых в удаленной базе данных. Это передается в «c1». «driver_table» используется для ограничения возвращаемых данных, нам не нужно все это, поэтому в запросе есть некоторые условия. Это может быть, например, LIMITER_USER.TABLE1, mand_join - это условие соединения, например, A.ID = B.ID add_joins - это предложение where. Например. B.DTE> = '01 -DEC-2014 ' Таким образом, в конечном итоге PL / SQL создает несколько циклов SQL и выводит их в выходной файл.

declare
v_sql_c1 pls_integer;
l_dblink varchar2(100) := 'DB1';

begin

for c1 in (select /*+parallel*/ * from meta_data_tbl where add_joins is not null)
loop
execute immediate' select /*+parallel*/ count(*) from '||c1.schema||'.'||c1.table|| '@' ||l_dblink ||' b '
||','||
c1.driver_table 
|| '@' ||l_dblink ||' a '
||' where '||
c1.mand_join
||' and '||
c1.add_joins
into v_sql_c1;
dbms_output.put_line(v_sql_c1);
end loop;
end;
/

Я бы хотел, чтобы вывод производился максимально эффективно, если он еще не выполняется. В настоящее время для завершения

требуется двенадцать минут.

1 Ответ

1 голос
/ 28 марта 2019

Возможно, вы захотите использовать параллельную конвейерную функцию для включения как параллелизма, так и параллелизма.

Термины "параллелизм" и "параллелизм" часто являются синонимами, но в Oracle они иногда имеют разные значения.Параллельность - это когда несколько операторов SQL или блоков PL / SQL выполняются одновременно, а параллелизм - это когда один оператор SQL выполняется с несколькими потоками.

Ваша текущая программа использует параллелизм для получения данных курсора, ноэто не заставляет курсорный цикл FOR выполняться в нескольких потоках.Поскольку вы используете ссылки на базы данных, я предполагаю, что эти операторы будут выполняться во многих базах данных, поэтому вы, вероятно, сможете сэкономить время, запустив их одновременно на нескольких базах данных.

Функция параллельного конвейера запускает курсор ввода впараллельно, и разделяет результаты и запускает их в несколько потоков.(Вы можете добиться того же, используя DBMS_SCHEDULER, но для этого решения требуется больше кода управления.)

--Create parallel pipelined function.
create or replace function parallel_pipe(p_cursor sys_refcursor)
return sys.odcinumberlist pipelined
parallel_enable(partition p_cursor by any) is
    v_meta_data_tbl meta_data_tbl%rowtype;
    v_sql varchar2(32767);
    v_count number;
begin
    loop
        fetch p_cursor into v_meta_data_tbl;
        exit when p_cursor%notfound;

        v_sql := 'select /*+ parallel */ count(*) from '||
            v_meta_data_tbl.schema||'.'||v_meta_data_tbl.table_name;

        execute immediate v_sql into v_count;

        pipe row(v_count);
    end loop;
end;
/

--Call the function.
select column_value row_count
from table(parallel_pipe(cursor(select /*+ parallel */ * from meta_data_tbl)));

Я не воссоздал всю вашу таблицу и присоединился.Я просто использовал схему, достаточно маленькую, чтобы продемонстрировать принципы:

create table meta_data_tbl(schema varchar2(128), table_name varchar2(128));
insert into meta_data_tbl select 'SYS', 'DUAL' from dual connect by level <= 100;
commit;

Будьте осторожны при сочетании параллелизма и параллелизма.Вышеупомянутое решение может заставить ваши серверы работать на порядок сложнее.Вы должны экспериментировать с различными комбинациями - попробуйте запустить только параллелизм или параллелизм плюс небольшое количество параллелизма и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...