Ok - spróbuję, jest to głównie odliczenie od dostępnych informacji:
Dlaczego Oracle wybiera inny plan wykonania?
Wydaje się, że w drugim zapytaniu z nietypowym formatem daty optymalizator nie ma pojęcia, jaka jest wartość otrzymanej daty. Widzisz predykat filtra:
1 - filter(TO_DATE('20140610','rrrrmmdd')<=TO_DATE('2014-06-10 23:59:59', 'rrrr-mm-dd hh24:mi:ss'))
Co oznacza, że optymalizator nie jest nawet pewien, czy pierwsza data jest mniejsza od drugiej! Oznacza to, że optymalizator nie ma pojęcia o liczbie zwróconych wierszy i po prostu użyje ogólnego planu bez uwzględniania konkretnych statystyk. Byłoby tak samo, gdybyś miał zdefiniowaną przez użytkownika funkcję xyt(), która zwracałaby datę dla zakresu. Optymalizator nie ma możliwości sprawdzenia, jaka będzie wartość daty — oznacza to, że otrzymujesz ogólny plan, który powinien być całkiem przyzwoity dla dowolnego określonego zakresu dat.
W pierwszym i trzecim przypadku wydaje się, że optymalizator bezpośrednio rozumie datę i może odgadnąć liczbę wierszy z zakresu dat za pomocą statystyk. Tak więc, podczas gdy drugie zapytanie było skierowane do Optymalizatora, takie jak BETWEEN X AND 3
to zapytanie jest jak BETWEEN 1 AND 3
Optymalizuje więc plan zapytania pod kątem przewidywanej liczby zwróconych wierszy!
Dziwne wydaje się, że optymalizator zapytań ma takie problemy z dziwnym formatem daty, może być zgłoszony jako błąd/prośba o poprawę...
Ale ważny punkt:
- Pełne skanowanie tabeli nie musi być ZŁYM planem... Podobnie jak używanie indeksu nie zawsze jest szybsze!
- Koszt w planie zapytania nie jest w żaden sposób bezpośrednio związany z rzeczywistym czasem wykonania lub wydajnością — jest to wewnętrzna miara porównywania różnych planów dla TEGO SAMEGO ZAPYTANIA (więc nie można porównywać kosztów różnych zapytań, takich jak zapytania 1 ,2 i 3)
Zasadniczo, jeśli zwrócisz dużą liczbę wierszy z tabeli, pełne skanowanie tabeli bez dostępu do indeksu będzie w wielu przypadkach znacznie szybsze, szczególnie podczas pracy na niektórych partycjach! - Skanowanie tabeli uzyska dostęp tylko do pertition dla pasującego zakresu dat - a więc tylko dla danej daty i zwróci wszystkie wiersze z tej partycji. Jest to znacznie szybsze niż zapytanie o indeks dla każdego pojedynczego wiersza, a następnie wyodrębnienie wiersza przez dostęp do indeksu... Spróbuj profilować zapytania - pełne skanowanie tabeli na partycji powinno być 3 razy szybsze przy znacznie mniejszej liczbie operacji we/wy