Это зависит от вашего механизма базы данных (то есть, какого рода SQL), но почти каждый вариант SQL поддерживает разбиение на страницы запроса.
Например, MySQL имеет LIMIT , а MS SQL имеет ROW_NUMBER .
Таким образом, вы строите свой SQL как обычно, а затем просто добавляете материал разбивки на страницы для ядра СУБД, и сервер автоматически возвращает, скажем, строки с 10 по 20 результата запроса.
EDIT:
Таким образом, последний запрос (который выбирает данные, возвращаемые пользователю) выбирает данные из некоторых таблиц (временных или нет), как я и ожидал.
Это SELECT
запрос, который вы можете просмотреть с помощью LIMIT
в MySQL.
Ваше описание звучит для меня так, как будто фактические вычисления требуют гораздо больше ресурсов, чем окончательный запрос, который возвращает результаты пользователю.
Поэтому я бы сделал следующее:
- получить отдельные таблицы результатов для введенных слов и сохранить их в таблице таким образом, чтобы вы могли получить данные для этого конкретного запроса позже (например, с дополнительным столбцом, таким как SessionID или QueryID). Здесь нет нумерации страниц.
- запросите эти таблицы результатов еще раз для получения окончательного запроса, возвращаемого пользователю.
Здесь вы можете выполнить пейджинг, используя LIMIT
.
Таким образом, вы должны выполнять фактические вычисления (запросы с перегрузкой ресурсов) только один раз, когда пользователь «запускает» запрос. Затем вы можете вернуть пользователю разбитые на страницы результаты, просто выбрав из уже заполненной таблицы результатов.
РЕДАКТИРОВАТЬ 2:
Я только что увидел, что вы приняли мой ответ, но, тем не менее, вот более подробно о моем использовании "временных" таблиц.
Конечно, это только один из возможных способов сделать это. Если ожидаемый результат не слишком велик, то также возможен возврат всего набора результатов клиенту, сохранение его в памяти и выполнение пейджинговой части клиента (как вы предложили).
Но если мы говорим о реальных огромных объемах данных, из которых пользователь будет просматривать только несколько (например, результаты поиска Google), и / или о низкой пропускной способности, то вам нужно передать клиенту как можно меньше данных.
Об этом я и думал, когда писал этот ответ.
Итак: я не имею в виду «настоящую» временную таблицу, я говорю о «нормальной» таблице, используемой для сохранения временных данных.
Я гораздо лучше разбираюсь в MS SQL, чем в MySQL, поэтому я мало что знаю о временных таблицах в MySQL.
Я могу рассказать вам, как бы это сделать в MS SQL, но, возможно, есть лучший способ сделать это в MySQL, которого я не знаю.
Когда мне нужно выполнить пейджинг ресурсоемкого запроса, я хочу выполнить фактический расчет один раз, сохранить его в таблице и затем несколько раз запросить эту таблицу у клиента (чтобы избежать повторного вычисления для каждой страницы) .
Проблема в том, что в MS SQL временная таблица существует только в области запроса, в которой она создается.
Поэтому я не могу использовать временную таблицу для этого, потому что она исчезнет, когда я захочу запросить ее во второй раз.
Поэтому я использую "настоящие" таблицы для подобных вещей.
Я не уверен, правильно ли я понял ваш пример алгоритма, поэтому я немного упросту пример. Я надеюсь, что все равно смогу прояснить свою точку зрения:
Это таблица (это, вероятно, неверный MySQL, просто чтобы показать концепцию):
create table AlgorithmTempTable
(
QueryID guid,
Rank float,
Value float
)
Как я уже говорил, это не буквально "временная" таблица, это фактически настоящая постоянная таблица, которая просто используется для временных данных.
Теперь пользователь открывает ваше приложение, вводит свои поисковые слова и нажимает кнопку «Поиск».
Затем вы запускаете свой ресурсоемкий алгоритм, чтобы вычислить результат один раз и сохранить его в таблице:
insert into AlgorithmTempTable (QueryID, Rank, Value)
select '12345678-9012-3456789', foo, bar
from Whatever
insert into AlgorithmTempTable (QueryID, Rank, Value)
select '12345678-9012-3456789', foo2, bar2
from SomewhereElse
Гид должен быть известен клиенту. Возможно, вы можете использовать для этого SessionID клиента (если он у него есть и если он не может запустить более одного запроса одновременно ... или вы генерируете новый Guid на клиенте каждый раз, когда пользователь нажимает кнопку «Поиск», или что угодно).
Теперь все вычисления выполнены, и ранжированный список результатов сохранен в таблице.
Теперь вы можете запросить таблицу, фильтруя по QueryID:
select Rank, Value
from AlgorithmTempTable
where QueryID = '12345678-9012-3456789'
order by Rank
limit 0, 10
Из-за QueryID несколько пользователей могут делать это одновременно, не вмешиваясь в запросы друг друга. Если вы создаете новый QueryID для каждого поиска, один и тот же пользователь может даже запустить несколько запросов одновременно.
Теперь осталось сделать только одно: удалить временные данные, когда они больше не нужны (только данные! Таблица никогда не удаляется).
Итак, если пользователь закрывает экран запроса:
delete
from AlgorithmTempTable
where QueryID = '12345678-9012-3456789'
Хотя в некоторых случаях это не идеально. В случае сбоя приложения данные остаются в таблице навсегда.
Есть несколько лучших способов. Какой из них лучше для вас, зависит от вашего приложения. Некоторые возможности:
- Вы можете добавить столбец datetime с текущим временем в качестве значения по умолчанию, а затем запустить ночное (или еженедельное) задание, удаляющее все, что старше X
- То же, что и выше, но вместо еженедельной работы вы можете удалять все старше X каждый раз, когда кто-то начинает новый запрос
- Если у вас есть сеанс для каждого пользователя, вы можете сохранить SessionID в дополнительном столбце таблицы. Когда пользователь выходит из системы или истекает сеанс, вы можете удалить все с этим SessionID в таблице