Всем привет! Меня зовут Алексей Пьянков, я эксперт Отдела экспертизы по техническим компонентам SAP компании Норникель. В этой статье поделюсь с вами некоторыми нюансами использования оператора FOR ALL ENTRIES в АВАР.

Регулярно просматривая ракурс m_expensive_statements на БД SAP HANA, которая обслуживает продуктивную систему SAP ERP, временами, замечаю в ТОПе среди большого количества классических записей CALL  "CL_J_3RMOBVEDH… , отдельные записи, statement_string которых начинается с SELECT /* FDA WRITE */.

Что это за зверь такой /* 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 запрос, быстро и красиво, но случаются нюансы.

И эти нюансы легче всего обнаружить в m_expensive_statements. В поле application_source для соответствующей строки этой таблицы можно найти, что-то похожее на “SAPLRSA3:1422”. Если запустить транзакцию DBA_VIEW_ABAP_SOURCE и скормить ей эти данные, то она бросит вас прямо в редактор кода на то место, где находится пациент.

Итак, встречайте:

Пациент №1:

Код был написан на старте проекта внедрения и успешно работал, не вызывая никаких проблем несколько лет, а потом вдруг начал выполняться часами создавая дикую нагрузку на процессоры БД.

Пациент № 2:

Здесь, внезапно, после переноса небольшого изменения, десяток пользователей, запустивших этот отчет, чуть не обрушили БД. HANA встала колом показывая 100% утилизацию процессора.

Пациент №3:

Лаконично, но очень эффективно. Пара десятков процессов, запустивших это код, создали критическую проблему с быстродействием системы, процессы пришлось рубить руками Базиса.

В этом пациенте я отменил желтым маркером то, что приводит к плачевному результату – сочетание FOR ALL ENTRIES и OR

Теперь вы можете сами поискать такие сочетания у пациентов №1 и №2. В комментариях напишите – удалось ли найти?

Такие запросы могут легко работать на старте проекта, когда данных в системе немного. Но когда проектная команда уйдет и начнутся будни поддержки, OR в комплекте с FOR ALL ENTRIES однажды гарантировано положат ваш сервер БД. 

И это ни какая-то особенность SAP HANA, это всеобщий закон вселенной Баз Данных, про который можно чуть подробнее прочитать, здесь же на Хабре про PostgreSQL – ищите раздел BitmapOr vs UNION

Собственно, здесь же и содержится ответ, что с этим делать. Нужно просто разбить запрос на два и соединить результаты. Вместо UNION у второго запроса напишите APPENDING TABLE вместо INTO TABLE и SAP опять начнет летать как на старте проекта!

Резюмирую:

Господа АВАРеры, постарайтесь воздержаться от использования OR в запросах с FOR ALL ENTRIES.

PS.         Прямо сейчас наблюдаю, как третий час выполняется еще один запрос с FOR ALL ENTRIES, написанный на заре проекта внедрения:

Ставьте лайки, пишите комментарии, делитесь советами, как такое можно оптимизировать.

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

Комментарии (2)


  1. Vest
    02.08.2023 19:55

    Позвольте спросить, так почему CPU на БД был под 100%? Что было не так с выборкой?

    Хана попыталась выполнить два подзапрос одновременно или что? Можно узнать план первого примера, что в нём оказалось дорогим?

    Извините за 1000 вопросов.


  1. OcTep
    02.08.2023 19:55

    Тут напрашивается выбрать сразу все явные lt_bkpf-awkey. Потом уже в цикле по et_docs_reg_material почистить записи где belnr <> lt_bkpf-belnr