Вы находитесь на странице: 1из 4

SQL и оптимизация в SAP R/3

Как известно в системе R/3 используется так называемый Open SQL. Это модификация
языка SQL, в котором поддерживаются основные команды ANSI SQL. Если мы задали
какой либо запрос в ABAP, то сервер приложений преобразует его в запрос,
соответствующий используемой СУБД.
Достоинства Open SQL:
- не зависит от СУБД
- и впрочем все...
Недостатки Open SQL:
- медленный
- преобразование в запросы БД очень часто не оптимально
- весьма слабые возможности
Также в R/3 можно использовать Native SQL – в этом случае ABAP не производит
конвертацию запросов, а передает их на исполнение непосредственно в СУБД.
Достоинства Native SQL:
- высокая производительность
- возможность использования полного синтаксиса и возможностей СУБД
- возможность использования тонкостей программирования конкретной СУБД
Недостатки Native SQL:
- зависит от установленной СУБД (однако если использовать стандарт ANSI SQL 92
то эта проблема отпадает)
- не все заказчики допускают использование Native SQL

В R/3 могут использоваться следующие СУБД


- Oracle
- Informix
- DB2
- DB2 Universal (DB6)
- Adabas
- Microsoft SQL Server

Каждая из них имеет свои тонкости в обращении к таблицам и построении запросов.


Причем, влиять на производительность запроса можно только используя Native SQL. Так
что при использовании Open SQL вся оптимизация сводится к правильной
последовательности выборки и использования первичных ключей. Оптимизацию на
уровне запросов и использования/не использования индексов в Open SQL сделать не
возможно. Также эти СУБД отличаются производительностью. Лидер по
производительности это Oracle, DB2 достаточно медленная СУБД, а про SQL Server
лучше вообще не упоминать в приличном обществе .
Любая СУБД имеет свой optimizer, и R/3 также имеет свой optimizer. Однако это не
приводит к желаемым результатам т.к. optimizer системы R/3 преобразует запросы «в
лоб», без учета оптимальности.

Как выполняется SELECT (или немного теории)


Этот раздел позволит лучше понимать как работает СУБД.
Почти всегда результат оператора SELECT выполнять непосредственно, в чистом виде,
чрезвычайно накладно. Например, когда вычисляется декартово произведение таблиц, в
разделе FROM, может получиться таблица огромных размеров, причем практически
большинство строк и колонок из нее будет отброшено на следующих шагах.
Функцией оптимизатора и является нахождение такого оптимального алгоритма
выполнения запроса, который гарантирует получение правильного результата.
Схематично работу оптимизатора можно представить в виде последовательности
нескольких шагов:
Шаг 1 (Синтаксический анализ). Поступивший запрос подвергается синтаксическому
анализу. На этом шаге определяется, правильно ли вообще (с точки зрения синтаксиса
SQL) сформулирован запрос. В ходе синтаксического анализа вырабатывается некоторое
внутренне представление запроса, используемое на последующих шагах.
Шаг 2 (Преобразование в каноническую форму). Запрос во внутреннем представлении
подвергается преобразованию в некоторую каноническую форму. При преобразовании к
канонической форме используются как синтаксические, так и семантические
преобразования. Синтаксические преобразования (например, приведения логических
выражений к конъюнктивной или дизъюнктивной нормальной форме, замена выражений
"x AND NOT x" на "FALSE", и т.п.) позволяют получить новое внутренне представление
запроса, синтаксически эквивалентное исходному, но стандартное в некотором смысле.
Семантические преобразования используют дополнительные знания, которыми владеет
система, например, ограничения целостности. В результате семантических
преобразований получается запрос, синтаксически не эквивалентный исходному, но
дающий тот же самый результат.
Шаг 3 (Генерация планов выполнения запроса и выбор оптимального плана). На этом шаге
оптимизатор генерирует множество возможных планов выполнения запроса. Каждый план
строится как комбинация низкоуровневых процедур доступа к данным из таблиц, методам
соединения таблиц. Из всех сгенерированных планов выбирается план, обладающий
минимальной стоимостью. При этом анализируются данные о наличии индексов у таблиц,
статистических данных о распределении значений в таблицах, и т.п. Стоимость плана это,
как правило, сумма стоимостей выполнения отдельных низкоуровневых процедур,
которые используются для его выполнения. В стоимость выполнения отдельной
процедуры могут входить оценки количества обращений к дискам, степень загруженности
процессора и другие параметры.
Шаг 4. (Выполнение плана запроса). На этом шаге план, выбранный на предыдущем шаге,
передается на реальное выполнение.
Во многом качество конкретной СУБД определяется качеством ее оптимизатора.
Хороший оптимизатор может повысить скорость выполнения запроса на несколько
порядков. Качество оптимизатора определяется тем, какие методы преобразований он
может использовать, какой статистической и иной информацией о таблицах он
располагает, какие методы для оценки стоимости выполнения плана он знает.

