Ok - jeg vil give det en chance, dette er for det meste fradrag fra den tilgængelige information:
Hvorfor vælger Oracle en anden eksekveringsplan?
Det ser ud til i din anden forespørgsel med det usædvanlige datoformat, at optimeringsværktøjet ikke har nogen idé om, hvad værdien af den resulterende dato er. Du ser filterprædikatet:
1 - filter(TO_DATE('20140610 ','ååååmmdd ')<=TO_DATE(' 2014-06-10 23:59:59', 'åååå-mm-dd tt24:mi:ss'))
Hvilket betyder, at optimizeren ikke engang er sikker på, at den første date er mindre end den anden! Det betyder, at optimeringsværktøjet ikke har nogen idé om antallet af returnerede rækker og blot vil bruge en generisk plan uden at tage specifikke statistikker i betragtning. Det ville være det samme, hvis du havde en brugerdefineret funktion xyt(), som ville returnere en dato for området. Optimeringsværktøjet har ingen måde at vide, hvilken dato-værdi vil resultere - Dette betyder, at du får en generel plan til alle formål, som burde være ret anstændig for ethvert angivet datointerval.
I det første og tredje tilfælde ser optimeringsværktøjet ud til at forstå datoen direkte og kan gætte antallet af rækker, der er i datointervallet, ved at bruge statistik. Så mens den anden forespørgsel var til Optimizer som MELLEM X OG 3
denne forespørgsel er som MELLEM 1 OG 3
Så han optimerer forespørgselsplanen for det forudsagte antal returnerede rækker!
Det mærkelige synes at være, at forespørgselsoptimeringsværktøjet har sådanne problemer med et mærkeligt datoformat, kunne indgives som en fejl/anmodning om forbedring...
Men en vigtig pointe:
- En fuld tabelscanning behøver ikke at være en DÅRLIG plan... Ud over at bruge et indeks er det ikke altid hurtigere!
- Omkostningerne i forespørgselsplanen er på ingen måde direkte relateret til den faktiske udførelsestid eller ydeevne - det er en intern måling at sammenligne forskellige planer for den SAMME FORESPØRGSEL (så du kan ikke sammenligne omkostningerne ved forskellige forespørgsler som dine forespørgsler 1 ,2 og 3)
Grundlæggende, hvis du returnerer et højt antal rækker fra en tabel, vil en fuld tabelscanning uden indeksadgang i mange tilfælde være meget hurtigere, især når du arbejder på visse partitioner! - Tabelscanningen vil kun få adgang til rettigheden for det matchende datointerval - altså kun for den pågældende dato og returnerer alle rækker fra denne partition. Dette er meget hurtigere end at forespørge indekset for hver enkelt række og derefter udtrække rækken ved indeksadgang... Prøv at profilere forespørgslerne - den fulde tabelscanning på partitionen skal være 3 gange så hurtig med meget mindre IO