La tabella ha la chiave primaria surrogata generata dalla sequenza. Sfortunatamente, questa sequenza è usata per generare le chiavi per alcune altre tabelle (non l'ho progettata e non posso cambiarla).Selezionare `n` ultimi record inseriti nella tabella - oracle
Qual è il modo più veloce per selezionare gli ultimi record inseriti in Oracle n
in ordine decrescente (ultimo inserito in alto)?
n
è un numero relativamente piccolo - il numero di record da visualizzare nella pagina - probabilmente non più grande di 50.
tavolo ha ora 30.000.000 record con 10-15 migliaia di nuovi record al giorno.
Il database è Oracle 10g.
Edit:
In risposta a un commento: La domanda è stata motivata con il piano di esecuzione per la query:
select * from MyTable order by primarykeyfield desc
Piano di esecuzione era:
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | SORT ORDER BY | |
| 2 | TABLE ACCESS FULL| MyTable |
---------------------------------------------
Mi ha sorpreso che Oracle vuole per eseguire la scansione completa della tabella e l'ordinamento quando ha indice sul campo di ordinamento.
La query di risposta accettata utilizza l'indice ed evita l'ordinamento.
Modifica 2:
Re. Il commento di APC: l'ordinamento è stato una parte che mi ha sorpreso. Mi aspettavo che Oracle usasse l'indice per recuperare le righe nell'ordine previsto. piano di esecuzione per la query:
select * from (select * from arh_promjene order by promjena_id desc) x
where rownum < 50000000
utilizza l'indice invece di accesso completo tavolo e ordinare (condizione di preavviso rownum < 50.000.000
- questo è il modo più di numero di record nella tabella e Oracle sa che deve recuperare tutti i record dalla tabella). Questa query restituisce tutte le righe come la prima interrogazione, ma con le seguenti piano di esecuzione:
| 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)
era insolito per me che Oracle sta creando diversi piani di esecuzione di queste due query che restituiscono essenzialmente lo stesso set di risultati.
Edit 3: il commento di Re Amoq:
Oracle non sa che 50M è maggiore del numero di righe. Certo, ha statistiche, ma potrebbero essere vecchie e sbagliate - e Oracle non avrebbe mai consentire a se stesso di fornire un risultato errato solo perché le statistiche sono sbagliato.
Sei sicuro? Nelle versioni Oracle fino a 9 si consigliava di aggiornare manualmente le statistiche di volta in volta. Dalla versione 10 Oracle aggiorna automaticamente le statistiche. A che cosa servono i dati statistici se Oracle non li usa per l'ottimizzazione delle query?
Perché è spiacevole che la sequenza venga utilizzata anche per altre tabelle? Non importa per la query recuperare gli ultimi n record inseriti perché una sequenza non è mai garantita essere priva di barriere da parte di Oracle. Quindi non è possibile fare un semplice id tra max-n e max in ogni caso. – tuinstoel
La tua query seleziona * tutte * le colonne per * tutte * le righe. Perché sei sorpreso che Oracle esegua una scansione completa? In quale altro modo otterrebbe i dati per soddisfare questa query? – APC
Oracle non * sa * che 50M è maggiore del numero di righe. Certo, ha delle statistiche, ma potrebbero essere vecchie e sbagliate - e Oracle * non * si permetterebbe mai di fornire un risultato errato solo perché le statistiche sono sbagliate. –