Всем привет! Меня зовут Алексей Пьянков, я эксперт Отдела экспертизы по техническим компонентам 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)
OcTep
02.08.2023 19:55Тут напрашивается выбрать сразу все явные lt_bkpf-awkey. Потом уже в цикле по et_docs_reg_material почистить записи где belnr <> lt_bkpf-belnr
Vest
Позвольте спросить, так почему CPU на БД был под 100%? Что было не так с выборкой?
Хана попыталась выполнить два подзапрос одновременно или что? Можно узнать план первого примера, что в нём оказалось дорогим?
Извините за 1000 вопросов.