sql >> Database >  >> RDS >> PostgreSQL

Hoe kan ik gemeenschappelijke gegevens invoegen in een tijdelijke tabel van ongelijksoortige schema's?

Ten eerste kunt u een VIEW maken om deze functionaliteit te bieden:

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;

U kunt deze weergave opvragen zoals elke andere tabel:

SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
  • De source is nodig als het order_nr is niet uniek. Hoe zou je anders unieke bestelnummers over verschillende bronnen garanderen?

  • Een timestamp without time zone is een ambigue in een mondiale context. Het is alleen goed in verband met zijn tijdzone. Als je timestamp door elkaar haalt en timestamptz , moet u de timestamp . plaatsen in een bepaalde tijdzone met de AT TIME ZONE bouwen om dit te laten werken. Lees voor meer uitleg dit gerelateerde antwoord .

    Ik gebruik UTC als tijdzone, misschien wilt u een andere opgeven. Een eenvoudige cast "OrderDate"::timestamptz zou uitgaan van uw huidige tijdzone. AT TIME ZONE toegepast op een timestamp resulteert in timestamptz . Daarom heb ik geen andere cast toegevoegd.

  • Terwijl je kunt , raad ik aan om geen camel-case-ID's te gebruiken in PostgreSQL ooit . Vermijdt vele soorten mogelijke verwarring. Let op de kleine letters (zonder de nu overbodige dubbele aanhalingstekens) die ik heb opgegeven.

  • Gebruik varchar(25) niet als type voor het order_nr . Gebruik gewoon text zonder willekeurige lengtemodifier als het een string moet zijn. Als alle bestelnummers uitsluitend uit cijfers bestaan, integer of bigint zou sneller zijn.

Prestaties

Een manier om dit snel te maken zou zijn om het uitzicht te materialiseren. Dat wil zeggen, schrijf het resultaat in een (tijdelijke) tabel:

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

Je nodig een index. In mijn voorbeeld levert de primaire sleutelbeperking automatisch de index.

Als je tabellen groot zijn, zorg er dan voor dat je voldoende tijdelijke buffers hebt om dit voor in het RAM af te handelen je maakt de temp tabel. Anders zal het je juist vertragen.

SET temp_buffers = 1000MB;

Moet de eerste oproep zijn om tijdelijke objecten in uw sessie te plaatsen. Zet het niet wereldwijd hoog, alleen voor uw sessie. Een tijdelijke tafel wordt sowieso automatisch verwijderd aan het einde van je sessie.

Om een ​​schatting te krijgen hoeveel RAM u nodig heeft, maakt u de tabel één keer aan en meet u:

SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

Meer over objectgroottes onder deze gerelateerde vraag over dba.SE .

Alle overhead loont alleen als je meerdere vragen binnen één sessie moet verwerken. Voor andere use-cases zijn er andere oplossingen. Als u de brontabel kent op het moment van de query, zou het veel sneller zijn om uw query in plaats daarvan naar de brontabel te leiden. Als je dat niet doet, zou ik de uniciteit van je order_nr in twijfel trekken nog een keer. Als het in feite gegarandeerd uniek is, kun je de kolom source . weglaten Ik heb geïntroduceerd.

Voor slechts één of enkele zoekopdrachten kan het sneller zijn om de weergave te gebruiken in plaats van de gerealiseerde weergave.

Ik zou ook een plpgsql-functie . overwegen die de ene tabel na de andere doorzoekt totdat het record is gevonden. Misschien goedkoper voor een paar vragen, gezien de overhead. Indexen voor elke benodigde tafel natuurlijk.

Ook als u zich houdt aan text of varchar voor uw order_nr , overweeg COLLATE "C" ervoor.



  1. Snapshot controlfile-functie met RMAN en ORA-00245

  2. meerdere selectInput-waarden creëren onverwacht dplyr (postgres) gedrag

  3. Kun je een veld in een MySQL-query splitsen/exploderen?

  4. Sessies opslaan in DB-tabel werkt niet (met Zend_Session_SaveHandler_DbTable)