CLUSTER
Pokud máte v úmyslu použít CLUSTER
, zobrazená syntaxe je neplatná.
create CLUSTER ticket USING ticket_1_idx;
Spustit jednou:
CLUSTER ticket USING ticket_1_idx;
Toto může hodně pomoci s většími sadami výsledků. Ne tolik pro jeden vrácený řádek.
Postgres si pamatuje, který index použít pro následující volání. Pokud vaše tabulka není pouze pro čtení, účinek se časem zhoršuje a je třeba ji opakovat v určitých intervalech:
CLUSTER ticket;
Možná jen na nestálých oddílech. Viz níže.
Nicméně , pokud máte hodně aktualizací, CLUSTER
(nebo VACUUM FULL
) může být ve skutečnosti špatná pro výkon. Správné množství nafouknutí umožňuje UPDATE
umístit nové verze řádků na stejnou datovou stránku a vyhnout se nutnosti příliš často fyzicky rozšiřovat základní soubor v operačním systému. Můžete použít pečlivě vyladěný FILLFACTOR
získat to nejlepší z obou světů:
- Faktor vyplnění pro sekvenční index, kterým je PK
pg_repack
CLUSTER
bere na stůl exkluzivní zámek, což může být problém ve víceuživatelském prostředí. Cituji manuál:
Při seskupování tabulky se zobrazí
ACCESS EXCLUSIVE
je na něm získán zámek. To zabrání jakýmkoli dalším databázovým operacím (jak čtení, tak zápisu ) od operace na stole až poCLUSTER
je hotovo.
Odvážný důraz můj. Zvažte alternativní pg_repack
:
Na rozdíl od
CLUSTER
aVACUUM FULL
funguje online, bez držení exkluzivního zámku na zpracovávaných tabulkách během zpracování. pg_repack je efektivní při zavádění, s výkonem srovnatelným s použitímCLUSTER
přímo.
a:
pg_repack potřebuje na konci reorganizace získat exkluzivní zámek.
Verze 1.3.1 pracuje s:
PostgreSQL 8.3, 8.4, 9.0, 9.1, 9.2, 9.3, 9.4
Verze 1.4.2 pracuje s:
PostgreSQL 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 10
Dotaz
Dotaz je dostatečně jednoduchý, aby sám o sobě nezpůsoboval žádné problémy s výkonem.
Pár slov ke správnosti :BETWEEN
konstrukt zahrnuje hranic. Váš dotaz vybere všechny z 19. prosince plus záznamy z 20. prosince, 00:00 hodin. To je extrémně nepravděpodobné požadavek. Je pravděpodobné, že opravdu chcete:
SELECT *
FROM ticket
WHERE created >= '2012-12-19 0:0'
AND created < '2012-12-20 0:0';
Výkon
Nejprve se zeptáte:
Proč volí sekvenční skenování?
Váš EXPLAIN
výstup jasně ukazuje Skenování indexu , nikoli sekvenční skenování tabulky. Musí dojít k nějakému nedorozumění.
Pokud jste tvrdě tlačeni k lepšímu výkonu, možná budete schopni věci zlepšit. Potřebné základní informace ale v otázce nejsou. Mezi možné možnosti patří:
-
Místo
*
jste mohli zadat dotaz pouze na požadované sloupce snížit náklady na přenos (a případně další výkonnostní výhody). -
Můžete se podívat na rozdělování a dejte praktické časové úseky do samostatných tabulek. Podle potřeby přidejte indexy do oddílů.
-
Pokud rozdělení není možné, další související, ale méně rušivá technika by bylo přidání jednoho nebo více částečných indexů .
Pokud se například nejčastěji dotazujete na aktuální měsíc , můžete vytvořit následující částečný index:CREATE INDEX ticket_created_idx ON ticket(created) WHERE created >= '2012-12-01 00:00:00'::timestamp;
CREATE
nový index těsně před začátek nového měsíce. Úlohu můžete snadno automatizovat pomocí úlohy cron. VolitelněDROP
částečné indexy pro staré měsíce později. -
Uchovávejte celkový index navíc pro
CLUSTER
(který nemůže pracovat s dílčími indexy). Pokud se staré záznamy nikdy nezmění, rozdělení tabulek by tomuto úkolu velmi pomohlo, protože potřebujete pouze znovu seskupovat novější oddíly. Pokud se záznamy nikdy nezmění, pravděpodobně nebudete potřebovatCLUSTER
.
Pokud zkombinujete poslední dva kroky, výkon by měl být úžasný.
Základy výkonu
Možná vám chybí jeden ze základů. Platí všechny obvyklé rady ohledně výkonu:
- https://wiki.postgresql.org/wiki/Slow_Query_Questions
- https://wiki.postgresql.org/wiki/Performance_Optimization