SQL-нумерация данных на лету - PullRequest
       0

SQL-нумерация данных на лету

2 голосов
/ 22 февраля 2012

Я новичок в нумерации страниц, поэтому не уверен, что полностью понимаю, как это работает.Но вот что я хочу сделать.

По сути, я создаю своего рода поисковую систему, которая генерирует результаты из базы данных ( MySQL ).Эти результаты объединяются алгоритмически, а затем возвращаются пользователю.

У меня такой вопрос: когда результаты объединяются в бэкэнд, нужно ли мне создавать временное представление с результатами, которые затем используются для разбивки на страницы PHP?Или мне создать таблицу?Я не хочу, чтобы куча представлений и / или таблиц плавали вокруг для каждого запроса.Кроме того, если я использую временные таблицы, когда они уничтожаются?Что если пользователь нажмет кнопку «Назад» в своем браузере?

Надеюсь, это имеет смысл.Пожалуйста, попросите разъяснений, если вы не понимаете.Я предоставил немного больше информации ниже.

ДОПОЛНИТЕЛЬНОЕ ОБЪЯСНЕНИЕ: База данных содержит английские слова и фразы, каждое из которых сопоставлено с понятием (Пример: «яблоко» 0,67 семантически связано с понятием «приготовление пищи»).Пользователь может ввести несколько ключевых слов и найти наиболее подходящую концепцию для каждого из этих ключевых слов.Поэтому я математически комбинирую необработанные реляционные оценки, чтобы найти ранжированный список наиболее семантически связанных понятий для набора слов, который вводит пользователь.Так что это не так просто, как создать SQL-запрос типа «SELECT * FROM words WHERE blah blah ...»

Ответы [ 2 ]

2 голосов
/ 22 февраля 2012

Это зависит от вашего механизма базы данных (то есть, какого рода 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 в таблице
0 голосов
/ 22 февраля 2012

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

Лучше всего это сделать с помощью хранимой процедуры.

  1. Сохранить результаты запроса во временной таблице.
  2. Выберите количество данных на странице X из временной таблицы.
  3. Также возвращает назад текущую страницу и общее количество страниц.
...