![](https://habrastorage.org/getpro/habr/upload_files/e9b/e8e/01e/e9be8e01ec347ba4eeb1107daa49596a.png)
Всем привет! Меня зовут Алексей Пьянков, я эксперт Отдела экспертизы по техническим компонентам SAP компании Норникель. В этой статье поделюсь с вами некоторыми нюансами использования оператора FOR ALL ENTRIES в АВАР.
Регулярно просматривая ракурс m_expensive_statements на БД SAP HANA, которая обслуживает продуктивную систему SAP ERP, временами, замечаю в ТОПе среди большого количества классических записей CALL "CL_J_3RMOBVEDH… , отдельные записи, statement_string которых начинается с SELECT /* FDA WRITE */.
![](https://habrastorage.org/getpro/habr/upload_files/ccf/03e/67c/ccf03e67c9d61712f356c5811bdcfb31.png)
Что это за зверь такой /* FDA WRITE */, почему он лезет в ТОП времени выполнения и как с этим бороться я хотел бы рассказать в этой статье.
FDA это FAST DATA ACCESS - довольно новая по меркам SAP технология, позволяющая быстро передавать содержимое внутренней таблицы с сервера приложений ABAP на сервер БД и обратно.
Когда FDA появляется вместе с WRITE, это значит, что запрос к БД сформирован оператором FOR ALL ENTRIES (FAE).
FOR ALL ENTRIES это оператор языка OPEN SQL, который позволяет выполнить операцию соединения внутренней таблицы с сервера приложений ABAP, с таблицами на стороне сервера БД. Раньше это означало, что некий OPEN SQL запрос с FAE преобразуется движком АВАР в последовательность SQL запросов к БД, в которой, в каждый SQL запрос, в условие WHERE подставляются ограничения, сформированные по строкам внутренней таблицы.
Позже SAP придумал технологию FDA WRITE, которая просто берет внутреннюю таблицу на стороне ABAP, целиком передает ее на сервер базы данных и там выполняет классический SQL JOIN с этой таблицей.
Все происходит за один SQL запрос, быстро и красиво, но случаются нюансы.
![](https://habrastorage.org/getpro/habr/upload_files/045/cc6/79e/045cc679e689902e5cc51bfd2f8f028d.jpg)
И эти нюансы легче всего обнаружить в m_expensive_statements. В поле application_source для соответствующей строки этой таблицы можно найти, что-то похожее на “SAPLRSA3:1422”. Если запустить транзакцию DBA_VIEW_ABAP_SOURCE и скормить ей эти данные, то она бросит вас прямо в редактор кода на то место, где находится пациент.
![](https://habrastorage.org/getpro/habr/upload_files/21f/c50/8c3/21fc508c3ca882732311575ab29f6258.png)
Итак, встречайте:
Пациент №1:
Код был написан на старте проекта внедрения и успешно работал, не вызывая никаких проблем несколько лет, а потом вдруг начал выполняться часами создавая дикую нагрузку на процессоры БД.
![](https://habrastorage.org/getpro/habr/upload_files/0de/da0/a15/0deda0a15b679b31555d6843e38a9fa8.png)
Пациент № 2:
Здесь, внезапно, после переноса небольшого изменения, десяток пользователей, запустивших этот отчет, чуть не обрушили БД. HANA встала колом показывая 100% утилизацию процессора.
![](https://habrastorage.org/getpro/habr/upload_files/4e7/39a/a5d/4e739aa5d03eb358b24017b545910101.png)
Пациент №3:
Лаконично, но очень эффективно. Пара десятков процессов, запустивших это код, создали критическую проблему с быстродействием системы, процессы пришлось рубить руками Базиса.
![](https://habrastorage.org/getpro/habr/upload_files/482/bf6/976/482bf697675462b52de4c59a7ce69850.png)
В этом пациенте я отменил желтым маркером то, что приводит к плачевному результату – сочетание FOR ALL ENTRIES и OR.
Теперь вы можете сами поискать такие сочетания у пациентов №1 и №2. В комментариях напишите – удалось ли найти?
Такие запросы могут легко работать на старте проекта, когда данных в системе немного. Но когда проектная команда уйдет и начнутся будни поддержки, OR в комплекте с FOR ALL ENTRIES однажды гарантировано положат ваш сервер БД.
И это ни какая-то особенность SAP HANA, это всеобщий закон вселенной Баз Данных, про который можно чуть подробнее прочитать, здесь же на Хабре про PostgreSQL – ищите раздел BitmapOr vs UNION.
Собственно, здесь же и содержится ответ, что с этим делать. Нужно просто разбить запрос на два и соединить результаты. Вместо UNION у второго запроса напишите APPENDING TABLE вместо INTO TABLE и SAP опять начнет летать как на старте проекта!
![](https://habrastorage.org/getpro/habr/upload_files/8da/61d/3a7/8da61d3a7651a5894094af3796207112.png)
Резюмирую:
Господа АВАРеры, постарайтесь воздержаться от использования OR в запросах с FOR ALL ENTRIES.
PS. Прямо сейчас наблюдаю, как третий час выполняется еще один запрос с FOR ALL ENTRIES, написанный на заре проекта внедрения:
![](https://habrastorage.org/getpro/habr/upload_files/b2c/7de/4cc/b2c7de4cc2150c33eaa54249bf959321.png)
Ставьте лайки, пишите комментарии, делитесь советами, как такое можно оптимизировать.
Помните, оптимизировать нужно только тогда, когда это действительно потребуется, но способы лучше знать заранее.