将两列合并为一列

时间:2015-11-27 12:12:18

标签: performance postgresql sql-tuning

对于7m条目的表大小,将两列合并为一列会出现性能问题。

我的主要目标是:

  • 在一个'时间'列中合并open_time和close_time
  • DESC订购时间和account_id
  • 根据按时间和account_id排序的条目检查每个account_id的op_type列:
    • 如果op_type从0更改为1,反之亦然,对于第一个和第二个条目,请将计数器+1。
    • 如果op_type从0更改为1,反之亦然,对于第二和第三个条目,再次使计数器+1。
    • 每个account_id的所有条目
    • 等等。

account_id,open_time和close_time被编入索引。

选项#1:使用两个select语句的并集将open_time和close_time列合并到一个列'time'中:

select account_id, op_type, open_time as time, instrument_id
from tmp_operations
UNION
select account_id, op_type=0, close_time as time, instrument_id
from tmp_operations

union两个select语句的执行时间超过4 000 000 ms且仍在运行。

选项#2:使用不需要的数组将open_time和close_time列合并到一个列'time'中:

SELECT
    account_id,
    op_type,
    unnest(ARRAY[open_time, close_time]) as time,
    instrument_id
FROM risklive.operations_mt4 op

取消阵列的执行时间约为315 000 ms,这样会更好。谢谢加布里埃尔的Messanger!

我希望看到的一些示例是时间戳合并的结果:

      open_time               close_time                       time
"2015-08-19 09:18:24"    "2015-08-19 09:20:40"          "2015-08-19 09:18:24" 
"2015-08-19 09:11:54"    "2015-08-19 09:17:16"    -->   "2015-08-19 09:20:40"
"2015-08-19 09:17:46"    "2015-08-19 09:18:22"          "2015-08-19 09:11:54"
                                                        "2015-08-19 09:17:16"
                                                        "2015-08-19 09:17:16"
                                                        "2015-08-19 09:17:46"
                                                        "2015-08-19 09:18:22"

对于每个account_id的每个条目的op_type列更改计数器:

account_id   op_type         time
  63004;        1;    "2015-08-19 09:18:24"
  63004;        1;    "2015-08-19 09:20:40"
  63004;        1;    "2015-08-19 09:11:54"
  63004;        1;    "2015-08-19 09:17:16"   <-- op_type will be changed in next entry
  63004;        0;    "2015-08-19 09:17:46"   <-- counter = 1
  63004;        0;    "2015-08-19 09:18:22"   <-- op_type will be changed in next entry
  63004;        1;    "2015-08-19 09:09:31"   <-- counter = 2
  63004;        1;    "2015-08-19 09:09:31"
  63004;        1;    "2015-08-19 09:31:09"
  63004;        1;    "2015-08-19 09:32:07"   <-- op_type will be changed in next entry
  63004;        0;    "2015-08-19 09:32:09"   <-- counter = 3
  63004;        0;    "2015-08-19 09:57:44"   <-- op_type will be changed in next entry
  63004;        1;    "2015-08-19 09:20:43"   <-- counter = 4
  63004;        1;    "2015-08-19 09:31:51"
  63004;        1;    "2015-08-19 09:20:59"
  63004;        1;    "2015-08-19 09:31:51"

上面的op_type更改计数器我现在不知道如何实现。

如何调整所有内容?

1 个答案:

答案 0 :(得分:1)

既然你已经改变了一些问题,但在我回答之后,我也完全改写了我的帖子。

声明:

你需要执行操作需要合并,并且每次瓶颈时都要订购整个表(7M行)。你有可能找不到满足你的解决方案,完全改变你的appraoch。尽管如此,让我试试。

第一个问题:

所以你的第一个问题是&#34;合并&#34;两列成一个整表7M行。您尝试UNION,需要两个seq scan。正如我之前提出的,解决方案可能是使用数组聚合和unnest(你做过):

SELECT
    account_id,
    op_type,
    unnest(ARRAY[open_time, close_time]) as time,
    instrument_id
FROM risklive.operations_mt4 op

第二个问题:

正在计算op_type的{​​{1}}更改,同时按&#34; merge&#34;时间栏。为了便于阅读,我使用account_id来放置&#34;合并表&#34;英寸

我们必须使用子查询。在一个级别,我们使用正确的顺序检查CTE更改(使用op_type lag(),返回当前行之前一行的值)。在第二级,我们总共WINDOW FUNCTION次更改。

op_type

不幸的是,您的需求可能需要很长时间。如果是这样,我的意见中很难做更多的改进。