#mysql #pagination #sql-order-by #union-all
#mysql #разбивка на страницы #sql-order-by #объединение-все
Вопрос:
У меня проблема с разбиением на страницы двух больших таблиц:
Receipts table: id, receipt_date, record_details (650k records)
Z Reports table: id, receipt_date, record_details (88k records)
Что я хочу сделать, так это отсортировать обе эти таблицы по receipt_date
и union, после чего я хочу разбить их на страницы. В настоящее время у меня есть этот SQL (не совсем, но основная идея заключается в следующем):
SELECT c.id, c.receipt_date, c.col_type FROM (
SELECT a.id, a.receipt_date, 'receipt' AS coltype
FROM `terminal_receipts` a
WHERE `a`.`deleted` IS NULL
UNION ALL
SELECT b.id, b.receipt_date, 'zreport' AS coltype
FROM z_reports` b WHERE `b`.`deleted` IS NULL
) c
ORDER BY receipt_date desc LIMIT 50 OFFSET 0
Таким образом, сервер выбирает все записи из двух таблиц, упорядочивает их по дате, а затем применяет разбивку на страницы.
Но когда количество строк увеличивается, выполнение этого запроса займет больше времени. Существует ли какой-либо другой алгоритм для получения того же результата, не зависящего от размеров таблицы?
Ответ №1:
Существует метод, называемый методом поиска, о котором вы можете прочитать здесь . В соответствии с этим вам необходимо определить набор столбцов, который однозначно идентифицирует каждую строку. Затем этот набор столбцов будет использоваться с предикатом при поиске по базе данных.
В ссылке, которую я упомянул, есть несколько примеров, но вот еще один, очень простой:
CREATE TABLE IF NOT EXISTS `docs` (
`id` int(6) unsigned NOT NULL,
`rev` int(3) unsigned NOT NULL,
`content` varchar(200) NOT NULL,
PRIMARY KEY (`id`,`rev`)
) DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`id`, `rev`, `content`) VALUES
('1', '1', 'The earth is flat'),
('2', '1', 'One hundred angels can dance on the head of a pin'),
('1', '2', 'The earth is flat and rests on a bull's horn'),
('1', '3', 'The earth is like a ball.');
SELECT *
FROM `docs`
ORDER BY rev, id
LIMIT 2;
SELECT *
FROM `docs`
WHERE (rev, id) > (1, 2) # let's use the last row from the previous select with the predicate
ORDER BY rev, id
LIMIT 2;
SELECT *
FROM `docs`
WHERE (rev, id) > (3, 1) # same idea
ORDER BY rev, id
LIMIT 2;
Наличие индексов еще больше ускорит разбиение на страницы.
Надеюсь, это поможет.
Комментарии:
1. Спасибо за ответ, но порядок основан на дате и времени, и есть две таблицы, которые мне тоже не очень помогают. например, если я их индексирую, это может быть
z1 r1 r2 r3 z2 r4 r5 r6 r7 r8 z3
etc, и мне понадобятся два маркера.