PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PostgreSQL:Dlaczego to zapytanie nie używa mojego indeksu?

Jak już zauważyłeś, problem jest związany z używaniem operatorów innych niż równe. Indeks może być używany najefektywniej tylko w przypadku skrajnych lewej kolumny, które są porównywane z wartościami równymi (plus jeden warunek zakresu).

W twoim przykładzie:

create index i on t (a,b,c,d);
where a=1 and b=11 and c!=5 and d<8;

Może używać indeksu tylko dla a i b wydajnie. Oznacza to, że baza danych pobiera wszystkie wiersze pasujące do a i b warunku, a następnie sprawdza każdy wiersz pod kątem pozostałych warunków.

Kiedy zmienisz filtr na c równa się, pobiera (potencjalnie) mniej wierszy (tylko te pasujące do a i b i c ), a następnie porównuje te (mniej) wiersze z d filtr. W tym przypadku użycie indeksu jest bardziej efektywne.

Ogólnie rzecz biorąc, planer zapytań PostgreSQL ocenia obie opcje:(1) używając indeksu; (2) wykonanie SeqScan. W obu przypadkach oblicza wartość kosztów — im wyższy, tym gorsza jest oczekiwana wydajność. W konsekwencji bierze ten o mniejszej wartości kosztowej. W ten sposób decyduje się użyć indeksu, czy nie, nie ma ustalonego progu.

Na koniec napisano "plus jeden warunek zakresu" powyżej. Oznacza to, że może nie tylko używać indeksu w najbardziej efektywny sposób, jeśli używasz znaków równości, ale także dla pojedynczego warunku zakresu.

Biorąc pod uwagę, że w zapytaniu występuje jeden warunek dotyczący zakresu, sugeruję zmianę indeksu w następujący sposób:

create index i on t (a,b,d,c);

Teraz może używać filtrów na a i b i d wydajnie z indeksem i wystarczy odfiltrować wiersze, gdzie c!=5 . Chociaż ten indeks może być użyty w zapytaniu bardziej efektywnie niż oryginalny, nie oznacza to automatycznie, że PG go użyje. To zależy od kosztorysów. Ale spróbuj.

Wreszcie, jeśli to nie wystarczy, i wartość 5 używasz w wyrażeniu c!=5 jest stała, możesz rozważyć indeks częściowy:

 create index i on t (a,b,d)
        where c!=5;

Możesz to zrobić również ze wszystkimi innymi kolumnami, jeśli wartości, z którymi je porównujesz, są stałymi.

Referencje:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać w zmiennej wartość wyboru z menu Wybierz/rozwiń PHP lub HTML

  2. Postgresql nie powiedzie się JEDEN raz po ponownym uruchomieniu systemu Windows

  3. Jak INTERSECT działa w PostgreSQL

  4. Mam inne wyniki niż zapytanie o COUNT('e.id') lub COUNT(e.id)

  5. Jak policzyć wszystkie połączone węzły (wiersze) na wykresie w Postgresie?