PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann ich gemeinsame Daten aus unterschiedlichen Schemas in eine temporäre Tabelle einfügen?

Zuerst können Sie eine VIEW erstellen um diese Funktionalität bereitzustellen:

CREATE VIEW orders AS
SELECT '1'::int            AS source -- or any other tag to identify source
      ,"OrderNumber"::text AS order_nr
      ,"InvoiceNumber"     AS tansaction_id -- no cast .. is int already
      ,"OrderDate" AT TIME ZONE 'UTC' AS purchase_date -- !! see explanation
FROM   tbl_newegg

UNION  ALL  -- not UNION!
SELECT 2
       "amazonOrderId"
      ,"merchant-order-id"
      ,"purchase-date"
FROM   tbl_amazon;

Sie können diese Ansicht wie jede andere Tabelle abfragen:

SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
  • Die source ist erforderlich, wenn die order_nr ist nicht einzigartig. Wie sonst würden Sie eindeutige Bestellnummern über verschiedene Quellen hinweg garantieren?

  • Ein timestamp without time zone ist im globalen Kontext mehrdeutig. Es ist nur in Verbindung mit seiner Zeitzone gut. Wenn Sie timestamp mischen und timestamptz , müssen Sie den timestamp platzieren zu einer bestimmten Zeitzone mit dem AT TIME ZONE konstruieren, damit dies funktioniert. Für weitere Erklärungen lesen Sie diese verwandte Antwort .

    Ich verwende UTC als Zeitzone, vielleicht möchten Sie eine andere angeben. Ein einfacher Cast "OrderDate"::timestamptz würde Ihre aktuelle Zeitzone annehmen. AT TIME ZONE angewendet auf einen timestamp ergibt timestamptz . Deshalb habe ich keinen weiteren Cast hinzugefügt.

  • Solange Sie können , rate ich davon ab, Camel-Case-Identifikatoren in PostgreSQL niemals zu verwenden . Vermeidet viele Arten möglicher Verwirrung. Beachten Sie die von mir bereitgestellten Bezeichner in Kleinbuchstaben (ohne die jetzt unnötigen doppelten Anführungszeichen).

  • Verwenden Sie varchar(25) nicht als Typ für die order_nr . Verwenden Sie einfach text ohne beliebigen Längenmodifikator, wenn es ein String sein muss. Wenn alle Bestellnummern ausschließlich aus Ziffern bestehen, integer oder bigint wäre schneller.

Leistung

Eine Möglichkeit, dies schnell zu machen, wäre, die Ansicht zu materialisieren. D.h. das Ergebnis in eine (temporäre) Tabelle schreiben:

CREATE TEMP TABLE tmp_orders AS
SELECT * FROM orders;

ANALYZE tmp_orders; -- temp tables are not auto-analyzed!

ALTER TABLE tmp_orders
ADD constraint orders_pk PRIMARY KEY (order_nr, source);

Sie brauchen ein Index. In meinem Beispiel liefert die Primärschlüssel-Einschränkung den Index automatisch.

Wenn Ihre Tabellen groß sind, stellen Sie sicher, dass Sie genügend temporäre Puffer haben um dies im RAM vorher zu handhaben Sie erstellen die temporäre Tabelle. Andernfalls wird es Sie tatsächlich verlangsamen.

SET temp_buffers = 1000MB;

Muss der erste Aufruf von temporären Objekten in Ihrer Sitzung sein. Stellen Sie es nicht global hoch ein, nur für Ihre Sitzung. Eine temporäre Tabelle wird am Ende Ihrer Sitzung sowieso automatisch gelöscht.

Um abzuschätzen, wie viel RAM Sie benötigen, erstellen Sie die Tabelle einmal und messen Sie:

SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

Mehr zu Objektgrößen unter dieser verwandten Frage zu dba.SE .

Der gesamte Aufwand zahlt sich nur aus, wenn Sie mehrere Abfragen innerhalb einer Sitzung verarbeiten müssen. Für andere Anwendungsfälle gibt es andere Lösungen. Wenn Sie die Quelltabelle zum Zeitpunkt der Abfrage kennen, wäre es viel schneller, Ihre Abfrage stattdessen an die Quelltabelle zu richten. Wenn Sie dies nicht tun, würde ich die Eindeutigkeit Ihrer order_nr in Frage stellen einmal mehr. Wenn die Eindeutigkeit garantiert ist, können Sie die Spalte source weglassen Ich habe vorgestellt.

Für nur eine oder wenige Abfragen kann es schneller sein, die Ansicht anstelle der materialisierten Ansicht zu verwenden.

Ich würde auch eine plpgsql-Funktion in Betracht ziehen die eine Tabelle nach der anderen abfragt, bis der Datensatz gefunden ist. Könnte für ein paar Abfragen billiger sein, wenn man den Overhead berücksichtigt. Indizes für jede benötigte Tabelle natürlich.

Auch, wenn Sie sich an text halten oder varchar für Ihre order_nr , betrachten Sie COLLATE "C" dafür.