如何将公共数据从不同的模式插入临时表?
我不知道如何解决这个问题:
我们从各种在线供应商(亚马逊,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类有帮助,请随时提出建议。
首先,您可以创建一个VIEW
来提供此function:
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;
-
如果
order_nr
不是唯一的,则source
是必需的。 您如何保证不同来源的唯一订单号? -
timestamp without time zone
的timestamp without time zone
在全局上下文中是不明确的。 它与时区有关。 如果混合timestamp
和timestamptz
,则需要使用AT TIME ZONE
结构将timestamp
放在特定时区以使其工作。 有关更多说明,请阅读此相关答案 。我使用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函数 ,它一个接一个地查询一个表,直到找到记录。 考虑到开销,考虑几个查询可能会更便宜。 当然需要每个表的索引。
另外,如果您坚持使用order_nr
text
或varchar
,请考虑使用COLLATE "C"
。
听起来你需要创建一个抽象类来定义与数据交互的基础知识,然后为每个需要访问的数据库模式派生一个类。 这将允许核心代码在单个对象类型上运行,然后每个实现都可以以特定于该数据库模式的forms指定查询。
就像是:
public class Order { private String orderNumber; private BigDecimal orderTotal; ... etc ... } public abstract class AbstractOrderInformation { public abstract ArrayList getOrders(); ... }
与Neweggclass级:
public class NeweggOrderInformation extends AbstractOrderInformation { public ArrayList getOrders() { ... do the work of getting the newegg order } ... }
然后,您可以拥有任意数量的格式,当您需要信息时,您可以迭代所有实现并从每个实现获取订单。