Про оптимизацию запросов можно говорить много и долго (можно даже диссертацию
написать ). Попробуем рассмотреть все это вкратце.
Что не следует использовать (как в Open SQL так и в Native SQL):
- выборка по неиндексированным полям (!!!)
- внешняя выборка из таблицы с большим количеством записей (!!)
- использование неполного первичного ключа (приводит к неоднозначности)
- использование DISTINCT в ненужных местах (например при выборке по
первичному ключу)
- вложенные SELECT
- READ с ключом по неупорядоченной таблице и без BINARY SEARCH
- выборка таблиц БД целиком во внутренние таблицы
Что следует использовать:
- выборку по индексам
- многотабличные запросы (JOIN)
- Native SQL там где это возможно
Notes (for ANSI or Native SQL):
- условие A=1 or A=5 or A=34 лучше заменить на A in (1,5,34), за исключением
случая если поле A является индексным
- если выбирается большое количество записей таблицы (10-20%) то обращение к
индексу менее оптимально чем полный перебор таблицы

Рекомендую изучить всем !!!


Подробно про оптимизацию запросов - http://www.citforum.ru/database/articles/art_26.shtml

Про оптимизатор DB2 Universal Database


Оптимизатор функционирует на базе модели оценки стоимости исполнения запроса. В
оптимизаторе DB2 помимо размеров таблиц и доступных маршрутов исполнения
учитываются еще и скорость процессора и скорость дисковых операций ввода/вывода,
причем запросы, для которых возможна более эффективная обработка, полностью
переписываются.
В состав DB2 UDB входит целый ряд средств, предназначенных для оптимизации
использования памяти базой данных и гибкого управления буфер-пулами. Одно из таких
средств, Global SQL Cache (глобальный кэш SQL), сохраняет в памяти как статический,
так и динамический SQL, что дает возможность его повторного использования
множеством пользователей. Это минимизирует доступы к каталогам для совместно
используемых SQL запросов.

Подробно про работу оптимизатора в DB2 Universal Database (практическое применение


информации сомнительно, но для понимания принципов полезно):
\\tower_server\docs\DB2\DB2 V7 RUS\db2d3ru.pdf
Страницы 149 – 210.

А вот так делать не надо 


Поучимся на чужих ошибках. Как можно добиться минимально возможной
производительности сервера баз данных? Безусловно, самый простой способ - это
ухудшить характеристики "железа" компьютера и операционной системы, где установлен
SQL-сервер, но такие варианты рассматривать не будем. Итак:
1. Делайте COMMIT после каждой вставки записи или ее обновлении. Особенно этот
способ эффективен при пакетной вставке большого (более 1000) количества
записей.
2. Побольше контроля целостности (constraints), особенно ссылочной целостности
между таблицами, даже где это не так нужно. Все constraints являются
вычисляемыми. Чем больше контроля ссылок, тем больше производится чтений с
диска, и тем быстрее можно достичь оптимального замедления (правда, этого не
всегда можно добиться, особенно если структура таблиц и связей в базе данных
хорошо продумана).
3. Побольше индексов. При каждом изменении или добавлении записи
соответственно будет изменяться большее количество индексных страниц. Правда,
если кэш SQL-сервера достаточно большой, то по максимуму загрузить сервер не
удастся.
4. Не смотря ни на что стройте индексы по полям, содержащим наименьшее
количество разных значений (например только 0 и 1, пол мужской/женский и т.п.).
Пусть сервер при поиске или выборках перебирает максимально возможное
количество записей.
5. Комбинируйте вышеперечисленные пункты в разных вариантах. Великолепных
результатов можно достичь объединив пункты 1 и 2, и может быть прибавив к ним
пункт 3. Только так вы поставите ваш SQL-сервер в буквальном смысле на колени.