sql >> Databáze >  >> RDS >> PostgreSQL

Indexování cizích klíčů v Postgresql

tl;dr Musíte přidat index na item_id . „Černá magie“ indexování Postgres je popsána v 11. Indexy .

Máte složený index na (topic_id, item_id) a pořadí sloupců je důležité. Postgres to může použít k indexování dotazů na topic_id , dotazy na obě topic_id a item_id , ale ne (nebo méně efektivně) item_id sám.

Z 11.3. Vícesloupcové indexy ...

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

Důvodem je složený index jako (topic_id, item_id) nejprve ukládá ID tématu a poté ID položek, které mají také toto ID tématu. Aby bylo možné v tomto indexu efektivně vyhledat ID položky, musí Postgres nejprve zúžit vyhledávání pomocí ID tématu.

Postgres umí obrátit index, pokud si myslí, že to stojí za námahu. Pokud existuje malý počet možných ID témat a velký počet možných ID indexů, vyhledá ID indexu v každém ID tématu.

Řekněme například, že máte 10 možných ID témat a 1000 možných ID položek a váš index (topic_id, index_id) . Je to jako mít 10 jasně označených segmentů ID tématu, každý s 1000 jasně označenými segmenty ID položek uvnitř. Chcete-li se dostat do segmentů ID položek, musí se podívat do každého segmentu ID tématu. Chcete-li použít tento index na where item_id = 23 Postgres musí v každém z 10 segmentů ID tématu vyhledat všechny segmenty s ID položky 23.

Ale pokud máte 1000 možných ID témat a 10 možných ID položek, Postgres by musel prohledat 1000 segmentů ID témat. S největší pravděpodobností místo toho provede úplné skenování tabulky. V tomto případě byste chtěli obrátit svůj index a vytvořit jej (item_id, topic_id) .

To do značné míry závisí na dobrých statistikách tabulky, což znamená, že automatické vakuování funguje správně.

Pokud má jeden sloupec mnohem menší variabilitu než jiný, můžete si vystačit s jediným indexem pro dva sloupce.

Postgres může také použít více indexů, pokud si myslí, že spustí dotaz rychlejší . Pokud jste například měli index na topic_id a index na item_id , může použijte oba indexy a zkombinujte výsledky. Například where topic_id = 23 or item_id = 42 mohli použít index topic_id k vyhledání tématu ID 23 a index item_id k vyhledání položky ID 42 a poté výsledky zkombinovat.

To je obecně pomalejší než použití složeného (topic_id, item_id) index. Může to být také pomalejší než použití jednoho indexu, takže se nedivte, že se Postgres rozhodne nepoužívat více indexů.

Obecně platí, že pro indexy b-stromu, když máte dva sloupce, máte tři možné kombinace.

  • a + b
  • a
  • b

A potřebujete dva indexy.

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

(a, b) pokrývá jak hledání a, tak a + b. (b) pokrývá vyhledávání b .

Když máte tři sloupce, máte sedm možných kombinací.

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

Ale potřebujete pouze tři indexy.

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

Pravděpodobně se však ve skutečnosti chcete vyhnout tomu, abyste měli index ve třech sloupcích. Často je to pomalejší . To, co ve skutečnosti chcete, je toto.

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

Čtení z rejstříku je pomalejší než čtení z tabulky. Chcete, aby vaše indexy snížily počet řádků, které je třeba číst, ale nechcete, aby Postgres musel provádět skenování indexů více, než je nutné.



  1. Migrujte MS Access na MySQL

  2. Může být cizí klíč NULL a/nebo duplicitní?

  3. ORA-01797:po tomto operátoru musí následovat LIBOVOLNÁ nebo VŠECHNA chyba

  4. můžeme spustit unixový příkaz z procedury oracle10g