|
Программирование >> Oracle
Глава 10 Проверяйте производительность Периодическая проверка производительности по ходу реализации принципиально важна. То, что нормально работает для 10 пользователей, не проходит для 100 или 1000. Проверка в реальных условиях - единственный способ убедиться, что можно будет достичь поставленных целей. Главное - с первого же дня определить критерии (метрики) производительности. Это мой ночной кошмар: необходимо проверить и настроить производительность, а цель проста: чтобы работало как можно быстрее . Такой настройкой производительности можно заниматься весь остаток жизни. Все может работать немного быстрее. Если цель ставится как можно быстрее , она недостижима. Необходимо установить ограничения и вести разработку в рамках этих ограничений. Кроме того, если единственное ограничение - как можно быстрее , можно делать и как можно медленнее . Сравнивать не с чем, поэтому любая реализация получается достаточно быстродействующей. Последнее утверждение многих удивит: как можно быстрее , значит, так медленно, как получится ? Чтобы этого не случилось, надо установить четкие критерии. Сначала надо проверить производительность изолированно. Если требуемая скорость работы не достигается в однопользовательском режиме, в реальной эксплуатации все будет еще медленнее. Запишите полученные результаты и сравнивайте их с предыдущими и последующими проверками. Так намного проще будет найти модуль, который раньше работал одну секунду, а теперь выполняется минуту. Следующий шаг - проверить масштабируемость и протестировать приложение (или заложенные в него идеи) под предполагаемой нагрузкой, чтобы убедиться, что создаваемое решение будет масштабироваться. При тестировании многие проверяют функциональность. Я проверяю масштабируемость. Теперь, когда все модули приложения впервые собраны вместе, необходимо потратить время и усилия на обеспечение его масштабируемости и проверить, будет оно летать или нет. Именно в ходе этой проверки будут выявлены запросы, не использующие связываемые переменные, обнаружены блокирования и конфликты, создаваемые приложением, а также недостатки архитектуры. В ходе проверки масштабируемости эти проблемы становятся до боли очевидными. Если вы хотите успешно внедрить приложение, проверяйте его масштабируемость перед внедрением. Я все время слышу обращения типа: При разработке мы использовали подмножество реальных данных, и все было отлично. При внедрении системы в производственной среде все стало работать слишком медленно. Помогите нам, пожалуйста! . Единственное, что в этой ситуации можно сделать быстро, - убрать систему с производственного сервера и вернуться к расчетам. Необходимо разрабатывать систему и проверять ее на реальных объемах данных, с которыми она будет использоваться. Полный просмотр 100 строк на машине разработчика проходит успешно. Проблема производительности появляется, когда просматривается 100000 строк, причем одновременно 100 пользователями. Необходимо при разработке использовать реальные данные, реальные таблицы, реальную защиту - все, как будет в действительности. Это единственный способ сразу избавиться от неэффективных запросов. Не забудьте записывать результаты проверок производительности - сравнивая их, вы быстро найдете, что именно отрицательно повлияло на производительность. Вы также сможете доказать, что какое-то программное Стратегии и средства настройки 527 или аппаратное решение повысило пропускную способность на столько-то - гадать не придется. Например, следующая последовательность операторов сама по себе работает отлично: declare l rec t%rowtype; begin select * from T into l rec from T where rownuro = 1 FOR UPDATE; process(l rec); delete from t where t.pk = l rec.pk; commit; end; Она очень быстро обрабатывает первую запись. Измерив время работы в изолированной среде, вы можете сказать: Я могу выполнять 5 транзакций в секунду (TPS) . Затем вы экстраполируете это значение и продолжаете: При запуске 10 таких процессов, можно будет достичь 50 TPS . Проблема в том, что при запуске 10 процессов вы будете обрабатывать те же 5 транзакций в секунду (хорошо, если - 5), поскольку все они будут выполняться последовательно, один за другим, так как блокируют первую запись, а в каждый момент времени это может сделать лишь один процесс. Хорошо, если удается выполнять что-то быстро в изолированной среде, но добиться быстрого выполнения того же самого в многопользовательской среде - принципиально другая задача. Даже если система используется только для чтения, другими словами, блокирование, вроде представленного выше, невозможно, масштабируемость надо проверять. Запросы требуют ресурсов - буферов, ввода/вывода с диска, процессорного времени для сортировки данных и т.д.; все, что требует ресурсов, необходимо проверять. Блокировка строки в рассмотренном выше примере - лишь один из типов ресурсов, а соревноваться приходится за сотни ресурсов, независимо от типа создаваемой системы. Наконец, последним шагом в процессе настройки должна быть настройка СУБД. Большинство разработчиков ищут то, что я называю параметром инициализации FAST=TRUE, - какую-то простую установку, включив которую в файл инициализации, можно заставить все работать быстрее. Такой установки нет. Настройка СУБД, по моему опыту, дает наименьший рост производительности, если уже используются ра-зумнге установки. Крайне редко встречаются случаи, когда экземпляр настроен настолько плохо, что его настройка дает заметный рост производительности, но так бывает действительно редко (например, в буферном кэше хранилища данных сконфигурировано 300 блоков, а надо - 30000 или даже 300000). Настройка приложения, в частности изменение структур базы данных и реализация более производительных алгоритмов, - наиболее плодотворный путь, дающий максимально ощутимые результаты. Часто для решения проблемы почти ничего или вообще ничего нельзя сделать на уровне настройки экземпляра. Теперь вернемся в реальный мир, где приложения просто создаются и не проверяются на масштабируемость, не имеют критериев производительности при разработке и вообще не снабжаются средствами отладки и тестирования. Что с этим делать (кроме как сбежать подальше, чтобы ничего не слышать об этом)? В некоторых случаях для диагностики и решения проблем можно будет использовать ряд существующих средств. 528 Глава 10 Во многих других случаях необходимо снабдить средствами трассировки сам код, особенно в больших приложениях, состоящих из нескольких взаимодействующих модулей. При поиске проблем в больших приложениях сложно определить даже, с чего начать. Если имеется клиент на Java, взаимодействующий с сервером приложений, который вызывает объект CORBA, изменяющий базу данных, то найти, что именно срабатывает медленно, непросто (если только приложение не предлагает соответствующих средств). Даже после выяснения причины, устранить ее очень сложно. Зачастую самое простое решение - правильное. Чем меньше составных частей необходимо учитывать, тем проще настраивать. Связываемые переменные и разбор (еще раз) Мы уже несколько раз с разных точек зрения касались темы связываемых перемен-н1х. Мы видели, например, что если не использовать связываемые переменные, до 90 процентов общего времени работы может уходить на разбор запросов, а не на их выполнение. Мы видели, как это может повлиять на разделяемый пул - ценнейший ресурс в Oracle. К этому моменту вы уже понимаете, что связываемые переменные определяют производительность системы. Не используйте их, и система будет работать во много раз медленнее, чем могла бы; кроме того, сократится количество одновременно поддерживаемых пользователей. Используйте их, и жизнь станет намного проще. По крайней мере, не придется возвращаться и исправлять программы, чтобы их можно было использовать. Связываемые переменные важны, поскольку одной из особенностей конструкции СУБД Oracle является максимально возможное повторное использование планов оптимизатора. При получении SQL-оператора или блока PL/SQL, СУБД Oracle сначала просматривает разделяемый пул в поисках точно такого же. Например, в случае SQL-запроса сервер Oracle будет искать, не был ли уже такой запрос разобран и оптимизирован. Если запрос найден и план его выполнения можно использовать повторно, все готово для выполнения. Если же запрос не найден, сервер Oracle должен пройти через трудный процесс полного разбора запроса, оптимизации плана выполнения, проверки защиты и т.д. Это не только требует существенных вычислительных ресурсов процессора (обычно во много раз больше, чем собственно выполнение запроса), но и приводит к блокированию частей библиотечного кэша на сравнительно продолжительные периоды времени. Чем больше сеансов разбирают запросы, тем дольше приходится ждать освобождения защелок в библиотечном кэше, и работа системы постепенно останавливается. Связываемые переменные и их использование - хороший пример того, почему необходимо проверять масштабируемость. В однопользовательской системе постоянный разбор запросов, не использующих связываемые переменные, можно и не заметить. Единственный сеанс будет, конечно, работать медленнее, чем мог бы, но все же достаточно быстро . А вот при одновременном запуске 10 или 100 таких сеансов, система неизбежно остановится. Избыточно тратятся ценные ресурсы (время процессора, библиотечный кэш, защелки библиотечного кэша). Применяя же связываемые переменные, можно уменьшить использование этих ресурсов во много раз. Я собираюсь еще раз продемонстрировать огромное влияние связываемых переменных на производительность. В главе 1 я показывал это на примере одного сеанса: если
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |