sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo puedo insertar datos comunes en una tabla temporal de esquemas dispares?

Primero, puede crear un VIEW para proporcionar esta funcionalidad:

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;

Puede consultar esta vista como cualquier otra tabla:

SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
  • La source es necesario si el order_nr no es único ¿De qué otra forma garantizaría números de pedido únicos en diferentes fuentes?

  • Una timestamp without time zone es ambiguo en un contexto global. Solo es bueno en relación con su zona horaria. Si mezclas timestamp y timestamptz , debe colocar la timestamp en una determinada zona horaria con el AT TIME ZONE construir para hacer este trabajo. Para obtener más explicaciones, lea esta respuesta relacionada .

    Uso UTC como zona horaria, es posible que desee proporcionar una diferente. Un lanzamiento simple "OrderDate"::timestamptz asumiría su zona horaria actual. AT TIME ZONE aplicado a una timestamp da como resultado timestamptz . Es por eso que no agregué otro elenco.

  • Mientras puedas , aconsejo no usar identificadores camel-case en PostgreSQL nunca . Evita muchos tipos de posibles confusiones. Tenga en cuenta los identificadores en minúsculas (sin las ahora innecesarias comillas dobles) que proporcioné.

  • No use varchar(25) como tipo para el order_nr . Solo usa text sin modificador de longitud arbitrario si tiene que ser una cadena. Si todos los números de pedido consisten exclusivamente en dígitos, integer o bigint sería más rápido.

Rendimiento

Una forma de hacer esto rápido sería materializar la vista. Es decir, escriba el resultado en una tabla (temporal):

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

Usted necesita un índice. En mi ejemplo, la restricción de clave principal proporciona el índice automáticamente.

Si sus tablas son grandes, asegúrese de tener suficientes búferes temporales para manejar esto en RAM antes creas la tabla temporal. De lo contrario, te retrasará.

SET temp_buffers = 1000MB;

Tiene que ser la primera llamada a objetos temporales en su sesión. No lo establezca alto globalmente, solo para su sesión. Una tabla temporal se elimina automáticamente al final de su sesión de todos modos.

Para obtener una estimación de la cantidad de RAM que necesita, cree la tabla una vez y mida:

SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

Más información sobre los tamaños de los objetos en esta pregunta relacionada en dba.SE .

Todos los gastos generales solo se pagan si tiene que procesar varias consultas en una sesión. Para otros casos de uso hay otras soluciones. Si conoce la tabla de origen en el momento de la consulta, sería mucho más rápido dirigir su consulta a la tabla de origen. Si no lo hace, cuestionaría la singularidad de su order_nr una vez más. Si, de hecho, está garantizado que es único, puede eliminar la columna source Yo presenté.

Para solo una o algunas consultas, podría ser más rápido usar la vista en lugar de la vista materializada.

También consideraría una función plpgsql que consulta una tabla tras otra hasta que se encuentra el registro. Podría ser más barato para un par de consultas, teniendo en cuenta los gastos generales. Por supuesto, se necesitan índices para cada tabla.

Además, si te limitas a text o varchar para su order_nr , considere COLLATE "C" por ello.