Mam tabelę z 250 000 wierszy w mojej testowej bazie danych. (W produkcji jest kilkaset milionów, możemy zaobserwować ten sam problem.) Tabela ma identyfikator ciągu nvarchar2 (50), a nie null, z unikalnym indeksem (to nie jest PK).
Identyfikatory składają się z pierwszej części, która ma 8 różnych wartości w mojej testowej bazie danych (i około tysiąca w produkcji), następnie znaku @, a na końcu liczby o długości od 1 do 6 cyfr. Na przykład może być 50 tysięcy wierszy zaczynających się od „ABCD_BGX1741F_2006_13_20110808.xml @”, po których następuje 50 tysięcy różnych liczb.
Kiedy pytam o pojedynczy wiersz na podstawie jego identyfikatora, liczność jest szacowana na 1, koszt jest bardzo niski, działa dobrze. Gdy pytam o więcej niż jeden wiersz z kilkoma identyfikatorami w wyrażeniu IN lub wyrażeniu OR, oszacowania dla indeksu są całkowicie niepoprawne, więc używany jest pełny skan tabeli. Jeśli wymuszę indeks za pomocą podpowiedzi, jest to bardzo szybkie, skanowanie pełnego stołu jest faktycznie wykonywane o rząd wielkości wolniej (i znacznie wolniej w produkcji). Jest to więc problem z optymalizatorem.
W ramach testu zduplikowałem tabelę (w tym samym schemacie + przestrzeni tabel) z dokładnie tym samym DDL i dokładnie taką samą zawartością. Dla lepszej miary odtworzyłem unikalny indeks na pierwszej tabeli i utworzyłem dokładnie ten sam indeks na tabeli klonowania. Zrobiłem DBMS_STATS.GATHER_SCHEMA_STATS('schemaname',estimate_percent=>100,cascade=>true);
. Możesz nawet zobaczyć, że nazwy indeksów są następujące po sobie. Tak więc teraz jedyną różnicą między dwiema tabelami jest to, że pierwsza została załadowana w losowej kolejności przez długi czas, z blokami rozrzuconymi na dysku (w przestrzeni tabel wraz z kilkoma innymi dużymi tabelami), druga została załadowana jako jedna partia WYBIERZ WSTAW. Poza tym nie wyobrażam sobie żadnej różnicy. (Oryginalna tabela została zmniejszona od ostatniego dużego usunięcia, a potem nie było ani jednego usunięcia).
Oto plany zapytań dla chorych i tabeli klonów (ciągi pod czarnym pędzlem są takie same na całym obrazie, a także pod szarym pędzlem.):
(W tym przykładzie jest 1867 wierszy, które zaczynają się od czarnego, szczotkowanego identyfikatora. Zapytanie 2-wierszowe daje liczność 1867 * 2, zapytanie 3-wierszowe daje liczność 1867 * 3 itd. Nie można przypadek, Oracle wydaje się nie przejmować końcem identyfikatorów).
Co może powodować takie zachowanie? Oczywiście odtworzenie stołu w produkcji byłoby dość drogie.
USER_TABLES: http://i.stack.imgur.com/nDWze.jpg USER_INDEXES: http://i.stack.imgur.com/DG9um.jpg Zmieniłem tylko nazwę schematu i obszaru tabel. Widać, że nazwy tabel i indeksów są takie same jak na zrzucie ekranu planu zapytań.