sql >> Database >  >> RDS >> PostgreSQL

Externe sleutels indexeren in Postgresql

tl;dr U moet een index toevoegen op item_id . De "zwarte magie" van Postgres-indexering wordt behandeld in 11. Indexen .

Je hebt een samengestelde index op (topic_id, item_id) en kolomvolgorde is belangrijk. Postgres kan dit gebruiken om zoekopdrachten te indexeren op topic_id , zoekopdrachten op beide topic_id en item_id , maar niet (of minder efficiënt) item_id alleen.

Van 11.3. Indexen met meerdere kolommen ...

-- 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 = ?

Dit komt omdat een samengestelde index zoals (topic_id, item_id) slaat eerst de onderwerp-ID op en vervolgens de item-ID's die ook die onderwerp-ID hebben. Om een ​​item-ID efficiënt in deze index op te zoeken, moet Postgres de zoekopdracht eerst verfijnen met een onderwerp-ID.

Postgres kan keer een index om als hij denkt dat het de moeite waard is. Als er een klein aantal mogelijke onderwerp-ID's is en een groot aantal mogelijke index-ID's, zoekt het naar de index-ID in elk onderwerp-ID.

Stel dat u bijvoorbeeld 10 mogelijke onderwerp-ID's en 1000 mogelijke item-ID's hebt en uw index (topic_id, index_id) . Dit is hetzelfde als het hebben van 10 duidelijk gelabelde onderwerp-ID-buckets, elk met 1000 duidelijk gelabelde item-ID-buckets binnenin. Om bij de item-ID-buckets te komen, moet het in elke onderwerp-ID-bucket kijken. Om deze index te gebruiken op where item_id = 23 Postgres moet in elk van de 10 onderwerp-ID-buckets zoeken naar alle buckets met item-ID 23.

Maar als je 1000 mogelijke onderwerp-ID's en 10 mogelijke item-ID's hebt, zou Postgres 1000 onderwerp-ID's-buckets moeten doorzoeken. Hoogstwaarschijnlijk zal het in plaats daarvan een volledige tafelscan uitvoeren. In dit geval zou je je index willen omkeren en deze (item_id, topic_id) maken .

Dit hangt sterk af van het hebben van goede tabelstatistieken, wat betekent dat het autovacuüm goed werkt.

U kunt dus wegkomen met een enkele index voor twee kolommen, als de ene kolom veel minder variabiliteit heeft dan de andere.

Postgres kan ook meerdere indexen gebruiken als het denkt dat het de query zal uitvoeren sneller . Als u bijvoorbeeld een index had op topic_id en een index op item_id , het kan gebruik beide indexen en combineer de resultaten. Bijvoorbeeld where topic_id = 23 or item_id = 42 zou de topic_id index kunnen gebruiken om te zoeken naar onderwerp-ID 23, en de item_id index om te zoeken naar item-ID 42, en dan de resultaten te combineren.

Dit is over het algemeen langzamer dan een samengestelde (topic_id, item_id) inhoudsopgave. Het kan ook langzamer zijn dan het gebruik van een enkele index, dus wees niet verbaasd als Postgres besluit om niet meerdere indexen te gebruiken.

In het algemeen geldt dat voor b-tree-indexen, als je twee kolommen hebt, je drie mogelijke combinaties hebt.

  • a + b
  • een
  • b

En je hebt twee indexen nodig.

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

(a, b) omvat zowel zoekopdrachten naar a als a + b. (b) covers zoeken naar b .

Als je drie kolommen hebt, heb je zeven mogelijke combinaties.

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

Maar je hebt maar drie indexen nodig.

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

U wilt echter waarschijnlijk voorkomen dat u een index op drie kolommen heeft. Het is vaak langzamer . Wat je eigenlijk wilt is dit.

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

Lezen uit een index is langzamer dan lezen uit de tabel. U wilt dat uw indexen het aantal te lezen rijen verminderen, maar u wilt niet dat Postgres meer indexscans moet doen dan nodig is.



  1. CannotAcquireLockException (Spring, Hibernate, MySQL)

  2. Controleer of de gebruiker al is ingelogd op de asp.net-website

  3. Geneste lussen Joins en prestatiespoelen

  4. problemen met het installeren van mysql python, mysqldb-module niet gevonden in django