constraint umbenennen (beim umbenennen der Tabelle)

Hintergrund:
Haben ein GROßE Tabelle. Die soll ein bisschen umstrukturiert werden. Damit wir möglichst wenig downtime haben, erstellen wir zunächst im laufenden Betrieb eine temporäre Tabelle. Diese müssen wir dann währen einer kurzen downtime nur noch mit den letzten Daten füllen und umbenennen. Soweit der Plan.

Ein Problem haben wir jetzt wegen des primary keys.
Der Primary key legt ja einen constraint und einen index an. Beide benennt er gemäß dem Tabellennamen. Da dieser sich ändert, sollten die namen des index und des constraint geändert werden.

Mit dem index funzt das problemlos. Constraint kann man aber - nach meinen Nachforschungen - nicht umbenennen. D.h. ich muss den constraint (und index) droppen und neu anlegen. Neuanlegen den index dauert aber wegen der table-größe zu lange.
Bei manchen DBMS kann man das Problem lösen, indem man den index zuerst unabhängig vom Constraint anzulegen. Dieser wird dann bei Erzeugung des Constraint automatisch verwendet. Das krieg ich aber in PostgreSQL nicht hin. ADD PRIMARY KEY legt anscheinend immer selber einen index an.

Was kann ich machen?

Was genau wollt ihr tun? Wozu das mit der temp. Tabelle?

Ein Problem haben wir jetzt wegen des primary keys.
Der Primary key legt ja einen constraint und einen index an. Beide benennt er gemäß dem Tabellennamen. Da dieser sich ändert, sollten die namen des index und des constraint geändert werden.

Du wirst möglicherweise ganz andere Probleme haben: wenn Dein Primary Key in anderen Tabellen referenziert wird, dann brechen bei Deiner Aktion exakt diese Referenzen weg.

Mit dem index funzt das problemlos. Constraint kann man aber - nach meinen Nachforschungen - nicht umbenennen. D.h. ich muss den constraint (und index) droppen und neu anlegen. Neuanlegen den index dauert aber wegen der table-größe zu lange.

wenn ich Dich richtig verstehe hast Du die Hoffnung, den Index der einen Tabelle der anderen zuzuschieben, um den Index nicht neu erstellen zu müssen. Das wird wohl nix werden.

Bei manchen DBMS kann man das Problem lösen, indem man den index zuerst unabhängig vom Constraint anzulegen. Dieser wird dann bei Erzeugung des Constraint automatisch verwendet. Das krieg ich aber in PostgreSQL nicht hin. ADD PRIMARY KEY legt anscheinend immer selber einen index an.

Was kann ich machen?

PG legt implizit einen Index an, wenn Du eine Spalte als PK haben willst, ja. Und zwar einen UNIQUE INDEX, um das zu erzwingen. Möglicherweise gibt es einen Weg, einen bereits vorhandenen passenden Index zu verwenden, aber das habe ich jetzt auf die Schnelle auch nicht hinbekommen.

Aber: an Deiner Stelle würde ich überlegen, ob dieser Weg mit der temp. Tabelle überhaupt sinnvoll als auch machbar ist. Und wenn: welche Rolle spielt der Name eines Indexes für Dich?


Andreas

Einfach ein update auf eine sehr große Tabelle. Das update dauert > 5 Minuten und das wolln wir an downtime vermeiden.


Du wirst möglicherweise ganz andere Probleme haben: wenn Dein Primary Key in anderen Tabellen referenziert wird, dann brechen bei Deiner Aktion exakt diese Referenzen weg.

wird nicht. Die Datenbank ist entsprechend ohne foreign keys aufgebaut.

wenn ich Dich richtig verstehe hast Du die Hoffnung, den Index der einen Tabelle der anderen zuzuschieben, um den Index nicht neu erstellen zu müssen. Das wird wohl nix werden.

Nein, vergiss das mit dem temp-table. Ich möchte einfach nur eine Tabelle umbenennen und möchte, dass die Namen aller indices und constraints ensprechend umbenannt werden und zwar ohne dass ich sie teuer neu aufbauen (drop + create) muss.


PG legt implizit einen Index an, wenn Du eine Spalte als PK haben willst, ja. Und zwar einen UNIQUE INDEX, um das zu erzwingen. Möglicherweise gibt es einen Weg, einen bereits vorhandenen passenden Index zu verwenden, aber das habe ich jetzt auf die Schnelle auch nicht hinbekommen.

ich auch nicht. Deswegen frage ich :slight_smile:


Und wenn: welche Rolle spielt der Name eines Indexes für Dich?

Wegen diverser scripte etc. wär es schön, wenn man die namen kennen würde und sie nicht ‘irgendwie_temp1’ heißen würden.

Versteh ich nicht. Ein UPDATE bedeutet doch keine Downtime. Wir haben MVCC.

Andreas

neue spalte hinzufügen, füllen, index drauf … das kann auch 2008 noch ein paar minuten dauern. Zumindest auf unseren Servern (gerade ende 2007 für nicht wenig kohle angeschafft) und mit unseren anzahl von Daten (mehrere zig millionen). Wie gesagt, mehrere Minuten und das ist zu lange.

Aber völlig egal, die Frage ist:
Kann ich eine Tabelle ‘sauber’ (mit allem was dazugehört) umbenennen (ohne irgendwas dropen und neuanlegen zu müssen)?

Schon klar, daß das dauern kann. Aber Du bekommst keine Downtime, nur das ALTER TABLE will einen exklusiven lock, sollte aber schnell gehen. Mache also nach dem ALTER TABLE erst einmal ein COMMIT. Solange das Update läuft, kannst Du dann wenigstens lesend zugreifen. Mehr fällt mir da erst mal nicht zu ein…

Andreas

es hilft nix, wenn ich lesend zugreifen kann. Ich mein auch keine datenbank downtime sondern unsere app läuft halt einfach nicht, wenn sie keine Einträge machen kann. Deswegen schalten wir sie auch ab und das ist unsere downtime.

Ich verstehe das Problem nicht ganz:

ads=# create table index_test (id serial not null primary key unique, content text);
NOTICE:  CREATE TABLE will create implicit sequence "index_test_id_seq" for serial column "index_test.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "index_test_pkey" for table "index_test"
CREATE TABLE
ads=# \d index_test
                          Table "public.index_test"
 Column  |  Type   |                        Modifiers
---------+---------+---------------------------------------------------------
 id      | integer | not null default nextval('index_test_id_seq'::regclass)
 content | text    |
Indexes:
    "index_test_pkey" PRIMARY KEY, btree (id)

ads=# alter table index_test rename to index2_test;
ALTER TABLE
ads=# \d index2_test
                         Table "public.index2_test"
 Column  |  Type   |                        Modifiers
---------+---------+---------------------------------------------------------
 id      | integer | not null default nextval('index_test_id_seq'::regclass)
 content | text    |
Indexes:
    "index_test_pkey" PRIMARY KEY, btree (id)

Ist doch egal, wie der Index heisst … der Name wird eigentlich nur intern verwendet. Das einzige Problem wären halt externe Referenzen.

Das ganze sollte man sogar problemlos innerhalb einer Transaktion ausführen können.