Различия в архитектуре Oracle и MS SQL Server

Архитектура Oracle и MS SQL сравнениеМне приходилось сотрудничать со многими клиентами, использующими крупные производственные приложения, которые были “перенесены” в Oracle из другой платформы баз данных (например, MS SQL Server). Слово “перенесено” взято в кавычки потому, что большинство встречаемых мною адаптаций сводились к точке зрения “найти минимальные изменения, которые обеспечили бы успешную компиляцию и выполнение кода MS SQL Server на платформе Oracle”. Откровенно говоря, приложения, построенные в результате такого подхода к делу, попадались мне чаще всего, поскольку именно они требовали наибольшей помощи. Я вовсе не критикую SQL Server в этом отношении — ведь справедливо и обратное! Перенос приложения Oracle и его помещение с минимальными изменениями в среду SQL Server приведет к получению столь же плохо работающего кода, как и наоборот; проблема имеет обоюдный характер.

Однако в одном конкретном случае архитектура SQL Server и способ применения SQL Server действительно были навеяны реализацией Oracle. В качестве конечной цели ставилось масштабирование, но обратившиеся ко мне разработчики на самом деле не хотели переходить на другую базу данных. Они хотели провести перенос с минимальными усилиями со своей стороны, и потому оставили архитектуру в основном прежней - на уровне клиента и базы данных. Это решение имело два важных последствия.

Эти два обстоятельства повлекли за собой построение системы, которая не могла поддерживать необходимую пользовательскую нагрузку (серверу базы данных просто не хватало доступной памяти) и обладала крайне низкой производительностью.

Используйте единственное подключение в Oracle

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

Однако, как раз это и было сделано. Простое веб-приложение для каждой веб-страницы может открывать 5, 10, 15 и более подключений, а это значит, что сервер мог поддерживать только 1/5, 1/10, 1/15 и менее параллельно работающих пользователей от того числа, которое должен. Кроме того, была предпринята попытка использования базы данных на обычной платформе Windows — в среде простого сервера Windows без доступа к Datacenter-вepcии Windows Server. В результате архитектура Windows с единственным процессом ограничила общий объем оперативной памяти, доступной серверу баз данных Oracle, до приблизительно 1,75 Гбайт. Поскольку каждое подключение Oracle занимает, как минимум, определенный фиксированный объем памяти, возможности масштабирования количества пользователей, работающих с приложением, были существенно ограничены. Объем оперативной памяти сервера составлял 8 Гбайт, но из них можно было использовать только около 2 Гбайт.

Важно! В среде 32-разрядной ОС Windows доступны способы использования большего объема оперативной памяти, такие как ключ /AWE, но для этого требуются версии ОС, которые в описанной ситуации не применялись.

Существовало три подхода к решению этой проблемы, причем все три были достаточно трудоемкими — и это после завершения “переноса”!

Были доступны следующие варианты.

Как видите, ни одна из этих возможностей не относилась к решениям, о которых можно было бы сказать: “Хорошо, мы сделаем это до обеда”. Каждая из них представляла собой сложное решение проблемы, которую проще всего было решить на этапе переноса базы данных, пока вносились изменения в код и в наиболее важные элементы системы. Более того, простое тестирование масштабирования, проведенное до развертывания системы, позволило бы выявить проблемы подобного рода еще до того, как конечные пользователи начали бы испытывать какие-то неудобства.

Используйте переменные привязки

Если бы я писал книгу о том, как строить немасштабируемые приложения Oracle, то первая и последняя глава называлась бы “Не используйте переменные привязки”. Отказ от применения переменных привязки является основной причиной возникновения проблем с производительностью и главным ограничителем возможностей масштабирования, не говоря уже об огромной степени риска в плане безопасности. Способ работы Oracle с разделяемым пулом (очень важная структура данных в разделяемой памяти) в большинстве случаев определяется разработчиками, использующими переменные привязки. Если вы хотите заставить транзакционную реализацию Oracle работать медленно, вплоть до полной ее остановки, просто откажитесь от применения переменных привязки.

Переменная привязки — это метка-заполнитель в запросе. Например, извлечения записи сотрудника 123 можно выполнить следующий запрос:

select * from emp where empno = 123;

В качестве альтернативы можно запустить такой запрос:

select * from emp where empno = :empno;

