PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Come posso inserire dati comuni in una tabella temporanea da schemi disparati?

Innanzitutto, puoi creare un VIEW per fornire questa funzionalità:

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;

Puoi interrogare questa vista come qualsiasi altra tabella:

SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
  • Il source è necessario se il order_nr non è unico. In quale altro modo garantiresti numeri d'ordine univoci su diverse fonti?

  • Un timestamp without time zone è un ambiguo in un contesto globale. Va bene solo in connessione con il suo fuso orario. Se mescoli timestamp e timestamptz , devi inserire il timestamp in un determinato fuso orario con il AT TIME ZONE costruire per farlo funzionare. Per ulteriori spiegazioni leggi questa risposta correlata .

    Uso UTC come fuso orario, potresti voler fornirne uno diverso. Un semplice cast "OrderDate"::timestamptz assumerebbe il tuo fuso orario attuale. AT TIME ZONE applicato a un timestamp risulta in timestamptz . Ecco perché non ho aggiunto un altro cast.

  • Mentre tu puoi , ti consiglio di non usare gli identificatori camel-case in PostgreSQL mai . Evita molti tipi di possibile confusione. Nota gli identificatori minuscoli (senza le virgolette ora non necessarie) che ho fornito.

  • Non utilizzare varchar(25) come tipo per il order_nr . Usa semplicemente text senza un modificatore di lunghezza arbitrario se deve essere una stringa. Se tutti i numeri d'ordine sono costituiti esclusivamente da cifre, integer o bigint sarebbe più veloce.

Prestazioni

Un modo per rendere questo veloce sarebbe quello di materializzare la vista. Ad esempio, scrivi il risultato in una tabella (temporanea):

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);

Hai necessità un indice. Nel mio esempio, il vincolo della chiave primaria fornisce l'indice automaticamente.

Se i tuoi tavoli sono grandi, assicurati di avere abbastanza buffer temporanei per gestirlo nella RAM prima crei la tabella temporanea. Altrimenti ti rallenterà effettivamente.

SET temp_buffers = 1000MB;

Deve essere la prima chiamata agli oggetti temporanei nella tua sessione. Non impostarlo in alto a livello globale, solo per la tua sessione. Una tabella temporanea viene comunque eliminata automaticamente alla fine della sessione.

Per ottenere una stima della quantità di RAM necessaria, crea la tabella una volta e misura:

SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

Ulteriori informazioni sulle dimensioni degli oggetti in questa domanda correlata su dba.SE .

Tutto il sovraccarico paga solo se devi elaborare un numero di query all'interno di una sessione. Per altri casi d'uso ci sono altre soluzioni. Se si conosce la tabella di origine al momento della query, sarebbe invece molto più veloce indirizzare la query alla tabella di origine. In caso contrario, metterei in dubbio l'unicità del tuo order_nr ancora una volta. Se, infatti, è garantito che sia univoco, puoi eliminare la colonna source Ho presentato.

Per solo una o poche query, potrebbe essere più veloce utilizzare la vista invece della vista materializzata.

Considererei anche una funzione plpgsql che interroga una tabella dopo l'altra finché non viene trovato il record. Potrebbe essere più economico per un paio di domande, considerando il sovraccarico. Ovviamente indici per ogni tabella necessaria.

Inoltre, se rimani su text o varchar per il tuo order_nr , considera COLLATE "C" per questo.