PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como posso inserir dados comuns em uma tabela temporária de esquemas diferentes?


Primeiro, você pode criar uma VIEW para fornecer esta funcionalidade:
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;

Você pode consultar essa visualização como qualquer outra tabela:
SELECT * FROM orders WHERE order_nr = 123 AND source = 2;

  • A source é necessário se o order_nr não é único. De que outra forma você garantiria números de pedidos exclusivos em diferentes fontes?

  • Um timestamp without time zone é ambíguo em um contexto global. Só é bom em conexão com seu fuso horário. Se você misturar timestamp e timestamptz , você precisa colocar o timestamp em um determinado fuso horário com o AT TIME ZONE construir para fazer este trabalho. Para obter mais explicações, leia esta resposta relacionada .

    Eu uso UTC como fuso horário, você pode querer fornecer um diferente. Uma conversão simples "OrderDate"::timestamptz assumiria seu fuso horário atual. AT TIME ZONE aplicado a um timestamp resulta em timestamptz . Por isso não adicionei outro elenco.

  • Enquanto você pode , aconselho não usar identificadores camel-case no PostgreSQL nunca . Evita muitos tipos de possíveis confusões. Observe os identificadores em minúsculas (sem as aspas duplas agora desnecessárias) que eu forneci.

  • Não use varchar(25) como tipo para o order_nr . Basta usar text sem modificador de comprimento arbitrário se tiver que ser uma string. Se todos os números de pedido consistirem exclusivamente em dígitos, integer ou bigint seria mais rápido.

Desempenho


Uma maneira de fazer isso rápido seria materializar a visão. Ou seja, escreva o resultado em uma tabela (temporária):
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);

Você precisa Um índice. No meu exemplo, a restrição de chave primária fornece o índice automaticamente.

Se suas tabelas forem grandes, certifique-se de ter buffers temporários suficientes para lidar com isso na RAM antes você cria a tabela temporária. Caso contrário, ele realmente irá atrasá-lo.
SET temp_buffers = 1000MB;

Tem que ser a primeira chamada para objetos temporários em sua sessão. Não o defina alto globalmente, apenas para sua sessão. Uma tabela temporária é descartada automaticamente no final de sua sessão de qualquer maneira.

Para obter uma estimativa de quanta RAM você precisa, crie a tabela uma vez e meça:
SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

Mais sobre tamanhos de objetos nesta pergunta relacionada no dba.SE .

Toda a sobrecarga só compensa se você tiver que processar várias consultas em uma sessão. Para outros casos de uso, existem outras soluções. Se você conhece a tabela de origem no momento da consulta, seria muito mais rápido direcionar sua consulta para a tabela de origem. Caso contrário, eu questionaria a exclusividade do seu order_nr mais uma vez. Se for, de fato, garantido como único, você pode remover a coluna source Eu apresentei.

Para apenas uma ou algumas consultas, pode ser mais rápido usar a visualização em vez da visualização materializada.

Eu também consideraria uma função plpgsql que consulta uma tabela após a outra até que o registro seja encontrado. Pode ser mais barato para algumas consultas, considerando a sobrecarga. Índices para cada tabela necessária, é claro.

Além disso, se você ficar com text ou varchar para seu order_nr , considere COLLATE "C" por isso.