Вопрос

Я бегу в следующем сценарии, который дает мне немного головных болей, так как я не могу найти точного объяснения поведения, которое я вижу. У меня следующее объявлено:

struct test_struct
{
    long testv1;
    char testv2[51];
    long testv3;
};

и соответствующая таблица в Oracle 10G:

CREATE TABLE test_table
(
    testv1 NUMBER(10, 0),
    testv2 VARCHAR(50),
    testv3 NUMBER(4, 0)
);

Чтобы получить доступ к данным в этой таблице, у меня есть функция:

bool getTestData(long test_var1, struct test_struct *outStruct)

И здесь я вижу различия, которые мне нужно объяснить, но не могу. Если тело функции выглядит так:

EXEC SQL BEGIN DECLARE SECTION;
    long testvar1_param = test_var1;
    struct test_struct *resStruct = outStruct;
EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT testv1, testv2, testv3
    INTO :resStruct
    FROM test_table
    WHERE testv1 = :testvar1_param;

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

EXEC SQL BEGIN DECLARE SECTION;
    long testvar1_param = test_var1;
    long *testv1_res = &(outStruct->testv1);
    char *testv2_res = outStruct->testv2;
    long *testv3_res = &(outStruct->testv3);
EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT testv1, testv2, testv3
    INTO :testv1_res, :testv2_res, :testv3_res
    FROM test_table
    WHERE testv1 = :testvar1_param;

Производительность во втором отличается значительным отрывом.

Кто -нибудь знает, что может объяснить это поведение?

Это было полезно?

Решение

Для проблем с производительностью, которые выглядят необъяснимыми с первого взгляда: включите отслеживание SQL, включая ожидание.

ALTER SESSION SET TRACEFILE_IDENTIFIER = "some_unique_identifier";
dbms_support.start_trace (binds=>true,waits=>true);

Запустите свой код, сделайте его совершение и отключите изящно. Не используйте dbms_support.stop_trace, потому что это может предотвратить катушки операций Rowsource. В сгенерированном Tracefile вы найдете точный текст SQL по мере его проанализирования, события ожидания, которые повлияли на SQL и операции Rowsource. Операции Rowsource показывают, как именно выглядит план SQL во время работы SQL.

  • Проверьте количество анализа
  • Проверьте, что используются переменные привязки или нет.
  • Проверьте операции Rowsource для ожидаемого плана.

Для вашей проблемы - необходимость приносить множество рядов случайным образом - я ожидаю найти

  • 1 Декларация курсора
  • 1 Parse
  • петля, которая открывает/извлекает/закрывает курсор

Для этих сценариев очень важно не анализировать каждый выбор. Растановление может занять больше времени, чем исполнение.

Один вопрос, который остается: зачем получать все ряды один за другим? Это какая -то операция копирования данных?

Другие советы

Вы учитываете эффект кэширования? Я предполагаю, что нет.

Если вы запустите первый запрос, запустите второй запрос, где значение testvar1_param одинаково, второе завершается в заметно другое время. Не имеет значения, какой запрос запускается первым, вторая версия будет лучше.

Это связано с тем, что место, где предикат одинаково в обоих запросах, а данные в результатах одинаковы в обоих запросах. Обычно последующие запросы идентичные запросы работают намного быстрее, когда вы идете против индексированного запроса, потому что вы никогда не заходите к таблице, чтобы получить результат, он исходит от SGA, где он кэширован.

Попробуйте использовать разные значения для TestVAR1_PARAM и запустите 10 запросов каждого из них с совершенно разными значениями PARM. Они будут очень близки вовремя.

Вы используете tkprof, верно?

Я имею в виду время (так как это развитие, верно?)

ALTER SYSTEM SET TIMED_STATISTICS = TRUE;

Это улучшает то, что Oracle дает вам в отслеживании для производительности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top