В типичной системе запрос информации о сотруднике 12 3 вполне может быть выполнен один или два раза и больше никогда на протяжении длительного периода времени. Позже может требоваться информация о сотруднике 456, затем - о сотруднике 7 8 9 и т.д. Или, как в предшествующих операторах SELECT, если вы не указываете в своих операторах вставки переменные привязки, то значения первичного ключа будут жестко закодированы в них, и мне известен тот факт, что такие операторы вставки никогда не смогут использоваться повторно! Если в запросе применяются литералы (константы), то каждый запрос оказывается совершенно новым, никогда ранее не выполнявшимся в базе данных. Он должен быть синтаксически разобран, определен (произведено распознавание имен), проверен на соблюдение правил безопасности, оптимизирован и т.п.

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

Во втором запросе использовалась переменная привязки :empno, значение которой передается во время выполнения запроса. Этот запрос компилируется только один раз, а затем план запроса сохраняется в разделяемом пуле (библиотечном кеше), из которого он может быть извлечен и применен повторно. Разница между этим двумя методами с точки зрения производительности и масштабируемости не просто велика - она огромна.

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

При выполнении полного разбора запроса база данных будет дольше хранить определенные низкоуровневые устройства последовательной обработки, называемые защелками (или внутренними блокировками). Эти защелки защищают структуры данных в разделяемой памяти Oracle от одновременных изменений двумя сеансами (в противном случае структуры данных были бы повреждены) и от считывания структуры данных кем-либо во время ее изменения. Чем дольше и чаще приходится “защелкивать” эти структуры данных, тем более длинной будет становиться очередь для получения таких защелок. Это приведет к монополизации ограниченных ресурсов. Временами компьютер может выглядеть недогруженным, тем не менее, все действия в базе данных будут выполняться очень медленно. Внешне все выглядит так, будто кто- то владеет одним из механизмов последовательной обработки, создавая очередь — достичь максимальной производительности не удастся. Достаточно наличия в базе данных одного неправильно ведущего себя приложения, чтобы производительность всех приложений значительно снизилась. Единственное небольшое приложение без переменных привязки со временем приведет к удалению из разделяемого пула всех SQL-запросов, принадлежащих остальным хорошо настроенным приложениям. Одной ложки дегтя хватит, чтобы испортить бочку меда.

Важно! Чтобы увидеть отличие между полным и частичным разбором в действии, рекомендуется пересмотреть демонстрационный видеоролик, доступный по ссылке http://tinyurl. corn/RWP-OLTP-PARSiNG. Он был смонтирован командой, с которой я работал - командой Real World Performance ( Производительность в реальном мире) из Oracle. В нем наглядно показана разница между полным и частичным разбором - она близка к отличию на порядок! В транзакционной системе, архитектура которой ориентирована на использование переменных привязки, можно добиться десятикратного увеличения скорости выполнения в случае их применения. Вы можете использовать эту короткую визуальную презентацию, чтобы убедить других разработчиков о высоком влиянии переменных привязки (либо их отсутствия) на производительность! 

for i in 1 .. 10000
lоор
execute immediate ' insert into t values ( '1 lil 1 ') ' ;
end lоор;
end;
/

Единственное отличие между этими двумя процедурами состоит в том, что в одной применяется переменная привязки, а в другой - нет. Обе процедуры используют динамический SQL-код с идентичной логикой. Разница заключается только в применении переменной привязки в первой процедуре. 

 Фактически если вы не используете переменные привязки и применяете прием с конкатенацией строк, то код становится уязвимым для атак внедрением SQL и потому должен быть тщательно пересмотрен. Причем это должен сделать кто-то другой, а не разработчик, написавший этот код, потому что код должен быть пересмотрен критически и объективно. Если проверяющий является партнером автора кода или хуже того — другом или подчиненным, то проверка будет не столь критической, какой должна быть. К коду, разработанному без использования переменных привязки, следует относиться с подозрением - он должен быть скорее исключением, нежели нормой.

 

Вас заинтересует / Intresting for you:

Oracle IDE: JDeveloper, SQL De...
Oracle IDE: JDeveloper, SQL De... 4538 просмотров Ольга Потемкина Tue, 21 Nov 2017, 13:18:46
Oracle и Java: использование P...
Oracle и Java: использование P... 5771 просмотров sepia Tue, 08 May 2018, 08:52:34
Деятельность Oracle в XML-инду...
Деятельность Oracle в XML-инду... 7955 просмотров Дэн Tue, 21 Nov 2017, 13:33:37
Язык PL/SQL Oracle для програм...
Язык PL/SQL Oracle для програм... 2635 просмотров Илья Дергунов Tue, 21 Nov 2017, 13:28:01
Печать
Войдите чтобы комментировать

ildergun аватар
ildergun ответил в теме #8006 7 года 2 мес. назад
Замечательная статья. Все грамотно растусовано! Автору - зачОт!))