В настоящее время мы изучаем способы ускорения наших приложений, а значительная часть этого связана со списком (фактически таблицей) объектов.Hibernate разбиение на страницы отсортированных данных с соединениями
Параметры и требования
Параметры и требования к этому списку являются следующие (я постараюсь упомянуть только важные из них здесь):
- Там может быть до 500000 строк/объектов в списке.
- Только пара из них отображается одновременно, здесь мы будем использовать разбивку на страницы.
- Пользователь может выбрать, какие столбцы должны отображаться в списке (поэтому мы не можем предоставить один «статический» запрос).
- Большинство столбцов списка сортируются и/или фильтруются.
- Объекты имеют пару ко многим отношениям, которые также предоставляют некоторые столбцы списка.
- Некоторые из этих столбцов списка могут содержать несколько значений (они отображаются как список внутри одной ячейки)
- Любые обновления данных, происходящие из действий текущего пользователя (например, редактирование, загрузка и т. Д.), Должны отражаться в список как можно быстрее (т.е. «immeditately»)
чтобы сделать модель немного яснее рассмотреть следующую упрощенную сущность (как в JPA) модель:
class Car {
String manufacturer;
String model;
Date dateOfProduction;
List<TyreSize> allowedTyreSizes;
Set<Date> inspectionDates;
}
Пожалуйста, не пытайтесь слишком много смысла в этой модели, поскольку это jus t, чтобы проиллюстрировать проблему (наши данные различны и намного сложнее).
А «полный» список автомобилей может выглядеть следующим образом:
+==============+=======+=======+===============+=============+
| Manufacturer | Model | Prod. | Allowed Tyres | Inspections |
+==============+=======+=======+===============+=============+
| BMW | 320d |01/2016| - 225/40 R18 | - 01/07/16 |
| | | | - 225/45 R17 | - 13/12/16 |
+--------------+-------+-------+---------------+-------------+
| Toyota | Camry |09/2016| - 185/70 R13 | - 31/12/16 |
+--------------+-------+-------+---------------+-------------+
Поскольку пользователь может выбрать столбцы, которые будут отображаться во время выполнения мы строим необходимые запросы динамически. Пока все хорошо работает.
Основная проблема
Проблема мы с является производительность при сортировке и фильтрации участвуют: Наш текущий подход заключается в загрузке всех данных, необходимых для сортировки и фильтрации в памяти, сделать сортировку и фильтрацию там и затем сохраните список отсортированных идентификаторов и страниц на них. Мы знаем, что это довольно медленно, но пока что производительность была достаточно хорошей, чтобы удовлетворить наше управление. Все изменилось, так как теперь у нас больше данных для работы, а требования к производительности повысились.
Таким образом, мы изучаем возможности для улучшения сортировки и фильтрации всех этих ADN данных в то время как мы в настоящее время следующий подход делает это на базе данных я все еще задаю этот (сторона) вопрос:
- Как лучше всего подобрать разбиение на страницы большого количества строк с динамическими столбцами и потенциально несколько значений на ячейку?
В настоящее время мы используем Postgresql и хотели бы продолжать использовать его, если это возможно, но если другое хранилище будет намного лучше, мы бы хотя бы это выяснили.
Текущий подход и вопрос (ы) (в нижней части)
Как описано выше, в настоящее время мы пытаемся иметь сортировки базы данных, фильтр и постраничной наши данные. Было бы хорошо использовать 2 запроса: один для получения идентификаторов строк для текущей страницы, а другой - для фактической загрузки данных для этих строк.
Поскольку задача является первым запрос я сосредоточусь на том, что:
AFAIK мы могли бы сделать что-то вроде этого в SQL (на примере автомобиля выше):
SELECT DISTINCT id FROM (
SELECT id, ... FROM car c
LEFT OUTER JOIN allowedtyresizes ats ON c.id = ats.car_id
LEFT OUTER JOIN tyresizes ts ON ts.id = ats.tyresize_id
... //additional joins if required
ORDER BY ... //apply any user-defined sorts
WHERE ... //apply any user-defined filters (or maybe put them into the joins)
)
OFFSET ... //page offset
LIMIT ... //page size
В теории запроса (возможно, это не совсем корректно) должен предоставить результат, нам нужно определить, какие строки загружать для текущей страницы.
Поскольку мы используем Hibernate (5.2 атм), мы хотели бы использовать HQL или Criteria для достижения этого. Однако кажется, что Hibernate не поддерживает выбор из инструкции select, как указано выше, и, следовательно, это может быть не жизнеспособным подходом. Если нам придется вернуться к родному SQL или совсем другому подходу, пусть будет так, но мы предпочли бы, чтобы он работал с инфраструктурой, которая в настоящее время существует.
Так вопросы:
- ли Hibernate поддержка 5.x что-то вроде "выбрать из выбора"?
- Как можно использовать разбиение на страницы с использованием Hibernate, когда сортировка и фильтрация должны выполняться во многих отношениях, то есть где одно соединение может приводить к дублированию строк?
Вы запускаете SQL-запрос с использованием HQL, передавая в него запрос как String –
@GauravSrivastav Да, мы знаем, как выполнить SQL-запрос, и если нет лучшего подхода, мы будем его использовать. Однако, поскольку запросы могут стать довольно сложными и создаваться динамически, нам бы хотелось, чтобы нам не приходилось обращаться к информации сопоставления наших объектов, чтобы извлечь информацию, необходимую для построения такого запроса, а не если Hibernate уже предоставляет что-то, что мы могли бы использовать. – Thomas
Насколько сложна ваша модель?Вероятно, вы получите лучшую производительность, используя представление (ы) базы данных и привязывая сущности к ним. Плохо то, что вам нужно будет вручную написать представление базы данных (и, возможно, другую версию, если вы начнете поддерживать новую RDBMS). Хорошо, что сущности станут проще, а у Hibernate меньше шансов создать плохо исполняемый SQL. –