Как сделать запрос на разбивку на страницы

задняя часть база данных MyBatis SQL
Как сделать запрос на разбивку на страницы

Функция пейджинга является очень распространенной функцией, особенно когда объем данных становится все больше и больше, запрос пейджинга имеет важное значение. Существует множество способов реализации функции подкачки. Если вы не используете подключаемый модуль подкачки, вам нужно разбивать страницы вручную.Поскольку разные базы данных реализуют разбиение на страницы, операторы SQL не согласованы, например, Mysql использует ключевое слово limit, а Oracle использует rownum, поэтому схема разбиения по страницам, описанная в этой статье, применимо только в базе данных Mysql.

Схема пейджинга на основе лимита

Во-первых, давайте поговорим о нескольких требованиях, которым должны соответствовать операции подкачки: одно — упорядоченность, а другое — неповторяемость. Упорядочивание можно рассматривать как необходимое условие отсутствия дублирования, потому что, если данные неупорядочены, нет гарантии отсутствия дублирования между несколькими страницами. Таким образом, операции постраничного вывода часто требуют сначала отсортировать данные, а затем добавить условия постраничного вывода. Первая схема, о которой мы говорим, — это схема пейджинга на основе ограничений, которая также является схемой пейджинга, используемой многими плагинами пейджинга. Давайте начнем с просмотра наших тестовых данных.

Сначала посмотрите на структуру таблицы:

mysql> desc user;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | bigint(20) | NO   | PRI | NULL    |       |
| name  | char(50)   | NO   |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set

Вы можете видеть, что наша пользовательская таблица имеет только 2 столбца: идентификатор типа bigint и имя типа char.

Далее смотрите данные в таблице ниже:

mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
|    45116 |
+----------+
1 row in set

mysql> select * from user order by id asc limit 10;
+----+--------+
| id | name   |
+----+--------+
|  0 | user_0 |
|  1 | user_1 |
|  2 | user_2 |
|  3 | user_3 |
|  4 | user_4 |
|  5 | user_5 |
|  6 | user_6 |
|  7 | user_7 |
|  8 | user_8 |
|  9 | user_9 |
+----+--------+
10 rows in set

Видно, что число данных равно 45 000.

Относительно просто реализовать пейджинг на основе лимита:

mysql> select * from user order by id asc limit 10000,10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10000 | user_10000 |
| 10001 | user_10001 |
| 10002 | user_10002 |
| 10003 | user_10003 |
| 10004 | user_10004 |
| 10005 | user_10005 |
| 10006 | user_10006 |
| 10007 | user_10007 |
| 10008 | user_10008 |
| 10009 | user_10009 |
+-------+------------+
10 rows in set

Среди них первый параметр после limit указывает индекс, то есть запись начинается с 10000-й строки, а второй параметр указывает, что всего берется 10 строк записей.

Использовать лимит для пейджинга очень просто, но есть ли какие-то проблемы?

Давайте сначала рассмотрим два элемента, которым должна соответствовать нумерация страниц: упорядоченность и неповторение. В приведенном выше утверждении мы использовали порядок по для сортировки, поэтому он может удовлетворять порядку, но удовлетворяет ли он неповторяемости? Предположим, между текущей страницей и следующей страницей запроса вставлена ​​запись, а id данных меньше самого большого id в записях текущей страницы, что произойдет? Давайте проверим это:

mysql> select * from user order by id asc limit 10000,10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10000 | user_10000 |
| 10001 | user_10001 |
| 10002 | user_10002 |
| 10003 | user_10003 |
| 10004 | user_10004 |
| 10005 | user_10005 |
| 10006 | user_10006 |
| 10007 | user_10007 |
| 10008 | user_10008 |
| 10009 | user_10009 |
+-------+------------+
10 rows in set

mysql> insert into user(id,name) values(-1,'user_-1');
Query OK, 1 row affected
mysql> select * from user order by id asc limit 10010,10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10009 | user_10009 |
| 10010 | user_10010 |
| 10011 | user_10011 |
| 10012 | user_10012 |
| 10013 | user_10013 |
| 10014 | user_10014 |
| 10015 | user_10015 |
| 10016 | user_10016 |
| 10017 | user_10017 |
| 10018 | user_10018 |
+-------+------------+
10 rows in set

Видно, что когда мы вставляем запись между двумя соседними страницами запроса, запись на следующей странице и на предыдущей странице дублируется (запись с id 10009 появляется на двух соседних страницах). Причина в том, что после вставки записи структура страниц изменилась, поэтому будут дублироваться данные.

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

Схема пейджинга на основе лимита и сравнения

Еще один способ записи пейджинга можно рассмотреть таким образом, например, мы хотим взять 10 строк записей, начиная с строки 10000, тогда мы можем сначала узнать и отсортировать данные, которые больше или равны 10000 строк, а затем вынуть первые 10 строк записей. , что также завершает разбиение на страницы. Затем посмотрите на конкретный оператор SQL:

mysql> select * from user where id >=10000 order by id asc limit 10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10000 | user_10000 |
| 10001 | user_10001 |
| 10002 | user_10002 |
| 10003 | user_10003 |
| 10004 | user_10004 |
| 10005 | user_10005 |
| 10006 | user_10006 |
| 10007 | user_10007 |
| 10008 | user_10008 |
| 10009 | user_10009 |
+-------+------------+
10 rows in set

Таким образом, этот способ написания предотвращает вышеуказанные проблемы? Давайте проведем тест, чтобы узнать.

mysql> select * from user where id >=10000 order by id asc limit 10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10000 | user_10000 |
| 10001 | user_10001 |
| 10002 | user_10002 |
| 10003 | user_10003 |
| 10004 | user_10004 |
| 10005 | user_10005 |
| 10006 | user_10006 |
| 10007 | user_10007 |
| 10008 | user_10008 |
| 10009 | user_10009 |
+-------+------------+
10 rows in set

mysql> insert into user(id,name) values(-4,'user_-4');
Query OK, 1 row affected
mysql> select * from user where id >=10010
 order by id asc limit 10;
+-------+------------+
| id    | name       |
+-------+------------+
| 10010 | user_10010 |
| 10011 | user_10011 |
| 10012 | user_10012 |
| 10013 | user_10013 |
| 10014 | user_10014 |
| 10015 | user_10015 |
| 10016 | user_10016 |
| 10017 | user_10017 |
| 10018 | user_10018 |
| 10019 | user_10019 |
+-------+------------+
10 rows in set

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

Конечно, этот поисковый запрос также ограничен. Это применимо только в том случае, если столбец, используемый для сортировки, уникален.В приведенном выше примере столбец id является первичным ключом, поэтому он уникален, поэтому вы можете использовать этот метод для разбиения по страницам. Если столбец, используемый для сортировки, не уникален, например метка времени, то этот метод листания тоже может повторяться, можно подумать, почему.

Если вы считаете, что эта статья была вам полезна, вы можете отсканировать QR-код ниже и обратить внимание на мой паблик-аккаунт «Java Architecture Meditation».