Медленный ВЫБОР ДЛЯ ВСЕХ ЗАПИСЕЙ

Приведенный ниже SELECT работает с внутренней таблицей GIT_KUNNR_TAB, содержащей 2.291.000 строк с уникальными клиентами (kunnr), и занимает 16 минут.

  select kunnr umsks umskz gjahr belnr buzei bschl shkzg dmbtr bldat
           zfbdt zbd1t zbd2t zbd3t rebzg rebzj rebzz rebzt
        into corresponding fields of table git_oi_tab
      from bsid
        for all entries in git_kunnr_tab
      where bukrs  =  p_bukrs
        and kunnr  =  git_kunnr_tab-kunnr 
        and umsks  = ' '
        and augdt  =   clear_augdt
        and budat  le  p_key 
        and blart  in  s_blart
        and xref3  in  s_xref3.

BSID содержит в общей сложности 20.000.000 записей, а для 2.291.000 уникальных клиентов он получает 445.000 записей от BSID.

В большинстве случаев в GIT_KUNNR_TAB строк еще больше.

Есть ли более быстрый выбор?


person ekekakos    schedule 22.04.2019    source источник
comment
По любому вопросу о производительности вам лучше прикрепить execution plan (ST05), который сообщает, что делает база данных для оптимизации чтения. Это индивидуально для каждой системы. Обратите внимание, что FOR ALL ENTRIES является конструкция ABAP, которая разделяет SELECT на множество SELECT, разделяя GIT_KUNNR_TAB на группы по 5 строк (значение 5 можно изменить в параметрах профиля rsdb/max_[in_]blocking_factor или подсказке max_[in_]blocking_factor)   -  person Sandra Rossi    schedule 22.04.2019
comment
@SandraRossi 5 истинно только для Oracle по умолчанию, это 50 для DB2 и 100 для HANA.   -  person András    schedule 22.04.2019
comment
@ András значение может даже различаться в зависимости от базы данных, версии SAP и ГДЕ (в настоящее время на HANA, 50 или 100 в зависимости от ГДЕ)   -  person Sandra Rossi    schedule 29.04.2019
comment
@SandraRossi, я знаю, но я не хотел перечислять все случаи и исключения в комментарии   -  person András    schedule 29.04.2019


Ответы (2)


Drop the FOR ALL ENTRIES part

Скорее всего, остальная часть условия WHERE достаточно избирательна. Вы получаете больше записей, чем необходимо, но намного быстрее.

Поскольку git_kunnr_tab уникален, вы можете превратить его в HASHED-таблицу и отфильтровать git_oi_tab с ней на сервере приложений.

SELECT kunnr umsks umskz gjahr belnr buzei bschl shkzg dmbtr bldat
       zfbdt zbd1t zbd2t zbd3t rebzg rebzj rebzz rebzt
    INTO corresponding fields of table git_oi_tab
    FROM bsid
    WHERE bukrs = p_bukrs 
      AND umsks = ' ' 
      AND augdt = clear_augdt 
      AND budat le p_key 
      AND blart in s_blart 
      AND xref3 in s_xref3.

DATA: lt_kunnr_tab TYPE HASHED TABLE of <type of git_kunnr_tab>
          WITH UNIQE KEY kunnr.
lt_kunnr_tab = git_kunnr_tab.
LOOP AT git_oi_tab ASSIGNING FIELD-SYMBOL(<fs_oi>).
  READ TABLE lt_kunnr_tab TRANSPORTING NO FIELDS
      WITH KEY kunnr = <fs_oi>-kunnr.
    IF sy-subrc <> 0
      DELETE git_oi_tab.
    ENDIF.
  ENDIF.
ENDLOOP.
FREE lt_kunnr_tab.

This is not a general solution

Если таблица драйверов FAE содержит более 20% строк целевой таблицы, полное удаление ее в основном полезно для скорости.
Если в ней меньше строк, лучшим решением будет FAE.

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

FOR ALL ENTRIES vs Range table

Вы можете увидеть много мест в Интернете, где таблицы диапазонов работают быстрее, чем FAE. Это верно в некоторых очень конкретных случаях:

  • Используется только одно поле из таблицы драйверов FAE 1
  • В таблице драйверов больше строк, чем FAE отправляет за один пакет.
  • По умолчанию размер пакета составляет 5 в Oracle, 50 в DB2, 100 в HANA.
  • В таблице Range не так много строк, чтобы вызывать дамп
  • Максимальная длина составляет 1048 576 байт (примечание 1002491).

Таблицы диапазонов могут быть быстрее, чем FAE, потому что они отправляют все условия фильтрации в одном запросе. Это, конечно, опасно, поскольку размер запроса ограничен. Если он превышает установленный лимит, вы получите дамп.

Однако, используя подсказку MAX_IN_BLOCKING_FACTOR и MAX_BLOCKING_FACTOR, вы можете дать FAE все преимущества таблиц диапазонов без их недостатков за счет увеличения размера пакета.

Поэтому используйте таблицы диапазонов только с фактическими диапазонами, например between A and C или not between G and J.


  1. это не о скорости, а о функциональной корректности. Таблицы диапазонов обрабатывают поля независимо, в то время как FAE работает со строками
