2016-10-19 13 views
3

Betrachten wir eine Tabelle, wo Einfügungen sehr oft mit zwei Feldern sind:Ist es möglich, Index pro Primärschlüssel in Postgresql zu machen?

user_id uuid, 
date timestamp 

Auch habe ich einen normalen B-Baum-Index auf (user_id, Datum). Das Problem mit einem solchen Ansatz ist, dass Insertionen zu verschiedenen user_ids nicht parallel von postgres durchgeführt werden können, da der Index in der Reihenfolge aktualisiert werden muss, da es sich um einen Baum handelt, der nach jedem Einfügen neu ausgerichtet werden kann muss warten, bis jeder einzelne Eintrag fertig ist.

Was ich will, ist der unabhängige Index pro user_id, so dass Einfügungen parallel erfolgen können. Gibt es einen Weg, es zu tun?

------- EDITED: perfekte Antwort von Laurenz Albe ist unter

+0

vielleicht können Sie den Index beim Einfügen deaktivieren? –

+0

Das ist nicht der Fall - die Abfrage, die den Index verwendet, kann oft und zu jeder Zeit aufgerufen werden. Daher ist es nicht möglich, den Index vor dem Start zu aktivieren. – user3231055

+0

"* Einreihen in verschiedene user_ids kann nicht parallel von postgres * durchgeführt werden es kann. Warum denkst du, das würde nicht funktionieren? Wenn das der Fall wäre, wäre Postgres ein ziemlich unbrauchbares DBMS –

Antwort

7

Abstract:

Sie die Macht der B-Tree-Indizes unterschätzen.

Mehrere Einfügungen in einem B-Tree-Index können parallel ausgeführt werden, und die Struktur wird nie neu ausgerichtet. Stattdessen haben Sie gelegentlich eine Indexseitenaufteilung, die nur die Vorgänge auf dieser Seite für eine kurze Zeit blockiert.

Referenzen:

Der Algorithmus zum Spalten von Seiten ist in der berühmten Papier von Lehman and Yao (ein Muss für jeden, der sich in Index-Interna) beschrieben, und die nbtree README aus der PostgreSQL Quelle beschreibt weitere Details wie, wie Löschungen werden behandelt.

Kurze Beschreibung des Einfügungsalgorithmus:

Solange eine Index-Seite nicht voll ist, neue Einträge nur eingesetzt bekommen. Dies verursacht nur eine kurze Sperre auf der Indexseite.

Wenn eine Seite voll ist, wird sie mit dem Lehman & Yao-Algorithmus aufgeteilt, der höchstens drei Seiten gleichzeitig sperrt. Diese Aufteilung erfordert einen neuen Eintrag auf der neu erstellten Seite in der übergeordneten Seite, so dass die Seite möglicherweise auch geteilt werden muss, möglicherweise bis zur Stammseite wiederkehrend.

Dennoch sind nicht mehr als drei Sperren erforderlich, da diese Vorgänge nacheinander erfolgen.

Beachten Sie, dass eine solche Stammseitenaufteilung nur 3-4 Mal während der Lebensdauer eines Index auftritt, da wenige Indizes mehr als 5 Ebenen tief sind.

Auf diese Weise haben alle Zweige eines B-Tree-Index die gleiche Tiefe, so dass der Index immer ausgeglichen ist und kein Rebalancing erforderlich ist. Rebalancing könnte nur beim Löschen von Einträgen interessant sein, aber PostgreSQL macht das nicht (außer dass es Indexseiten zurückfordert, wenn sie vollständig leer sind).

Andere Anmerkungen Ihre Frage zu:

mehr Indizes verwenden, wie Sie diese schnell – nicht machen vorschlagen würde es die Dinge viel komplizierter und langsamer, wenn Sie für jeden user_id einen Index haben zu schaffen machen würde, und Solche Indizes könnten ohnehin nicht für eine Suche verwendet werden.

Nichtsdestotrotz verlangsamen die Indizes die Einfügezeiten erheblich. Das ist ein Problem, das Sie nicht vermeiden können, wenn Daten gleichzeitig eingefügt und abgefragt werden. Wenn niemand die Daten abfragt, während Sie eine Masseneinfügung durchführen, können Sie den Index löschen und anschließend neu erstellen.

+0

+1, aber ich würde sagen, dass der Wiederaufbau des gesamten Index nach jedem Einfügen * teurer * als der Overhead einer einzelnen Einfügung ist. –

+0

Wie ich weiß, wenn eine Seite geteilt werden muss, könnte es Eltern und so weiter bis zur Wurzel beeinflussen, oder liege ich falsch? – user3231055

+1

@BillKarwin Natürlich. Das ist nur für das Masseneinfügen vieler Zeilen nützlich. –

Verwandte Themen