Получить общее количество строк перед разбивкой на страницы в JOOQ? - PullRequest
1 голос
/ 16 июня 2020

Мне интересно узнать, есть ли более оптимальный способ получения общего количества строк из запроса JOOQ перед разбивкой на страницы с помощью OFFSET и LIMIT

Мы пробовали использовать предложение JOOQs syntheti c SEEK однако, поскольку наши идентификаторы являются неупорядоченными UUID, это не работает.

Наша текущая реализация заключается в том, чтобы выполнить запрос дважды, в первый раз перед тем, как мы установим смещение и ограничение для получения результата / количества строк.

Затем мы получаем результаты во втором запросе.

    SelectQuery<Record> select = context.selectQuery();
    select.addSelect(FOO_TABLE.fields());
    select.addFrom(FOO_TABLE);


    int totalElements = select.fetch().size();

    select.addOffset(20);
    select.addLimit(50));

    List<Foo> paginatedFoo = select.fetchInto(Foo.class);

Это просто то, что нужно принять с этой реализацией / дизайном, или есть ли какой-нибудь драйвер JDB C magi c, что избавит от необходимости выполнять два запроса к БД?

Любой ввод или предложения приветствуются!

1 Ответ

1 голос
/ 16 июня 2020

Мы пробовали использовать предложение JOOQs syntheti c SEEK, однако, поскольку наши идентификаторы являются неупорядоченными UUID, оно не работает.

При разбивке на страницы вы упорядочиваете что-то значимое для пользователя. Таким образом, вы, вероятно, сначала будете заказывать / искать какой-нибудь другой столбец (например, какой-нибудь столбец DATE), а затем используйте UUID только для получения однозначных, стабильных результатов. Я не понимаю, почему SEEK не сработает для вас.

Если использование SEEK (разбивка на страницы) имеет смысл для вашего приложения, логически это намного предпочтительнее для причины производительности:

  1. Вам не нужно считать, потому что это не имеет значения
  2. Вам не нужно использовать смещение

Это просто что-то, что должно быть принято с этой реализацией / дизайном, или есть какой-либо JDB C драйвер magi c, который устраняет необходимость в двух запросах, которые должны выполняться в БД ?

Это большая дополнительная работа для базы данных. Особенно, если вы сделаете это так:

// Don't do this!
int totalElements = select.fetch().size();

Теперь вы переносите весь набор данных! Если вы должны подсчитать количество строк в отдельном запросе, по крайней мере, полностью выполнить этот запрос в базе данных:

// Do this instead (prior to adding the limit):
context.fetchCount(select);

Но почему бы просто не использовать оконную функцию? Добавьте DSL.count().over() к вашему запросу, чтобы вычислить общее количество строк, которое было бы создано вашим запросом, если бы вы не выполняли разбиение на страницы, и все готово.

Причина, по которой вы можете использовать оконные функции для этого потому что они вычисляются после всех других операций (WHERE, GROUP BY, HAVING, и c.), но до разбивки на страницы (OFFSET, LIMIT). См. Эту статью о логическом порядке операций .

...