Ich versuche, Teilindizes für eine große statische Tabelle (1,2 TB) in Postgres 9.4 zu erstellen.
Meine Daten sind vollständig statisch, sodass ich alle Daten einfügen und dann alle Indizes erstellen kann.
In dieser 1,2-TB-Tabelle habe ich eine Spalte mit dem Namen run_id
, die die Daten sauber aufteilt . Wir haben eine großartige Leistung erzielt, indem wir Indizes erstellt haben, die einen Bereich von run_id
s abdecken . Hier ist ein Beispiel:
CREATE INDEX perception_run_frame_idx_run_266_thru_270
ON run.perception
(run_id, frame)
WHERE run_id >= 266 AND run_id <= 270;
Diese Teilindizes geben uns die gewünschte Abfragegeschwindigkeit. Leider dauert die Erstellung jedes Teilindex etwa 70 Minuten.
Es sieht so aus, als wären wir CPU-begrenzt ( top
zeigt 100% für den Prozess an).
Kann ich irgendetwas tun, um die Erstellung unserer Teilindizes zu beschleunigen?
Systemspezifikationen:
- 18 Kern Xeon
- 192 GB RAM
- 12 SSDs in RAID
- Autovakuums sind ausgeschaltet
- tenance_work_mem: 64 GB (zu hoch?)
Tabellenspezifikationen:
- Größe: 1,26 TB
- Anzahl der Zeilen: 10.537 Milliarden
- Typische Indexgröße: 3,2 GB (es gibt eine Varianz von ~ 0,5 GB)
Tabellendefinition:
CREATE TABLE run.perception(
id bigint NOT NULL,
run_id bigint NOT NULL,
frame bigint NOT NULL,
by character varying(45) NOT NULL,
by_anyone bigint NOT NULL,
by_me bigint NOT NULL,
by_s_id integer,
owning_p_id bigint NOT NULL,
obj_type_set bigint,
seq integer,
subj_id bigint NOT NULL,
subj_state_frame bigint NOT NULL,
CONSTRAINT perception_pkey PRIMARY KEY (id))
(Lesen Sie nicht zu viel in die Spaltennamen - ich habe sie etwas verschleiert.)
Hintergrundinformation:
- Wir haben ein separates Team vor Ort, das diese Daten verwendet, aber tatsächlich gibt es nur einen oder zwei Benutzer. (Diese Daten werden alle über eine Simulation generiert.) Benutzer beginnen erst mit der Analyse der Daten, wenn die Einfügungen abgeschlossen und die Indizes vollständig erstellt sind. Unser Hauptanliegen ist es, den Zeitaufwand für die Generierung verwendbarer Daten zu reduzieren. Derzeit besteht der Engpass in der Indexerstellungszeit.
- Die Abfragegeschwindigkeit war bei Verwendung von Partials völlig ausreichend. Tatsächlich denke ich, wir könnten die Anzahl der Läufe, die jeder Index abdeckt, erhöhen und dennoch eine ausreichend gute Abfrageleistung aufrechterhalten.
- Ich vermute, dass wir die Tabelle partitionieren müssen. Wir versuchen, alle anderen Optionen auszuschöpfen, bevor wir diesen Weg einschlagen.
completely static
, was meinen Sie dann damit We have a separate team onsite that consumes this data
? Indizieren Sie nur den Bereich run_id >= 266 AND run_id <= 270
oder die gesamte Tabelle? Wie hoch ist die Lebenserwartung jedes Index / wie viele Abfragen werden ihn verwenden? Für wie viele verschiedene Werte run_id
? Klingt nach ~ 15 Mio. Zeilen pro run_id
, was würde es rund 800 verschiedene Werte für machen run_id
? Warum obj_type_set
, by_s_id
, seq
nicht NOT NULL definiert? Welcher grobe Prozentsatz der NULL-Werte für jeden?
run_id
? Gleichmäßig verteilt? Größe des resultierenden Index auf der Festplatte? Daten sind statisch, ok. Aber bist du der einzige Benutzer?