如何将公共数据从不同的模式插入临时表?

时间:2012-11-09 21:19:27

标签: java postgresql

我不知道如何解决这个问题:

我们从各种在线供应商(亚马逊,Newegg等)导入订单信息。每个供应商都有自己的特定术语和结构,用于我们已镜像到数据库中的订单。我们的数据导入数据库没有任何问题,但我遇到的问题是编写一个方法,从数据库中提取必需的字段,而不管架构如何。

例如假设我们有以下结构:

Newegg结构:

"OrderNumber" integer NOT NULL, -- The Order Number
"InvoiceNumber" integer, -- The invoice number
"OrderDate" timestamp without time zone, -- Create date.

亚马逊结构:

"amazonOrderId" character varying(25) NOT NULL, -- Amazon's unique, displayable identifier for an order.
"merchant-order-id" integer DEFAULT 0, -- A unique identifier optionally supplied for the order by the Merchant.
"purchase-date" timestamp with time zone, -- The date the order was placed.

如何选择这些项目并将它们放入临时表格中供我查询?

临时表可能如下所示:

"OrderNumber" character varying(25) NOT NULL,
"TransactionId" integer,
"PurchaseDate" timestamp with time zone

据我所知,有些数据库代表一个带整数的订单号,而其他数据库则代表一个字符变化;处理我计划将数据类型转换为String值。

有没有人建议我阅读有关这方面的建议?

我不需要一个确切的答案,只需要朝着正确的方向轻推。

数据将由Java使用,因此如果任何特定的Java类有帮助,请随时提出建议。

2 个答案:

答案 0 :(得分:3)

首先,您可以创建VIEW来提供此功能:

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;

您可以像查看任何其他表一样查询此视图:

SELECT * FROM orders WHERE order_nr = 123 AND source = 2;
  • 如果source不唯一,则order_nr是必需的。您如何保证不同来源的唯一订单号?

  • timestamp without time zone在全球范围内是不明确的。它与时区有关。如果您混合timestamptimestamptz,则需要将timestamp放置在具有AT TIME ZONE构造的特定时区以使其正常工作。有关详细说明,请阅读this related answer

    我使用UTC作为时区,您可能想要提供另一个。简单的演员"OrderDate"::timestamptz将假定您当前的时区。 AT TIME ZONE已应用于timestamp会导致timestamptz。这就是为什么我没有添加另一个演员。

  • 虽然可以,但我建议不要在PostgreSQL 中使用驼峰式标识符。避免多种可能的混淆。请注意我提供的小写标识符(没有现在不必要的双引号)。

  • 请勿使用varchar(25)作为order_nr的类型。如果它必须是一个字符串,只需使用text没有任意长度修饰符。如果所有订单号仅由数字组成,则integerbigint会更快。

性能

实现此目标的一种方法是实现视图。即,将结果写入(临时)表:

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

需要索引。在我的示例中,主键约束自动提供索引。

如果你的表很大,请确保你有足够的临时缓冲区来在中创建临时表之前在RAM 中处理它。否则它实际上会减慢你的速度。

SET temp_buffers = 1000MB;

必须是会话中对临时对象的第一次调用。不要在全局范围内设置它,仅适用于您的会话。无论如何,临时表会在会话结束时自动删除。

要估计您需要多少RAM,请创建一次表并测量:

SELECT pg_size_pretty(pg_total_relation_size('tmp_orders'));

有关此related question on dba.SE下的对象尺寸的更多信息。

如果您必须在一个会话中处理大量查询,则只需支付所有开销。对于其他用例,还有其他解决方案。如果您在查询时知道源表,那么将查询定向到源表会快得多。如果你不这样做,我会再次质疑你order_nr的独特性。事实上,如果确保它是唯一的,您可以删除我介绍的source列。

对于一个或几个查询,使用视图而不是物化视图可能会更快。

我还会考虑一个 plpgsql函数,它会一个接一个地查询一个表,直到找到记录。考虑到开销,考虑几个查询可能会更便宜。当然需要每个表的索引。

另外,如果您坚持使用textvarchar代替order_nr,请考虑COLLATE "C"

答案 1 :(得分:0)

听起来你需要创建一个抽象类来定义与数据交互的基础知识,然后根据需要访问的每个数据库模式派生一个类。这将允许核心代码在单个对象类型上运行,然后每个实现都可以以特定于该数据库模式的形式指定查询。

类似的东西:

public class Order
{
    private String orderNumber;
    private BigDecimal orderTotal;
    ... etc ...
}

public abstract class AbstractOrderInformation
{
  public abstract ArrayList<Order> getOrders();
  ...
}

有一个Newegg班:

public class NeweggOrderInformation extends AbstractOrderInformation
{
   public ArrayList<Order> getOrders() {
      ... do the work of getting the newegg order
   }
 ...
}

然后您可以拥有任意数量的格式,当您需要信息时,您可以遍历所有实现并从每个实现获取订单。