Пейджинг с Oracle - PullRequest
       19

Пейджинг с Oracle

83 голосов
/ 28 октября 2008

Я не настолько знаком с Oracle, как хотелось бы. У меня есть около 250 тыс. Записей, и я хочу отобразить их по 100 на страницу. В настоящее время у меня есть одна хранимая процедура, которая извлекает все четверти миллиона записей в набор данных, используя адаптер данных, набор данных и метод dataadapter.Fill (набор данных) для результатов из сохраненного процесса. Если у меня есть «Номер страницы» и «Количество записей на странице» в качестве целочисленных значений, я могу передать их в качестве параметров, что будет лучшим способом вернуть только этот конкретный раздел. Скажем, если я передам 10 в качестве номера страницы и 120 в качестве числа страниц, из оператора select это даст мне 1880–1200-е или что-то в этом роде, моя математика в голове может быть отключена.

Я делаю это в .NET с C #, думал, что это не важно, если я могу сделать это прямо на стороне SQL, то я должен быть крут.

Обновление: я смог воспользоваться предложением Брайана, и он отлично работает. Я хотел бы поработать над оптимизацией, но страницы появляются за 4-5 секунд, а не за минуту, и мой элемент управления подкачкой смог очень хорошо интегрироваться с моими новыми сохраненными процессами.

Ответы [ 5 ]

127 голосов
/ 28 октября 2008

Как-то так должно работать: Из блога Франса Боума

SELECT * FROM
(
    SELECT a.*, rownum r__
    FROM
    (
        SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
        ORDER BY OrderDate DESC, ShippingDate DESC
    ) a
    WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
123 голосов
/ 28 октября 2008

Спросите Тома о нумерации страниц и очень, очень полезных аналитических функциях.

Это выдержка из этой страницы:

select * from (
    select /*+ first_rows(25) */
     object_id,object_name,
     row_number() over
    (order by object_id) rn
        from all_objects)
    where rn between :n and :m
        order by rn;
55 голосов
/ 28 апреля 2015

В интересах полноты, для людей, которые ищут более современное решение, в Oracle 12c есть несколько новых функций, в том числе улучшенная подкачка страниц и лучшая обработка.

Paging

Пейджинг выглядит так:

SELECT *
FROM user
ORDER BY first_name
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;

Top N Records

Получение лучших записей выглядит так:

SELECT *
FROM user
ORDER BY first_name
FETCH FIRST 5 ROWS ONLY

Обратите внимание, что в обоих приведенных выше примерах запросов есть предложения ORDER BY. Новые команды уважают их и запускаются на отсортированных данных.

Мне не удалось найти хорошую справочную страницу Oracle для FETCH или OFFSET, но на этой странице представлен отличный обзор этих новых функций.

Производительность

Как отмечает @wweicker в комментариях ниже, производительность - это проблема с новым синтаксисом в 12c. У меня не было копии 18с, чтобы проверить, улучшил ли ее Oracle.

Интересно, что мои фактические результаты были возвращены немного быстрее при первом запуске запросов в моей таблице (113 миллионов + строк) для нового метода:

  • Новый метод: 0,013 секунды.
  • Старый метод: 0,107 секунд.

Однако, как упоминал @wweicker, план объяснения выглядит гораздо хуже для нового метода:

  • Стоимость нового метода: 300 110
  • Стоимость старого метода: 30

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

Давайте посмотрим при включении одного неиндексированного столбца в предыдущий набор данных:

  • Новый метод время / стоимость: 189,55 секунд / 998 908
  • Старый метод время / стоимость: 1,973 секунды / 256

Резюме: используйте с осторожностью, пока Oracle не улучшит эту обработку. Если у вас есть индекс для работы, возможно, вы можете обойтись без использования нового метода.

Надеюсь, у меня скоро будет копия 18c, с которой можно поиграть, и я смогу обновить

10 голосов
/ 03 ноября 2015

Просто хочу обобщить ответы и комментарии. Есть несколько способов сделать нумерацию страниц.

До появления oracle 12c функциональности OFFSET / FETCH не было, поэтому взгляните на whitepaper , как и предлагал @jasonk. Это самая полная статья, которую я нашел о различных методах с подробным объяснением преимуществ и недостатков. Копирование и вставка их здесь заняло бы значительное время, поэтому я не буду этого делать.

Существует также хорошая статья от создателей jooq, объясняющая некоторые распространенные предостережения с использованием оракула и других баз данных. пост в блоге jooq

Хорошие новости, начиная с oracle 12c, у нас появилась новая функция OFFSET / FETCH. Новые возможности OracleMagazine 12c . Пожалуйста, обратитесь к "Top-N Запросы и нумерация страниц"

Вы можете проверить свою версию Oracle, выполнив следующее заявление

SELECT * FROM V$VERSION
7 голосов
/ 16 декабря 2013

Попробуйте следующее:

SELECT *
FROM
  (SELECT FIELDA,
    FIELDB,
    FIELDC,
    ROW_NUMBER() OVER (ORDER BY FIELDC) R
  FROM TABLE_NAME
  WHERE FIELDA = 10
  )
WHERE R >= 10
AND R   <= 15;

через [tecnicume]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...