Таблица имеет суррогатный первичный ключ, сгенерированный из последовательности. К сожалению, эта последовательность используется для генерации ключей для некоторых других таблиц (я не разработал ее и не могу ее изменить).
Какой самый быстрый способ выбрать последние n
вставленные записи в Oracle, упорядоченные по id в порядке убывания (последний вставленный сверху)?
n
- это относительно небольшое число - количество записей, отображаемых на странице, - вероятно, не больше 50.
В таблице теперь 30 000 000 записей с 10-15 тысячами новых записей ежедневно.
База данных Oracle 10g.
Изменить:
В ответ на один комментарий: Этот вопрос был мотивирован планом выполнения запроса:
select * from MyTable order by primarykeyfield desc
План выполнения был:
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | TABLE ACCESS FULL| MyTable |
---------------------------------------------
Я был удивлен, что Oracle хочет выполнить полное сканирование таблицы и сортировку, когда у нее есть индекс для поля сортировки.
Запрос из принятого ответа использует индекс и избегает сортировки.
Редактировать 2:
Число рейнольдса Комментарий APC: сортировка была частью, которая удивила меня. Я ожидал, что Oracle будет использовать индекс для извлечения строк в ожидаемом порядке. План выполнения запроса:
select * from (select * from arh_promjene order by promjena_id desc) x
where rownum < 50000000
использует индекс вместо полного доступа к таблице и сортировки (условие уведомления rownum < 50.000.000
- это намного больше, чем количество записей в таблице, и Oracle знает, что она должна извлечь все записи из таблицы). Этот запрос возвращает все строки как первый запрос, но со следующим планом выполнения:
| Id | Operation | Name |
-------------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | COUNT STOPKEY | |
| 2 | VIEW | |
| 3 | TABLE ACCESS BY INDEX ROWID| MyTable |
| 4 | INDEX FULL SCAN DESCENDING| SYS_C008809 |
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<50000000)
Для меня было необычным, что Oracle создает разные планы выполнения для этих двух запросов, которые по существу возвращают один и тот же набор результатов.
Редактировать 3:
Re Amoq's комментарий:
Oracle не знает, что 50M
больше, чем количество строк. Конечно,
у него есть статистика, но они могут быть
старый и неправильный - и Oracle никогда бы не
позволить себе поставить неверный
результат только потому, что статистика
неправильно.
Вы уверены? В версиях Oracle до 9 рекомендуется время от времени обновлять статистику вручную. Начиная с версии 10 Oracle автоматически обновляет статистику. Какая польза от статистических данных, если Oracle не использует их для оптимизации запросов?