Логика вывода записей в таблицу (MasterDetailScreen) (7.2.4)

Добрый день.
Просьба проконсультировать, по какой логике отрабатывает вывод записей в таблицу.

Есть MasterDetailScreen, некоторые методы которого переопределены.
Есть экран на основе этого MDS, таблица которого наполняется из справочника с большим количеством записей (более 222К).
Настройки количества выводимых записей на одной странице таблицы стандартные - 50 штук.

Сейчас когда листаешь страницы таблицы, первые страницы (1 - 150, 51 - 100, 101 - 150, …) пролистываются быстро. (около 0,3-0,5 секунд в браузере).
Если я нажимаю на кнопку перехода на последнюю страницу
image
то последних 50-ти (или сколько доступно) записей грузятся намного дольше (порядка 10 секунд).
Соответственно, если я листаю с конца списка ,
image
то загрузка также длится около 10 секунд на 50 записей.

При изменении числа выводимых записей на странице (пробовал при 100, 1000, 5000) скорость загрузки последних страниц таблицы не изменяется, все также около 10 секунд.

Скорее всего, чем сложнее объект, тем дольше времени займет подобная загрузка (для сложных объектов в нашем проекте при количестве 140К время загрузки могло доходить до 40 секунд!)

При замерах сортировка включена по проиндексированному полю с читаемым для пользователя идентификатором сущности.

Я проанализировал, какие в момент загрузки страницы запросы идут к СУБД; увидел, что запросы идут вида:
SELECT
все_необходимые поля
FROM источник и всякие разные JOIN ссылочных объектов
WHERE условие
ORDER BY Колонка сортировки таблицы
Они направляются при каждом новом перелистывании страницы таблицы, и как минимум раз для страницы, если не включен кеш запросов.

В подобном запросе нет ограничений выборки OFFSET, TOP, LIMIT и подобного.
Вопрос:
Я верно понимаю, что дальнейшая обработка и партиционирование (по 50,100, 1000 и т.д как настроено в коде приложения) производится программно?
Если да, то это сделано, так как из-за особенностей синтаксиса разных СУБД, где могут не поддерживаться OFFSET, TOP, LIMIT?
По этой причине партиционирование в конце коллекции данных происходит дольше? (потому что приложению необходимо разбить все данные до этой страницы также на партии?)

Могу ли я это как-то настроить - оптимизировать у себя в проекте?

Работает ли кеш сущностей и настройка в app.properties?
eclipselink.cache.shared.itam_Portfolio = true
eclipselink.cache.size.itam_Portfolio = 500
где itam_Portfolio - имя метакласса объекта.

моя Idea подчеркивает эти строки как неиспользуемые…

Запросы в БД должны содержать ограничения типа offset/limit.
Какую СУБД вы используете и как вы смотрите текст запросов?

Мы используем MSSQL, смотрим в мониторе запросов.

Здравствуйте.
Не могли бы вы приложить текст sql запросов к топику?

Конечно.

Сведения

