2013-12-03 3 views
1

У меня есть таблица со структурой типа:офсет/предел оптимизации производительности

  • Id (серийный INT) (индекс на это)
  • Сообщение (текст)
  • ...
  • CreationDate (DateTime) (Указатель на этот счет)

Мне нужно реализовать разбивку на страницы. Мой простой запрос выглядит следующим образом:

SELECT Id, Post, etc FROM Posts ORDER BY CreationDate desc OFFSET x LIMIT 15 

При наличии нескольких записей (ниже 1 млн) производительность несколько терпимо, но когда таблица растет есть заметная разница.

Пропуск того факта, что есть хорошие настройки параметров БД, такие как размер кеша, рабочая память, стоимость, общий доступ и т. Д. Что можно сделать для повышения производительности и наилучшей практики разбивки на страницы с использованием Postgres. Есть что-то похожее на вопрос here, но я не уверен, что это может быть применено и в моем случае.

С моей Id будет автоматически увеличивается (так предсказуемы) один из других вариантов, я думаю, чтобы иметь что-то вроде этого

SELECT Id, Post...FROM Posts WHERE Id > x and Id < y 

Но это, кажется, усложнять, я должен получить количество записей все время и, кроме того, не гарантируется, что я всегда получу 15 записей (например, если один из сообщений был удален, а идентификаторы больше не находятся в «прямой» последовательности).

Я тоже думал о КУРСОРЕ, но если я не ошибаюсь, CURSOR будет держать соединение открытым, что неприемлемо в моем случае.

ответ

2

Пагинация жесткая; модель РСУБД не очень хорошо подходит для большого количества недолговечных запросов с прокруткой с учетом состояния. Как вы отметили, использование ресурсов имеет тенденцию быть слишком высоким.

У вас есть варианты:

  • LIMIT и OFFSET
  • Использование курсора
  • Копирование результатов во временную таблицу, либо в Memcached или аналогичный, то читать его оттуда
  • x > id и LIMIT

Из ese, я предпочитаю x > id с LIMIT. Просто запомните последний идентификатор, который вы видели, и попросите следующего. Если у вас монотонно возрастающая последовательность, это будет просто, надежно, а для простых запросов это будет эффективно.

+0

Спасибо за ответ. Я согласен, что x> id будет наиболее эффективным вариантом, предполагающим, что большинство людей будут проверять самые последние данные в любом случае. Но если я не ошибаюсь, есть проблема с этим, так как в таблице могут быть постоянные вставки, и идентификатор увеличивается. Это будет означать, что все время я должен получить максимальный id и все еще не могу полагаться на него, как если бы некоторые сообщения были удалены. Идентификаторы не будут последовательными (я имею в виду, что шаг между идентификаторами не всегда будет 1) ... – NDeveloper

+0

@ NDeveloper Вы разбиваетесь на страницы, не так ли? Вам просто нужно запомнить идентификатор, который вы видели в сеансе. Итак, скажем, вы сначала запускаете 'SELECT ... FROM ...WHERE id> 0 ORDER BY id LIMIT 20'. Вы можете получить набор результатов с идентификаторами 1, 3, 4, 5, ... 28. Таким образом, ваш следующий запрос для следующей страницы: «SELECT ... FROM ... WHERE id> 28 ORDER BY id LIMIT 1 '. Если вы ожидаете, что в основном сделаете * обратную * разбивку на страницы, вы сделаете свой первый запрос как '... ORDER BY id DESC LIMIT 20', а ваш следующий как' WHERE id> 99123 ORDER BY id DESC LIMIT 20' (где 99123 - это самый низкий идентификатор, который вы видели в последнем запросе). –

+0

Да, вы правы, это имеет смысл. Единственная проблема с этим подходом заключается в том, что если идентификаторы не являются последовательными, одна и та же запись может появляться несколько раз. – NDeveloper

Смежные вопросы