Различия в производительности Pro * C - PullRequest
1 голос
/ 10 января 2012

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

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;

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

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

Ответы [ 3 ]

1 голос
/ 11 января 2012

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

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

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

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

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

  • 1 объявление курсора
  • 1 синтаксический анализ
  • цикл, который открывает / выбирает / закрывает курсор

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

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

1 голос
/ 10 января 2012

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

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

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

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

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

0 голосов
/ 10 января 2012

Под временем я подразумеваю (поскольку это разработка, верно?)

ALTER SYSTEM SET TIMED_STATISTICS = TRUE;

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

...