SELECT t2.id,
t2.add_comment,
t2.code,
t2.comment_,
t2.create_date,
t2.delete_ts,
t2.deleted_by,
t2.description,
t2.priority,
t2.status,
t2.title,
t2.type_,
t2.version,
t2.category_id,
t2.lnk_contact_id,
t2.lnk_interaction_id,
t2.lnk_nature_id,
t2.lnk_recipient_id,
t0.id,
t0.discriminator,
t0.delete_ts,
t0.deleted_by,
t0.entity_type,
t0.NAME,
t0.version,
t3.id,
t3.dtype,
t3.delete_ts,
t3.deleted_by,
t3.login,
t3.version,
t3.fio,
t4.id,
t4.assign_date,
t4.cancellation_date,
t4.close_date,
t4.closure_code,
t4.code,
t4.contact_not_same_recipient,
t4.create_ts,
t4.created_by,
t4.delete_ts,
t4.deleted_by,
t4.description,
t4.escalate_date,
t4.has_escalated_records,
t4.recipient_mail_address,
t4.resolution,
t4.resolution_date,
t4.source,
t4.status,
t4.title,
t4.update_ts,
t4.updated_by,
t4.version,
t4.work_date,
t4.lnk_assignee_id,
t4.lnk_category_id,
t4.lnk_contact_id,
t4.lnk_created_by_fio_id,
t4.lnk_nature_id,
t4.lnk_recipient_id,
t4.lnk_updated_by_fio_id,
t4.lnk_work_group_id,
t5.id,
t5.dtype,
t5.delete_ts,
t5.deleted_by,
t5.login,
t5.version,
t5.fio,
t6.id,
t6.delete_ts,
t6.deleted_by,
t6.NAME,
t6.version,
t7.id,
t7.dtype,
t7.delete_ts,
t7.deleted_by,
t7.login,
t7.version,
t7.fio,
t8.id,
t8.dtype,
t8.delete_ts,
t8.deleted_by,
t8.login,
t8.version,
t8.fio,
t9.id,
t9.delete_ts,
t9.deleted_by,
t9.NAME,
t9.version,
t9.lnk_proc_definition_id,
t10.id,
t10.code,
t10.delete_ts,
t10.deleted_by,
t10.deployment_date,
t10.NAME,
t10.version,
t11.id,
t11.dtype,
t11.delete_ts,
t11.deleted_by,
t11.login,
t11.version,
t11.fio,
t12.id,
t12.dtype,
t12.delete_ts,
t12.deleted_by,
t12.login,
t12.version,
t12.fio,
t13.id,
t13.alias,
t13.delete_ts,
t13.deleted_by,
t13.NAME,
t13.version,
t14.id,
t14.delete_ts,
t14.deleted_by,
t14.NAME,
t14.version,
t15.id,
t15.dtype,
t15.delete_ts,
t15.deleted_by,
t15.login,
t15.version,
t15.fio
FROM itam_request t2
LEFT OUTER JOIN (sys_category t0
JOIN itam_dynamic_attr_set t1
ON ( t1.id = t0.id ))
ON ( t0.id = t2.category_id )
LEFT OUTER JOIN sec_user t3
ON ( t3.id = t2.lnk_contact_id )
LEFT OUTER JOIN itam_interaction t4
ON ( t4.id = t2.lnk_interaction_id )
LEFT OUTER JOIN sec_user t5
ON ( t5.id = t4.lnk_assignee_id )
LEFT OUTER JOIN itam_interaction_category t6
ON ( t6.id = t4.lnk_category_id )
LEFT OUTER JOIN sec_user t7
ON ( t7.id = t4.lnk_contact_id )
LEFT OUTER JOIN sec_user t8
ON ( t8.id = t4.lnk_created_by_fio_id )
LEFT OUTER JOIN itam_nature t9
ON ( t9.id = t4.lnk_nature_id )
LEFT OUTER JOIN bpm_proc_definition t10
ON ( t10.id = t9.lnk_proc_definition_id )
LEFT OUTER JOIN sec_user t11
ON ( t11.id = t4.lnk_recipient_id )
LEFT OUTER JOIN sec_user t12
ON ( t12.id = t4.lnk_updated_by_fio_id )
LEFT OUTER JOIN itam_work_group t13
ON ( t13.id = t4.lnk_work_group_id )
LEFT OUTER JOIN itam_nature t14
ON ( t14.id = t2.lnk_nature_id )
LEFT OUTER JOIN sec_user t15
ON ( t15.id = t2.lnk_recipient_id )
WHERE ( t2.delete_ts IS NULL )
ORDER BY t2.code DESC,
t2.id DESC

Поиск подобного вида ничего не выводит (пробовал и в верхнем, и в нижнем регистре, offset и fetch)
SELECT Txt.query_text_id, Txt.query_sql_text
FROM sys.query_store_query_text AS Txt
where Txt.query_sql_text like ‘%OFFSET%’

Приложил.

Здравствуйте,
EclipseLink для MSSQL не поддерживает подстановку параметров maxResult/firstResult в SQL запрос.
Paging осуществляется за счет JDBC API драйвера: выставление размера выборки java.sql.Statement#setMaxRows и смещение java.sql.ResultSet#absolute. Скорее всего это работает медленнее чем простановка значений в SQL запрос.

Paging с использованием SQL offset/limit/top корректно работает для: HSQL, Postgres, MySQL, Oracle (некоторые подробности по поддержке есть в https://wiki.eclipse.org/EclipseLink/Examples/JPA/Pagination)

1 Симпатия

Андрей, а вы случайно не знаете с чем связано такое ограничение? На сколько мне известно (с 2011 версии) в MS SQL поддерживается OFFSET/FETCH NEXT.

В EclipseLink для MSSQL для старых версий и новых версий используется один и тот же диалект. Я думаю это больше вопрос совместимости со старыми версиями и поддержку новых фич MSSQL они просто не делали.
В платформе завели issue: https://github.com/cuba-platform/cuba/issues/2895 возможно в будущем удастся это исправить.

2 Симпатий

Спасибо за развернутый ответ.
по п.2 подскажите, пожалуйста.

Работает ли кеш сущностей и настройка в app.properties?
eclipselink.cache.shared.itam_Portfolio = true
eclipselink.cache.size.itam_Portfolio = 500
где itam_Portfolio - имя метакласса объекта.

По факту кеш запросов не отрабатывает, пока я не укажу eclipselink.cache.shared.***, но ворнинг в идее меня смущает, она подчеркивает эти строки как неиспользуемые…

WARNING от неиспользуемых строк это не страшно - они по факту используются.
КЭШ запросов хранит ID cущностей, то есть его использование без КЭШа сущностей не имеет смысла - поскольку загрузка объектов будет происходить из БД по каждому ID.
Сейчас, насколько помню, в лог пишется сообщение о том, что используется КЭШ запросов без использования КЭШа по сущностям.

То есть это нормально, что вы указываете КЭШ по сущностям.

1 Симпатия