Jedynym sposobem, jaki mogę sobie wyobrazić, aby uzyskać taką różnicę w szybkości wykonywania, byłoby (a) posiadanie indeksu w field4
i (b) mieć dużo pustych bloków danych; prawdopodobnie od wysokiego poziomu wody ustawionego bardzo wysoko przez powtarzające się obciążenia o bezpośredniej ścieżce.
Pierwsze zapytanie nadal będzie używać indeksu i działać zgodnie z oczekiwaniami. Ale ponieważ wartości null nie są indeksowane, indeks nie może być użyty do sprawdzenia, czy or field4 is null
stan, więc powróci do pełnego skanowania tabeli.
To samo w sobie nie powinno stanowić problemu, ponieważ skanowanie pełnej tabeli zawierającej 7000 wierszy nie powinno zająć dużo czasu. Ale ponieważ jest trwa tak długo, dzieje się coś innego. Pełne skanowanie tabeli musi zbadać każdy blok danych przydzielony do tabeli, aby sprawdzić, czy zawierają jakieś wiersze, a czas, jaki zajmuje, sugeruje, że jest o wiele więcej bloków niż potrzeba do przechowywania 7000 wierszy, nawet w przypadku wbudowanej pamięci CLOB.
Najprostszym sposobem uzyskania wielu pustych bloków danych jest posiadanie dużej ilości danych, a następnie usunięcie większości z nich. Ale wierzę, że powiedziałeś w usuniętym komentarzu do wcześniejszego pytania, że wydajność była w porządku i pogorszyła się. Może się tak zdarzyć, jeśli wykonasz wstawianie ścieżki bezpośredniej , szczególnie jeśli „odświeżasz” dane, usuwając je, a następnie wstawiając nowe dane w trybie ścieżki bezpośredniej. Możesz to zrobić za pomocą wstawek, które mają /*+ append */
wskazówka; lub równolegle; lub przez SQL*Loader. Za każdym razem, gdy to robiłeś, przesuwał się znak wysokiej wody, ponieważ stare puste bloki nie byłyby ponownie używane; a za każdym razem wydajność zapytania, które sprawdza, czy nie ma wartości null, nieco się pogorszy. Po wielu iteracjach, które naprawdę zaczną się sumować.
Możesz sprawdzićw słowniku danych, ile miejsca jest przydzielone do Twojej tabeli (user_segments
itp.) i porównaj to z rozmiarem danych, które Twoim zdaniem faktycznie posiadasz. Możesz zresetować HWM, przebudowując tabelę, np. wykonując:
alter table mytable move;
(najlepiej w oknie konserwacji!)
W ramach demonstracji wykonałem cykl do wstawiania i usuwania 7000 wierszy z bezpośrednią ścieżką ponad sto razy, a następnie uruchomiłem oba zapytania. Pierwsza zajęła 0,06 sekundy (z czego duża część to obciążenie SQL Devleoper); drugi wziął 1,260. (Ja też prowadziłem Gordona, który uzyskał podobny czas, ponieważ wciąż musi robić FTS). Przy większej liczbie iteracji różnica stałaby się jeszcze bardziej wyraźna, ale zabrakło mi miejsca... Następnie wykonałem alter table move
i ponownie uruchom drugie zapytanie, które następnie zajęło 0,05 sekundy.