2012-04-11 6 views
3

Ich weiß, dass Sie einen Index für ein Feld in einer Hstore-Spalte erstellen können. Ich weiß, dass Sie auch einen GIN-Index für eine Array-Spalte erstellen können.Indizes auf PostgreSQL Hstore Array-Spalten

Aber wie lautet die Syntax zum Erstellen eines Index für ein Hstore-Array?

z.B.

CREATE TABLE customer (
    pk serial PRIMARY KEY, 
    customer hstore, 
    customer_purchases hstore[] 
); 

Sagen wir, der Kunde kauft hstore ein Hash sein kann wie

productId -> 1 
price -> 9.99 

und ich habe eine Reihe von denen in den customer_purchases hstore []

Ich möchte einen Index für Kunden schaffen .customer_purchases [] -> productId

Ist das möglich? Ich habe verschiedene Kombinationen von CREATE INDEX-Syntaxen ausprobiert, und keines davon scheint Indexfelder in einem Hstore-Array zu unterstützen.

+0

Dies scheint ein gelöstes Problem, wenn Sie Hstore ignorieren und einfach zwei zusätzliche Tabellen verwenden. Warum so? Wenn Sie aus irgendeinem Grund eine IMMUTABLE-Funktion definieren müssen, die einen sortierbaren Wert erzeugt, und rufen Sie die Funktion in Ihrer CREATE INDEX-Syntax auf. –

+0

Wie ich in einem Kommentar unten erwähnt habe, wollen wir uns zu einem schemafreien DB-Modell entwickeln, so dass wir neue Versionen unserer Anwendungen ohne Ausfallzeiten durch DB-Upgrades und Tabellensperren ALTER TABLE ADD COLUMN einführen können. –

Antwort

5

Ich denke, Sie haben PostgreSQL Array s missverstanden. Ein Array ist eigentlich nur eine Zeichenfolge. Sie können die Objekte (in diesem Fall HSTORE s) im Array nicht indexieren, einfach weil es kein TABLE ist. eine zusätzliche Tabelle

Stattdessen erstellen:

CREATE TABLE customer (
    pk bigserial PRIMARY KEY, 
    customer hstore 
); 

CREATE TABLE purchases (
    pk bigserial PRIMARY KEY, 
    customer_pk bigint not null, 
    purchase hstore not null, 
    constraint "must be a valid customer!" 
     foreign key (customer_pk) references customer(pk) 
); 

Auch Warum verwenden Sie HSTORE hier s?

Wenn Sie müssen eine INDEX erstellen auf der Grundlage der "purchase"HSTORE hier etwas tun, wie folgt aus:

CREATE OR REPLACE FUNCTION purchase_amount(purchase hstore) returns float as $$ 
    select ($1 -> 'price')::float; 
$$ language 'SQL' IMMUTABLE; 

CREATE INDEX "purchases by price" ON purchases (purchase_amount(purchase)); 

Ist dies nur eine Übung, die HSTORE Art zu verstehen? Oder haben Sie einen echten Anwendungsfall, der all diese Verschleierung Ihrer realen Daten lohnen würde?

+1

Ich weiß aus keinem Grund, dass Sie einen GIN- oder GIST-Index nicht direkt in einer Hstore-Spalte erstellen können. Es ist hier dokumentiert: http://www.postgresql.org/docs/9.1/interactive/hstore.html#AEN133006 Aber ich tendiere dazu zu denken, es ist eine schlechte Wahl, verglichen mit der Normalisierung der Daten mit separaten Tabellen für Einkäufe und line_items. Nur weil du * etwas * tun kannst, ist es keine gute Idee. Auf der anderen Seite, wenn dies eine Trainingsübung ist, um zu sehen, wie man hstore benutzt, denke ich, dass diese Antwort der beste Weg zu gehen ist. – kgrittn

+2

Es ist keine Verschleierung. Es müssen keine Upgrades für Downtime durchgeführt werden (d. H. Die Tabelle kann nicht mit ALTER TABLE ADD COLUMN gesperrt werden), wenn eine neue Version der App bereitgestellt wird. Hstore schien eine gute Option zu sein, einen schemalosen Entity-Speicher zu haben, der über die Anwendungslogik Überstunden generieren kann, ohne DB-Upgrades. –

+2

Das Hinzufügen einer Spalte zu einer Tabelle in postgresql sperrt die Tabelle nicht für eine merkliche Zeitspanne (vorausgesetzt, die Spalte hat keine Einschränkungen und kann nullbar sein). –

Verwandte Themen