【问题标题】:How to join two tables based on a timestamp (with variance of a few seconds)?如何根据时间戳(几秒的差异)连接两个表?
【发布时间】:2013-12-09 19:09:09
【问题描述】:

我有两个表,我试图根据三列的组合将它们加入并插入到另一个表中。我会解释的。

表 M

| ANO      | BNO     |         Timestamp   |  Duration
---------------------------------------------------------------
|  5612853 | 4732621 | 21.11.2013 09:50:58 | 196
|  4842988 | 5610953 | 21.11.2013 17:34:58 | 98
|  7765759 | 5612853 | 21.11.2013 20:48:00 | 377
|  2470321 | 2470263 | 21.11.2013 21:47:18 | 125

表 N

| ANO      | BNO     |         Timestamp   |  Duration
---------------------------------------------------------------
|  5612853 | 4732621 | 21.11.2013 09:50:52 | 196
|  4842988 | 5610953 | 21.11.2013 17:34:53 | 98
|  7765759 | 5612853 | 21.11.2013 20:47:55 | 377
|  2470321 | 2470263 | 21.11.2013 21:47:13 | 125

现在这两个表必须匹配并插入到 Table MN 基于

M.ANO=N.ANO and M.BNO=N.BNO and ((M.TIMESTAMP = N.TIMESTAMP+5/86400) or (M.TIMESTAMP = N.TIMESTAMP+6/86400))

所以理论上,我的输出Table MN应该是

| ANO      | BNO     |         Timestamp   |  Duration  || ANO      | BNO     |         Timestamp   |  Duration
--------------------------------------------------------------------------------------------------------------
|  5612853 | 4732621 | 21.11.2013 09:50:58 | 196        ||  5612853 | 4732621 | 21.11.2013 09:50:52 | 196
|  4842988 | 5610953 | 21.11.2013 17:34:58 | 98         ||  4842988 | 5610953 | 21.11.2013 17:34:53 | 98
|  7765759 | 5612853 | 21.11.2013 20:48:00 | 377        ||  7765759 | 5612853 | 21.11.2013 20:47:55 | 377
|  2470321 | 2470263 | 21.11.2013 21:47:18 | 125        ||  2470321 | 2470263 | 21.11.2013 21:47:13 | 125

表 M 大约有 140 万条记录,表 N 大约有 90 万条记录。

我已尝试根据以下两个查询连接这两个表。但它需要几个小时才能执行,如果我必须每天运行它,这是不可行的。

INSERT INTO MN_RECON (
SELECT M.*,N.* FROM M FULL OUTER JOIN N ON
M.ANO=N.ANO AND M.BNO=N.BNO AND 
((M.TIMESTAMP=N.TIMESTAMP+5/86400) OR (M.TIMESTAMP=N.TIMESTAMP+6/86400))

INSERT INTO MN_RECON (
SELECT M.*,N.* FROM M FULL OUTER JOIN N ON
M.ANO=N.ANO AND M.BNO=N.BNO AND
(M.TIMESTAMP-N.TIMESTAMP IN (5/86400,6/86400)

当我只运行上述 2 个查询的 SELECT 语句时,我会在一分钟内得到一个输出(只有 100 个样本行),但是添加了 INSERT 需要很长时间。 有没有办法优化我想做的事情?

我需要它来匹配时间戳,因为在一天中可能会多次出现相同的 ANO - BNO 组合,时间戳是它们之间的唯一标识符

而且我需要完全外连接,因为我需要关注不匹配的记录,以及两个表之间持续时间不同的匹配记录。

其他 Oracle 信息Oracle Database 11g Enterprise Edition 11.2.0.3.0 64-bit Production

解释计划

| Id  | Operation                | Name            | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |                 |  2386K|   530M|       |  2395M  (1)|999:59:59 |
|   1 |  LOAD TABLE CONVENTIONAL | MN_RECON        |       |       |       |            |          |
|   2 |   VIEW                   |                 |  2386K|   530M|       |  2395M  (1)|999:59:59 |
|   3 |    UNION-ALL             |                 |       |       |       |            |          |
|*  4 |     HASH JOIN RIGHT OUTER|                 |  1417K|   109M|    49M| 10143   (1)| 00:02:02 |
|   5 |      TABLE ACCESS FULL   | N_VOICE         |   968K|    38M|       |  1753   (1)| 00:00:22 |
|   6 |      TABLE ACCESS FULL   | M_VOICE         |  1417K|    52M|       |  2479   (1)| 00:00:30 |
|*  7 |     FILTER               |                 |       |       |       |            |          |
|   8 |      TABLE ACCESS FULL   | N_VOICE         |   968K|    38M|       |  1754   (1)| 00:00:22 |
|*  9 |      TABLE ACCESS FULL   | M_VOICE         |     1 |    29 |       |  2479   (1)| 00:00:30 |

【问题讨论】:

  • 你试过:“(M.TIMESTAMP IN (I.TIMESTAMP+5/86400,I.TIMESTAMP+6/86400))”吗?发布解释计划对于查询性能问题通常是必不可少的。
  • 另外,您的确切 oracle 版本、版本和许可选项是什么?
  • 不,我还没有尝试过,目前我正在尝试这个 ABS(TO_CHAR(M.MSC_CALL_DATE,'SSSSS')-TO_CHAR(O.OCS_CALL_DATE, 'SSSSS')) > 5和 ABS(TO_CHAR(M.MSC_CALL_DATE,'SSSSS')-TO_CHAR(O.OCS_CALL_DATE, 'SSSSS'))
  • 准确的oracle版本是Oracle Database 11g Enterprise Edition 11.2.0.3.0 64-bit Production
  • 为什么您对 4 秒或更短的差异不感兴趣?

标签: sql oracle11g sqltools


【解决方案1】:

加快查询速度的一种简单方法是创建基于函数的索引:

CREATE INDEX indexname1 ON N (timestamp+5/86400);
CREATE INDEX indexname2 ON N (timestamp+6/86400);

【讨论】:

  • 我不太清楚如何使用索引(我以前从未使用过它们)我应该在执行我的加入之前运行它吗?并且我的加入条件保持不变?
  • 当性能对您很重要时,索引是最重要的因素。我建议你调查一下。
  • 因为这似乎暗示您没有在任一表上定义单个索引,您应该这样做:CREATE INDEX indexname on M (ANO,BNO)CREATE INDEX indexname on N (ANO,BNO)
  • 在执行查询之前创建索引。无需更改查询本身。
  • 检查此查询是否有用:`SELECT M.ANO,M.BNO,M.TIMESTAMP TIMESTAMP_M,n.TIMESTAMP TIMESTAMP_M,M.DURATION DURATION_M, N.DURATION DURATION_N, M.TIMESTAMP- N.TIMESTAMP FROM M INNER JOIN N ON (M.ANO=N.ANO AND M.BNO=N.BNO)
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2020-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多