Oracle - параметризованный запрос имеет EXECUTIONS = PARSE_CALLS - PullRequest
3 голосов
/ 11 мая 2010

У нас есть приложение .NET, говорящее с Oracle 10g. Наш администратор баз данных недавно вытащил список запросов, где количество выполнений равно parse_calls. Мы предполагали, что это поможет нам найти все непараметризованные запросы в нашем коде.

Неожиданно в верхней части этого списка появился следующий запрос с 1 436 169 выполнениями и 1 436 151 анализом:

SELECT bar.foocolumn
  FROM bartable bar,
       baztable baz
 WHERE bar.some_id = :someId
   AND baz.another_id = :anotherId
   AND baz.some_date BETWEEN bar.start_date AND (nvl(bar.end_date, baz.some_date + (1/84600)) - (1/84600))

Почему для этого запроса количество выполнений равно parse_calls?

Ответы [ 2 ]

3 голосов
/ 11 мая 2010

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

На стороне сервера, есть различные виды разбора :

  • HARD parse - запрос никогда не видели раньше, не в общем бассейн. Мы должны разобрать это, хэш, поищите в общем пуле, не найти его, проверить безопасность, оптимизировать это и т. д. (много работы).

  • SOFT-анализ - запрос был видел раньше, находится в общем пуле. Мы надо разобрать, хэшировать, заглянуть в общий пул для него и найти его (меньше работы, чем жесткий анализ, но работа тем не менее)

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

Тем не менее, вы, вероятно, можете кэшировать оператор в своем приложении и использовать его повторно, чтобы (мягко) проанализировать его только один раз за сеанс.

3 голосов
/ 11 мая 2010

Вероятно, потому что .NET-программисты решили закодировать такую ​​подпрограмму в псевдокоде:

Loop over someId's and anotherId's
  parse(your_query);
  bind someId and anotherId to your_query;
  execute(your_query);
  close(your_query);
end loop;

где они должны были закодировать это так:

parse(your_query);
Loop over someId's and anotherId's
  bind someId and anotherId to your_query;
  execute(your_query);
end loop;
close(your_query);

Или даже лучше: используйте один запрос, чтобы получить все данные для всех someId / anotherId

С уважением, Роб.

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