В значительной степени проблема обусловлена принципом, который лучше всего проиллюстрировать с помошью небольшого мысленного эксперимента. Представьте себе, что сто пользователей стоят в очереди к персональному компьютеру с очень медленными процессором и диском, чтобы установить соединение с экземпляром Oracle. Когда пользователь достигает начала очереди, он открывает новый сеанс SQL*Plus, устанавливает соединение с Oracle, сворачивает окно приложения и выходит из комнаты. Предположим, что после того, как все 100 пользователей проделали эти действия, можно получить точные сведения о расходовании времени во всех ста сеансах Oracle в рамках минутного интервала.
Вы обнаружите, что ядро Oracle затратило 100 минут на ожидание 100 отдельных блокирующих вызовов чтения сокета SQL*Net. Профиль ресурсов системы за эту минуту покажет, что система затратила 100 минут фактического времени на «выполнение события». Как это может быть? В системе есть только один процессор и один диск. Откуда в ней взялись ресурсы, предоставленные 100 пользователям на 100 минут фактического времени? Ответ прост:
В любой системе ресурс ожидания бесконечен.
Конечно, наш пример иллюстрирует лишь небольшой частный случай, поскольку в нем рассматривается событие, известное как «событие простоя». Даже однопроцессорная система может ожидать миллионы таких событий одновременно, вообще не загружая диск или процессор.
Удивительно то, что данный пример так же хорошо будет работать, если мы выдвинем на главную роль событие, заведомо не относящееся к простою. Представьте себе, что, проявив чудеса координированности, 100 пользователей смогли одновременно обратиться к разным блокам базы данных на одном очень медленном диске настольного ПК. Для простоты предположим, что наш медленный диск может выполнять запросы на чтение со скоростью один блок в секунду.
Сначала все 100 сеансов будут ожидать события чтения одного блока db file sequential read. Через одну секунду первый сеанс, чей запрос на чтение будет выполнен, перейдет к ожиданию SQL*Net message from client, а остальные 99 продолжат ожидание db file sequential read. Через две секунды уже два сеанса будут ожидать чтения сокета, а 98 сеансов -чтения файла. Наконец, через 100 секунд все 100 сеансов будут заняты ожиданием чтения сокета SQL*Net.
Таким образом, через 100 секунд продолжительность ожиданий чтения файла составит 1 + 2 + 3 + ... + 100 = 5050 секунд, а продолжительность ожиданий чтения сокета будет равна 99 + 98 + 97 + ... + 0 = 4950 секундам. Профиль ресурсов системы, выполняющей 100 чтений файла на таком 100-секундном интервале, будет выглядеть так:
Event
|
Duration
|
%
|
Calls
|
db file sequential read
|
5,050.00
|
5,050.0
|
100
|
SQL*Net message from client
|
4, 950.00
|
4,950.0
|
99
|
unaccounted for
|
-9,900.00
|
-9,900.0
|
|
100.00
|
100. 0
|
200
|
Теперь выясняется, что наша однопроцессорная система с медленным диском на 100-секундном интервале обеспечила своим пользователям 5050 секунд дисковых операций. Как ей это удалось? Дело в том, что пользовательские сеансы получили лишь 100 секунд работы с диском. Оставшаяся часть «времени ожидания» (которое, как вы увидите в главе 9, фактически является временем отклика в терминах теории массового обслуживания) представляет собой задержку в очереди -время, затраченное в ожидании освобождения дискового устройства. Опять-таки, как видите, ресурс ожидания любой системы бесконечен.
Пользовательские сеансы (сеансы, для которых V$SESSION.TYPE = 'USER'), как правило, относят время простоя своих пользователей к событию SQL*Net message from client. В тех системах Oracle, где за время жизни экземпляра происходило множество регистраций пользователей, это время обычно оказывается первым в запросе к V$SYSTEM_EVENT, упорядоченном по убыванию значений в поле TIME_WAITED.
В то же время фоновые процессы Oracle (сеансы, для которых V$SES-SION.TYPE = 'BACKGROUND') сохраняют соединение на протяжении всей жизни экземпляра, практически не выполняя никаких действий, когда для них нет работы. Вследствие этого такие процессы вносят существенный вклад в «события простоя». Следующий запрос показывает почему:
PROGRAM
|
EVENT
|
SECONDS
|
STATE
|
|
oracle@research
|
(PMON)
|
pmon timer
|
1,529,843
|
WAITING
|
oracle@research
|
(DBW0)
|
rdbms ipc message
|
249
|
WAITING
|
oracle@research
|
(LGWR)
|
rdbms ipc message
|
246
|
WAITING
|
oracle@research
|
(CKPT)
|
rdbms ipc message
|
0
|
WAITING
|
oracle@research
|
(SMON)
|
smon timer
|
1,790
|
WAITING
|
oracle@research
|
(RECO)
|
rdbms ipc message
|
208,071
|
WAITING
|
6 rows selected.
|
Из полученного отчета видно, что сеанс PMON находился в ожидании события pmon timer приблизительно 17,7 суток (наш экземпляр, предназначенный для исследований, не очень загружен). Сеансы DBW0, LGWR, CKPT и RECO ожидают события rdbms ipc message. А у сеанса SMON имеется собственное событие таймера smon timer. Все эти события можно с полным правом отнести к «простоям», т. к. сообщающие о них сеансы в буквальном смысле ничего не делают, находясь в ожидании вызова от некоторого коммуникационного устройства.
Однако игнорирование событий простоя - это не очень хорошее решение фундаментальной проблемы, вызванной неправильным выбором временной области и области операций для сбора данных. До тех пор, пока повышение производительности фонового сеанса не представляет для нас интереса, мы можем не обращать внимания на события pmon timer, rdbms ipc message и smon timer. Если же действительно необходимо повысить производительность фонового сеанса и в собранных в корректной области данных велик вклад одного из этих событий, то вопрос, на который надо дать ответ, звучит так:
Почему этот сеанс простаивает, в то время как мы пытаемся заставить его работать быстрее, чем он это делает сейчас?
Если так называемое событие простоя увеличивает время отклика для конечного пользователя, то об этом действительно стоит побеспокоиться.
Почему я так долго утаивал от вас эти чудовищные сложности, вызванные «событиями простоя», и только сейчас рассказал о них? На самом деле я ничего не скрывал. Я рассказывал о событиях простоя в главе 5. Просто я называл их «событиями, произошедшими между вызовами базы данных» и никогда не говорил, что с ними связаны какие-то неприятности. События между вызовами не вызывают никаких проблем, если анализировать диагностические данные, собранные в корректно выбранной области. К потере данных приводит неправильный выбор области. Если же область выбрана корректно, то события между вызовами имеют такую же ценность для диагностики, как и все прочие события.
Правильный выбор области на этапе сбора данных проекта повышения производительности обеспечивает релевантность всех событий ожидания Oracle. Данные, собранные в корректно выбранной области, не содержат «событий простоя», которыми можно было бы пренебречь.
Выбор области сбора данных - ключ к экономически оправданному повышению производительности.
< Предыдущая | Следующая > |
---|