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

Indeksowanie kluczy obcych w Postgresql

tl;dr Musisz dodać indeks do item_id . „Czarną magię” indeksowania Postgres opisano w 11. Indeksy .

Masz indeks złożony na (topic_id, item_id) i kolejność kolumn jest ważna. Postgres może użyć tego do indeksowania zapytań na topic_id , zapytania dotyczące obu topic_id i item_id , ale nie (lub mniej wydajnie) item_id sam.

Od 11.3. Indeksy wielokolumnowe ...

-- indexed
select *
from topics_items
where topic_id = ?

-- also indexed
select *
from topics_items
where topic_id = ?
  and item_id = ?

-- probably not indexed
select *
from topics_items
where item_id = ?

Dzieje się tak, ponieważ indeks złożony, taki jak (topic_id, item_id) przechowuje najpierw identyfikator tematu, a następnie identyfikatory produktów, które również mają ten identyfikator tematu. Aby skutecznie wyszukać identyfikator elementu w tym indeksie, Postgres musi najpierw zawęzić wyszukiwanie do identyfikatora tematu.

Postgres może odwrócić indeks, jeśli uważa, że ​​jest to warte wysiłku. Jeśli istnieje niewielka liczba możliwych identyfikatorów tematów i duża liczba możliwych identyfikatorów indeksu, wyszuka identyfikator indeksu w każdym identyfikatorze tematu.

Załóżmy na przykład, że masz 10 możliwych identyfikatorów tematów i 1000 możliwych identyfikatorów produktów oraz indeks (topic_id, index_id) . To tak, jakby mieć 10 wyraźnie oznaczonych pojemników na identyfikatory tematów, każdy z 1000 wyraźnie oznaczonych pojemników na identyfikatory produktów w środku. Aby uzyskać dostęp do zasobników identyfikatorów produktów, należy zajrzeć do każdego zasobnika identyfikatorów tematu. Aby użyć tego indeksu na where item_id = 23 Postgres musi przeszukać każdy z 10 zasobników z identyfikatorami tematów pod kątem wszystkich zasobników o identyfikatorze 23.

Ale jeśli masz 1000 możliwych identyfikatorów tematów i 10 możliwych identyfikatorów produktów, Postgres musiałby przeszukać 1000 grup identyfikatorów tematów. Najprawdopodobniej zamiast tego wykona pełne skanowanie tabeli. W takim przypadku chciałbyś odwrócić swój indeks i uczynić go (item_id, topic_id) .

Zależy to w dużej mierze od dobrych statystyk stołowych, co oznacza upewnienie się, że autovacuum działa prawidłowo.

Możesz więc uciec z jednym indeksem dla dwóch kolumn, jeśli jedna kolumna ma znacznie mniejszą zmienność niż inna.

Postgres może również używać wielu indeksów, jeśli uważa, że ​​spowoduje to uruchomienie zapytania szybciej . Na przykład, jeśli masz indeks na topic_id i indeks na item_id , może użyj obu indeksów i połącz wyniki. Na przykład where topic_id = 23 or item_id = 42 może użyć indeksu topic_id, aby wyszukać temat o identyfikatorze 23, a indeksu item_id, aby wyszukać element o identyfikatorze 42, a następnie połączyć wyniki.

Jest to generalnie wolniejsze niż posiadanie złożonego (topic_id, item_id) indeks. Może to być również wolniejsze niż użycie jednego indeksu, więc nie zdziw się, jeśli Postgres zdecyduje się nie używać wielu indeksów.

Ogólnie rzecz biorąc, dla indeksów b-drzewa, gdy masz dwie kolumny, masz trzy możliwe kombinacje.

  • a + b
  • a
  • b

I potrzebujesz dwóch indeksów.

  • (a, b) -- a i a + b
  • (b) -- b

(a, b) obejmuje oba wyszukiwania a i a + b. (b) obejmuje wyszukiwanie b .

Gdy masz trzy kolumny, masz siedem możliwych kombinacji.

  • a + b + c
  • a + b
  • a + c
  • a
  • b + c
  • b
  • c

Ale potrzebujesz tylko trzech indeksów.

  • (a, b, c) -- a, a + b, a + b + c
  • (b, c) -- b, b + c
  • (c, a) -- c, c + a

Jednak prawdopodobnie chcesz uniknąć indeksowania trzech kolumn. Często wolniej . To, czego naprawdę chcesz, to to.

  • (a, b)
  • (b, c)
  • (c, a)

Czytanie z indeksu jest wolniejsze niż czytanie z tabeli. Chcesz, aby indeksy zmniejszały liczbę wierszy, które muszą zostać odczytane, ale nie chcesz, aby Postgres musiał wykonywać więcej skanowania indeksów niż to konieczne.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. IntegrityError:naruszenie klucza obcego po usunięciu

  2. Jaka jest najlepsza biblioteka SQL do użycia w Common Lisp?

  3. Jak utworzyć użytkownika tylko do odczytu w PostgreSQL

  4. Wstaw ramkę danych do postgresql sqlalchemy z autoinkrementacją idx

  5. Niezbędne monitorowanie PostgreSQL — część 2