person András    schedule 22.04.2019
comment
Согласовано для текущего случая, но это может быть контрпродуктивным, если количество строк в git_kunnr_tab мало. - person Sandra Rossi; 22.04.2019
comment
Андрас спасибо за ответ. Реализую завтра и сообщу о результатах. Я также пытаюсь найти способ реализовать этот выбор в параллельной обработке abap. Ваш, думаю, нормально. - person ekekakos; 22.04.2019
comment
Извини, Андрас, но мне пришлось решить некоторые производственные проблемы, и я не стал этого делать. Может быть завтра. Я дам вам знать все. Спасибо. - person ekekakos; 23.04.2019
comment
Каков предел диапазона строк в seltab при вызове дампа? - person Suncatcher; 24.04.2019
comment
@Suncatcher Максимальная длина оператора - 1 МБ (1048 576 байт). - person András; 25.04.2019
comment
Так это зависит от длины аргументов диапазона, а не от количества строк? - person Suncatcher; 25.04.2019
comment
@Suncatcher не напрямую. Вы умножаете количество строк на ширину, и оно должно уместиться в 1 МБ - person András; 25.04.2019
comment
Всем привет. Извините за задержку, но у нас были пасхальные каникулы. Сегодня я внедряю ваше решение, Андрас, и оно работает быстрее, а точнее всего за 10 минут по некоторым критериям выбора. Я также добавляю выделение в BSAD, добавляя itab после выбора BSID. Но я заметил странную вещь и хочу узнать ваше мнение. Утром селекция с FAE составила 20 минут, в 13:00 - 2 минуты и снова в 16:00 - 20 минут. Все это происходит в системе разработки по одним и тем же критериям. Может кто-нибудь сказать мне, почему это произошло? Спасибо - person ekekakos; 06.05.2019
comment
Скорее всего, в 13:00 все нужные страницы еще были в кеше. Затем if был сброшен за некоторое время до 16:00, так что нужно было читать с диска. Вы можете проверить, запустив его три раза подряд. Первый раз может быть медленным (страницы в кеше или нет), но два последних должны быть одинаково быстрыми. Если это не так, значит, кто-то, должно быть, выполнял дорогостоящий запрос к той же таблице утром и в 16:00. - person András; 06.05.2019
comment
Спасибо, Андрас, я проверю и расскажу. - person ekekakos; 08.05.2019
comment
@ekekakos, как все прошло? - person András; 09.10.2020

Обычно для одного поля использование диапазона намного быстрее. Поэтому, если вы выбираете данные по некоторому ключу из внутренней таблицы, сравнивая только одно поле из таблицы, превратите его в диапазон вместо FAE:

TYPES:
  tr_kunnr TYPE RANGE OF kunnr.

* or just do loop/append if you on the old system (>7.4)
DATA(lr_kunnr) = VALUE tr_kunnr(
  FOR <fs_oi> IN git_oi_tab
  (
    sign    = 'I'
    option  = 'EQ'
    low     = fs_oi-kunnr
  )
). 

 select kunnr umsks umskz gjahr belnr buzei bschl shkzg dmbtr bldat
           zfbdt zbd1t zbd2t zbd3t rebzg rebzj rebzz rebzt
        into corresponding fields of table @git_oi_tab
      from bsid
      where bukrs  =  @p_bukrs
        and kunnr  in @lr_kunnr...

Я не могу найти статью, но было проведено расследование, и диапазон намного быстрее в случае одного полевого сравнения, чем FAE.

person Ilya Kaznacheev    schedule 22.04.2019
comment
Это миф, потому что FOR ALL ENTRIES IN itab WHERE column = itab-column во время выполнения преобразуется в несколько SELECT, каждый из которых выполняет WHERE column IN ('A','B'...) (см. Примечание 48230 Параметризация оператора SELECT ... FOR ALL ENTRIES). Так что нет никакой разницы в том, чтобы делать это явно. - person Sandra Rossi; 23.04.2019
comment
Разница заключается в размере пакетов, которые передаются из БД в AS каждого размера. Возможно, это было изменено в более поздних версиях, но в остальном это основная причина. - person Ilya Kaznacheev; 24.04.2019
comment
Обычно (без подсказок) он преобразует SELECT в набор подзапросов. Я мог бы дать ссылку на отличную статью с глубоким расследованием дела, но она на русском языке. Использование подсказок - плохая практика в обычном сценарии, потому что они переопределяют базовые настройки и систему нелегко масштабировать. - person Ilya Kaznacheev; 24.04.2019
comment
Приведенное выше примечание служило подтверждением того, как ABAP SELECT неявно преобразуется в несколько SELECT для базы данных, я не хотел говорить о подсказках. stackoverflow требует, чтобы здесь были представлены аргументы, а ссылка служила ссылкой. Добавить ссылку на другом языке - не проблема, потому что в настоящее время достаточно инструментов для перевода. - person Sandra Rossi; 24.04.2019
comment
@IlyaKaznacheev вся цель подсказок - переопределить базовые настройки. Они являются общими, но подсказки могут быть адаптированы к конкретным запросам. - person András; 25.04.2019
comment
@IlyaKaznacheev, сообщение в блоге хорошее, но даже его автор говорит в комментариях, что RANGEs плохие. - person András; 27.04.2019
comment
@IlyaKaznacheev спасибо. Но это [сообщение в блоге] (habr.com/ru/post/262649) не о IN, а просто о FOR ALL ENTRIES IN. Нигде нет аргументов в пользу того, что IN быстрее. - person Sandra Rossi; 29.04.2019