Ho appena guardato il explain plan
per le query simili ai tuoi e il piano è esattamente lo stesso per entrambe le query, in modo Non sono sicuro di quali siano le prestazioni che il tuo DBA suggerisce.
Il wrapping della query con select * from (...) where rownum = 1
introduce uno STOPKEY che interrompe la query interna dopo una riga. Oracle sa che in realtà non vuoi ottenere tutti i risultati dalla subquery e quindi prendere solo la prima riga.
Cambiare la query prodotta da Hibernate sarà impossibile senza modificare il codice sorgente di ibernazione stesso.
nota, il motivo per cui questo nidificazione è necessario diventa evidente quando si tenta di introdurre una ORDER BY
clausola:
select ID, FIRSTNAME, LASTNAME
from PERSONS
where lower(FIRSTNAME) = 'john'
and rownum <= 1
order by LASTNAME
produce risultati diversi a
select * from (
select ID, FIRSTNAME, LASTNAME
from PERSONS
where lower(FIRSTNAME) = 'john'
order by LASTNAME)
where rownum <= 1
come where rownum
viene applicato prima della order by clause
....
MODIFICA:
Per riferimento ecco l'output del piano spiegare, e che è esattamente lo stesso per entrambe le query:
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 112 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
|* 2 | TABLE ACCESS FULL| TABLE_NAME | 1 | 112 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Le prestazioni possono essere migliorate mettendo un indice funzionale sulla lower(FIRST_NAME)
ma che potrebbe essere utilizzato da entrambe le query esattamente stesso.
prima di tutto vorrei creare un indice sul campo FIRSTNAME. –
@StefanBe: e tale indice verrebbe ignorato poiché la clausola where utilizza una funzione. Avresti bisogno di un indice funzionale ... – beny23
ah ok. non so che –