Таблица содержит первичный первичный ключ к суррогатной генерации из последовательности. К сожалению, эта последовательность используется для генерации ключей для некоторых других таблиц (я не проектировал ее, и я не могу ее изменить).Выберите `n` последние вставленные записи в таблицу - оракул
Что является самым быстрым способом выбора последнего n
вставленных записей в Oracle, упорядоченных по id в порядке убывания (последний вставлен сверху)?
n
некоторое относительно небольшое число - количество записей, отображаемых на странице - вероятно, не больше, чем 50.
Таблица теперь имеет 30.000.000 записей с 10-15 тысячами новых записей ежедневно.
База данных - это Oracle 10g.
Edit:
В ответ на один комментарий: Этот вопрос был мотивирован план выполнения для запроса:
select * from MyTable order by primarykeyfield desc
план выполнения был:
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | TABLE ACCESS FULL| MyTable |
---------------------------------------------
Я был удивлен, что Oracle хочет выполнить полное сканирование таблицы и сортировку, когда она имеет индекс в поле сортировки.
Запрос от принятого ответа использует индекс и позволяет сортировать сортировку.
Редакция 2:
Re. Комментарий 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 в:
Oracle не знает, что 50М больше, чем число строк. Конечно, у него есть статистика, но они могут быть старыми и неправильными - и Oracle никогда бы не позволил себе поставить неверный результат только потому, что статистика неверна.
Уверены ли вы? В версиях Oracle до 9 рекомендуется время от времени обновлять статистику вручную. Начиная с версии 10 Oracle автоматически обновляет статистику. Что такое использование статистических данных, если Oracle не использует его для оптимизации запросов?
Почему прискорбно, что последовательность также используется для других таблиц? Не имеет значения, чтобы запрос извлекал последние n вставленных записей, потому что Oracle никогда не может быть безразличной. Таким образом, вы не можете сделать простой, где id между max-n и max в любом случае. – tuinstoel
Ваш запрос выбирает * все * столбцы для * всех * строк. Почему вы удивлены тем, что Oracle делает полное сканирование таблицы? Как еще он получит данные для удовлетворения этого запроса? – APC
Oracle не знает *, что 50M больше числа строк. Конечно, у него есть статистика, но они могут быть старыми и неправильными - и Oracle никогда не позволит себе поставить неверный результат только потому, что статистика неверна. –