Одна из причин невероятного успеха корпорации Oracle на рынке высокопроизводительных баз данных заключается в простоте доступа к подробным данным о времени отклика. Ядро Oracle обеспечивает аналитика всеми сведениями (в файлах расширенной трассировки SQL и различных фиксированных представлениях), необходимыми для того, чтобы понять, почему время отклика приложения было именно таким. Остается «только» понять, что делать со всей этой информацией. Этот пробел мы надеемся заполнить нашей книгой.
Форматы строк файла трассировки описаны во многих достойных источниках [Oracle MetaLink note 39817.1; Kyte (2001) 464-475; Morle (2000) 133-142]. Однако ни один из них не предоставляет достаточной информации, чтобы сделать возможным полный учет времени отклика. А именно полный учет времени отклика - та цель, которой вы должны достичь при помощи этой книги. В последующих разделах описано значение каждой из связанных с производительностью статистик, встречающихся в данных расширенной трассировки SQL.
К
аждая строка файла трассировки соответствует одному «действию», выполненному процессом ядра Oracle. Имеющиеся в каждой строке символы #ID идентифицируют курсор, согласно которому ядро выполняло действие. Например, приведенная ниже строка соответствует выборке по курсору #1:
Н
о
мера курсоров имеют значение только в рамках файла трассировки. Более того, ядро Oracle делает номер курсора доступным для повторного использования в файле трассировки после закрытия курсора.1 Поэтому строки файла трассировки, содержащие ссылки на один и тот же номер курсора, совсем необязательно ссылаются на один и тот же курсор. К счастью, каждый конкретный файл трассировки содержит упорядоченную по времени историю создания всех курсоров; каждая лексема PARSING IN CURSOR указывает на рождение (или возрождение) курсора. Например, рассмотрим две строки PARSING IN CURSOR из файла трассировки в примере 5.2:
Первая секция PARSING IN CURSOR сообщает, что курсор #1 был сопоставлен команде ALTER SESSION. Далее в том же самом файле трассировки ядро Oracle повторно использует идентификатор #1 для курсора, сопоставленного команде SELECT.
Строка, начинающаяся с лексемы ***, указывает системное время, полученное непосредственно перед передачей строки *** в файл трассировки. Например: и показаниями системных часов. Ядро Oracle любезно вставляет в файл трассировки строку *** каждый раз, когда после вывода предыдущей строки трассировки проходит значительное количество времени (десятки секунд). Это удобно, потому что позволяет восстановить синхронизацию событий с фактическим временем после больших интервалов строк WAIT, содержащих приблизительное истекшее время (ela), а не значения внутренних часов (tim). Такую строку можно вставить в свой файл данных самостоятельно, вызвав DBMS_SYSTEM.KSDDDT.
Строка, содержащая лексему SESSION ID:(m. n), идентифицирует строки файла трассировки, следующие за ней, как относящиеся к сеансу Oracle с идентификатором V$SESSION.SID=m и порядковым номером V$SES-SION.SERIAL#=n. Строки идентификации сеанса обеспечивают уверенность в том, что анализируется именно тот файл, который нужен. Эти строки особенно важны в многопоточной конфигурации Oracle, т. к. каждый процесс ядра может обслуживать запросы от многих сеансов. Строки с идентификатором сеанса показывают, работа какого из них представлена в последующих строках трассировки.
Обратили ли вы внимание на то, что приведенные строки идентификации сеанса и временной метки выводятся не в хронологической последовательности? В первой строке отмечено время 22:25:53.716, а во второй строке - время на 0,002 секунды раньше. Это явление аналогично описанному ниже в разделе «Идентификация курсоров».
Если название модуля или операции приложения заданы при помощи процедур пакета DBMS_APPLICATION_INFO, то при активации трассировки SQL уровня 1 ядро Oracle передает строку APPNAME. Например:
APPNAME mod='SQL*Plus' mh=3669949024 act='' ah=4029777240
Рассмотрим входящие в эту строку значения:
mod
Имя модуля, заданное процедурой SET_MODULE.
mh
Хеш-значение, идентифицирующее модуль.
act
Имя операции, заданное процедурой SET_MODULE или SET_ACTION.
ah
Хеш-значение, идентифицирующее операцию.
Секция PARSING IN CURSOR содержит информацию о курсоре, например:
Сама строка PARSING IN CURSOR содержит информацию об идентификаторе курсора #ID. Текст между строкой PARSING IN CURSOR и соответствующей строкой END OF STMT - это собственно SQL-текст курсора. Ядро Oracle обычно отображает эту секцию по завершении вызова разбора, непосредственно перед строкой курсора PARSE. Однако если трассировка была отключена в момент завершения вызова разбора, ядро обычно передает секцию где-то в начале данных трассировки (непосредственно перед завершением первого трассируемого вызова базы данных, возможно, после одной или нескольких строк WAIT), как если бы ядро выполняло следующий псевдокод:
Таким образом, Oracle показывает в файле трассировки данные о курсоре, даже если трассировка была отключена в момент завершения вызова разбора курсора.
Каждая строка PARSING IN CURSOR содержит следующие сведения о курсоре:
len
Длина текста SQL.
dep
Рекурсивная глубина курсора. Курсор глубиной dep=n +1 является потомком некоторого курсора глубиной dep=n (n = 0, 1, 2, ...). Некоторые действия приводят к использованию рекурсивного SQL, например вызовы базы данных, которым необходима информация из словаря БД; команды, запускающие триггеры; PL/SQL-блоки, содержащие команды SQL. В разделе «Двойной учет рекурсивного SQL» далее в этой главе мы продолжим разговор о рекурсивных отношениях в SQL.
uid
Идентификатор пользователя, выполняющего разбор команды.
oct
Идентификатор типа команды Oracle [Oracle OCI (1999)].
lid
Идентификатор пользователя, обладающего привилегиями. Так, если пользователь FRED вызывает пакет, принадлежащий пользователю JOE, то для команды SQL, выполненной внутри пакета, uid будет ссылаться на FRED, а lid - на JOE.
Проверка в Oracle версии 9 показала, что независимо от того, выполнялась ли программа под привилегиями владельца или под привилегиями вызвавшего ее пользователя, uid и lid в файле трассировки имеют одно и то же значение: идентификатор пользователя, зарегистрировавшегося в системе и вызвавшего эту программу.
tim
Если значение tim равно 0, значит, параметр инициализации TIMED_ STATISTICS имел значение FALSE в момент, когда должно было подсчи-тываться время вызова. Таким образом, на основе значений tim можно сделать вывод о том, какое значение имел параметр инициализации TIMEDSTATISTICS. В процессе работы мы с коллегами пришли к выводу о том, что конкретные ненулевые значения tim, относящиеся к секциям PARSING IN CURSOR, не представляют особого интереса.
В Oracle9i значение tim измеряется в микросекундах (1 цс = 0,000001 секунды). В некоторых системах (например, на наших Linux-серве-рах) значения поля tim - это чистые значения gettimeofday. В других системах (например, на наших Windows-компьютерах) происхождение значений поля tim может быть весьма загадочным. В версиях, предшествующих Oracle9i, tim было значением V$TIMER.HSECS, выраженным в сотых долях секунды.
hv
Идентификатор команды SQL. Может показаться, что значение hv уникально, но это не так Может случиться (хотя это бывает редко), что разные тексты SQL имеют одинаковые значения hv.
ad
Вызов базы данных (database call) - это обращение к подпрограмме ядра Oracle. Если в момент завершения вызова базы данных активна трассировка SQL уровня 1, то ядро Oracle выводит в файл трассировки строку, информирующую о состоявшемся вызове. Чаще всего встречаются вызовы базы данных типа PARSE, EXEC и FETCH. Например:
О других типах вызовов (например, ERROR, UNMAP и SORT UNMAP) можно прочитать в документе Oracle MetaLink 39817.1. Каждая строка вызова базы данных содержит следующие статистики:
c
Общее процессорное время, потраченное процессом Oracle в ходе вызова. Oracle9i измеряет c в микросекундах (1 цс = 0,000001 секунды). В более ранних версиях ядра значение c выражалось в сотых долях секунды.
e
Фактическая продолжительность вызова. Oracle9i измеряет e в микросекундах (1 цс = 0,000001 секунды). В более ранних версиях ядра значение e выражалось в сотых долях секунды.
p
Количество блоков базы данных Oracle, полученных вызовом за счет обращения к дисковой подсистеме ОС. Предполагается, что p означает первую букву слова «physical» - физический, но имейте в виду, что не каждое так называемое «физическое» чтение Oracle обращается к физическому дисковому устройству. Многие такие чтения обслуживаются различными кэшами, расположенными между ядром Oracle и физическим диском.
cr
Количество блоков базы данных Oracle, полученных вызовом в режиме согласованного чтения из кэша буферов базы данных Oracle. Чтение в согласованном режиме может потребовать дополнительных согласованных чтений из блоков отката, хранящихся в сегментах отката.
cu
Количество блоков базы данных Oracle, полученных вызовом в режиме текущего чтения из кэша буферов базы данных Oracle. Чтение в текущем режиме - это просто чтение текущего содержимого блока.
mis
Количество непопаданий в библиотечный кэш в ходе вызова. Результатом каждого непопадания в библиотечный кэш является операция полного разбора (hard parse).
r
Количество строк, возвращаемых вызовом.
dep
Рекурсивная глубина курсора. Курсор глубиной dep=n + 1 является потомком некоторого курсора глубины dep=n (n = 0, 1, 2, ...). Подробнее об этом рассказано ниже в разделе «Двойной учет рекурсивного SQL» данной главы.
og
Фактическая цель оптимизатора в ходе вызова. Oracle использует значения, приведенные в табл. 5.1.
tim
См. раздел «Идентификация курсора» ранее в этой же главе.
Таблица 5.1. Цели оптимизатора запросов Oracle, соответствующие значениям og (источник: документ Oracle MetaLink 39817.1)
|
|
Значение og
|
Цель оптимизатора запросов Oracle
|
1
|
ALL_ROWS
|
2
|
FIRST_ROWS
|
3
|
RULE
|
4
|
CHOOSE
|
Имейте в виду, что ядро Oracle не передает в файл трассировки строку вызова базы данных до тех пор, пока операция не завершена. То есть чрезвычайно долгая операция над базой данных может привести к тому, что ядро Oracle будет работать несколько часов, ничего не передавая в файл трассировки. Плохо оптимизированный SQL может порождать вызовы EXEC (для обновлений или удалений) или FETCH (для выборок), способные загрузить процессор на несколько дней.
Событие ожидания Oracle - это последовательность инструкций ядра Oracle, для которой время учитывается специальным образом. Если в момент завершения события ожидания включена трассировка SQL уровня 8 или 12, то ядро Oracle по завершении данного события вставляет в файл трассировки строку WAIT. Например:
Каждая строка WAIT содержит следующую информацию о работе, выполненной в ходе события:
nam
Имя, присвоенное кем-то из разработчиков ядра Oracle для обозначения того, какая часть ядра Oracle отвечает за данную часть времени отклика.
ela
Фактическое время, потраченное на исполнение названного события. Oracle9i измеряет ela в микросекундах (1 цс = 0,000001 секунды).
В более ранних версиях ядра значение ela выражалось в сотых долях секунды.
1, p2, p3
Значения данных параметров зависят от значения nam. Полный перечень описаний параметров для всех типов событий можно получить, выполнив такой SQL-код:
Обратите внимание, что строки WAIT появляются в файле трассировки до строки того вызова базы данных, результатом которого является данное событие ожидания. Дело в том, что ядро Oracle передает строки в файл по мере завершения событий. Другими словами, если вызов выборки требует выполнения трех системных вызовов чтения, то три события ожидания для вызовов чтения появятся в файле трассировки прежде, чем Oracle выведет информацию о завершении вызова выборки.
Строки WAIT в файле трассировки SQL представляют собой интерфейс к чрезвычайно важной новой функциональности, введенной Oracle в 1992 г., которая коренным образом упрощает диагностику и решение проблем производительности.
< Предыдущая | Следующая > |
---|