1

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

我们从各种在线供应商(亚马逊、新蛋等)导入订单信息。每个供应商都有自己的特定术语和订单结构,我们已将其镜像到数据库中。我们的数据毫无问题地导入数据库,但是我面临的问题是编写一个方法,该方法将从数据库中提取所需的字段,而不管模式如何。

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

新蛋结构:

"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

我知道一些数据库代表一个带有整数的订单号,而另一些则代表一个不同的字符;为了处理这个问题,我计划将数据类型转换为字符串值。

有没有人建议我阅读这将帮助我解决这个问题?

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

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

4

2 回答 2

4

首先,您可以创建一个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您还如何保证不同来源的唯一订单号?

  • Atimestamp without time zone在全球范围内是模棱两可的。它仅与时区有关。如果您混合timestampand timestamptz,您需要将timestamp与构造一起放置在某个时区AT TIME ZONE以使其工作。有关更多解释,请阅读此相关答案

    我使用 UTC 作为时区,您可能想提供一个不同的时区。一个简单的演员"OrderDate"::timestamptz将假定您当前的时区。AT TIME ZONE应用于 中的timestamp结果timestamptz。这就是为什么我没有添加其他演员。

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

  • 不要varchar(25)用作order_nr. text如果它必须是一个字符串,只需使用不带任意长度修饰符。如果所有订单号仅由数字组成,integer或者bigint会更快。

表现

实现这一速度的一种方法是将视图具体化。即,将结果写入(临时)表:

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

在 dba.SE 上的这个相关问题下有更多关于对象大小的信息。

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

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

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

另外,如果你坚持textvarchar为你的order_nr,考虑COLLATE "C"一下。

于 2012-11-10T00:28:30.700 回答
0

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

就像是:

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

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

使用新蛋类:

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

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

于 2012-11-09T23:42:40.830 回答