Oracle: вернуть большой набор данных с курсором в процедуре - PullRequest
3 голосов
/ 26 марта 2020

Я видел много постов об использовании курсоров в PL / SQL для возврата данных в вызывающее приложение, но ни один из них не затрагивал проблему, которая, как мне кажется, связана с этой техникой. Я довольно новичок в Oracle, но имею большой опыт работы с MS SQL Server. На сервере SQL при построении запросов, вызываемых приложением для возврата данных, я обычно помещаю инструкцию SELECT в хранимый pro c с / без параметров и позволяю сохраненному pro c выполнять оператор (ы). ) и вернуть данные автоматически. Я узнал, что с PL / SQL вы должны сохранить результирующий набор данных в курсоре, а затем использовать курсор.

У нас есть запрос, который не обязательно возвращает огромное количество строк (~ 5K - 10K строк), однако набор данных очень широкий, так как состоит из 1400+ столбцов. Выполнение запроса SQL в SQL Разработчик мгновенно возвращает результаты. Однако вызов процедуры, которая открывает курсор для того же запроса , занимает 5+ минут до завершения sh.

CREATE OR REPLACE PROCEDURE PROCNAME(RESULTS OUT SYS_REFCURSOR)
AS
BEGIN    
    OPEN RESULTS FOR
    <SELECT_query_with_1400+_columns>
    ...
END;

После некоторой отладки, чтобы попытаться найти причину root медленности, я наклоняюсь к курсору, возвращающему одну строку за раз очень медленно. Я могу увидеть это в реальном времени, преобразовав pro c код в блок PL / SQL и используя DBMS_SQL.return_result(RESULTS) после запроса SELECT. При запуске я вижу каждую строку в окне вывода Script в SQL Developer по одной. Если именно так курсор возвращает данные вызывающему приложению, то я определенно вижу, как это является узким местом, так как это может занять 5-10 минут, чтобы завершить sh, возвращая все строки 5K-10K. Если я удаляю столбцы из запроса SELECT, курсор отображает все строки намного быстрее, поэтому кажется, что большое количество столбцов является проблемой при использовании курсора.

Зная, что выполнение запроса SQL само по себе возвращает мгновенные результаты, как я могу получить эту же производительность из курсора? Не похоже, что это возможно. Ответ помещает встроенный SQL в код приложения и не использует процедуру / курсор для возврата данных в этом сценарии? Мы используем Oracle 12 c в нашей среде.

Редактировать: Просто хочу рассказать о том, как я тестирую производительность, используя обычный запрос SELECT против блока PL / SQL с помощью метода курсора:

SELECT (для возврата ~ 6K строк требуется ~ 27 секунд):

SELECT <1400+_columns>
FROM <table_name>;

PL / SQL с курсором (для возврата ~ 6K строк требуется ~ 5-10 минут):

DECLARE RESULTS SYS_REFCURSOR;
BEGIN
    OPEN RESULTS FOR
    SELECT <1400+_columns>
    FROM <table_name>;

    DBMS_SQL.return_result(RESULTS);
END;

В некоторых комментариях говорится о том, что происходит в консольном приложении после возврата всех данных, но я говорю только о производительности двух методов, описанных выше в Oracle \ SQL Developer. Надеюсь, это поможет прояснить то, что я пытаюсь донести.

1 Ответ

0 голосов
/ 03 апреля 2020

Вы можете запустить отчет SQL Monitor для двух исполнений SQL; это покажет вам, где именно проводится время. Я также хотел бы рассмотреть возможность использования двух подходов в отдельных интервалах моментального снимка и проверки выходных данных из отчета о различиях AWR и отчета о сравнении ADDM; вы, вероятно, удивитесь удивительной детализации этих сравнительных отчетов. Кроме того, несмотря на то, что> 255 столбцов в таблице является «нет-нет» в соответствии с Oracle, поскольку это фрагментирует вашу запись по> 1 блокам базы данных, таким образом увеличивая время ввода-вывода, необходимое для получения результатов, я подозреваю, что различия в два подхода, которые вы видите, не являются проблемой ввода-вывода, так как в прямом SQL вы сообщаете о быстром получении результатов. Поэтому я подозреваю больше проблемы с памятью. Как вы, наверное, знаете, в коде PL / SQL будет использоваться программная глобальная область (PGA), поэтому я бы проверил параметр pga_aggregate_target и увеличил его до 5 ГБ (только предположения). Отчет ADDM, выполненный за интервал времени выполнения кода, сообщит вам, если советник рекомендует изменить этот параметр.

...