【发布时间】:2019-06-28 20:18:54
【问题描述】:
我正在尝试将一个表中的匹配记录合并到另一个表的单个记录中。我知道这可以通过 group by 和 sum()、max() 等来完成,我的困难是不属于 group by 的列是我需要连接的 varchars。
我使用的是 Sybase ASE 15,所以我没有 MySQL 的 group_concat 或类似的功能。
我尝试使用合并没有运气,目标表以与源表相同的记录数结束。
create table #source_t(account varchar(10), event varchar(10))
Insert into #source_t(account, event) values ('account1','event 1')
Insert into #source_t(account, event) values ('account1','event 2')
Insert into #source_t(account, event) values ('account1','event 3')
create table #target(account varchar(10), event_list varchar(2048))
merge into #target as t
using #source_t as s
on t.account = s.account
when matched then update set event_list = t.event_list + ' | ' + s.event
when not matched then insert(account, event_list) values (s.account, s.event)
select * from #target
drop table #target
drop table #source_t
考虑到上述表格,我希望每个帐户有一条记录,该帐户的所有事件连接在第二列中。
account, event_list
'account1', 'event 1 | event 2 | event 3'
但是,我得到的只是与#source 相同的记录。
在我看来,合并中的匹配是在语句执行开始时针对表的“状态”尝试的,因此 whenmatch 永远不会执行。有没有办法告诉 DBMS 匹配更新后的目标表?
我设法通过使用游标获得了我需要的结果,因此合并语句执行了n次,n是#source中的记录数,因此合并实际上执行了匹配时部分。
它的问题在于性能,以这种方式删除重复项大约需要 5 分钟才能将 63K 记录合并为 42K。
有没有更快的方法来实现这一点?
【问题讨论】:
-
5 分钟对于 63K 行来说是相当多的;虽然 tempdb 中的日志写入应自动延迟,但我想知道您的进程是否因大量独立的单事务
update语句而减慢;您是否尝试过将光标/合并循环包装在一个“开始/提交 tran”对中?目标是限制日志写入的数量,这反过来可能会加快速度;另一个考虑是merge语句存在性能问题,所以想知道是否...... -
... 您可以将
merge替换为您自己的 if/then/else 块,该块将公共帐户的事件附加到变量中,然后当帐户更改时,您刷新附加的事件'last' account to #target(你的光标需要有一个'order by account...'子句);目标是 a) 查看merge是否存在问题并减少对#target 的写入次数(在这种情况下,您将执行 42K 插入且没有更新);您可以使用和不使用“开始/提交 tran”包装器(围绕光标循环)进行测试,看看是否有任何区别 -
原来我忽略了创建目标表的主键。一旦我这样做了,执行时间就会下降到大约 16 秒。在循环周围添加开始/提交似乎会减少一两秒。
-
啊,是的,那(添加 PK/index 以加快查找速度)绝对可以产生差异;通过向 100KB 表添加索引,我已经将 2.1 小时的批处理过程缩短了 2 小时……一定会喜欢那些“简单”的修复;无论如何,很高兴听到您发现了性能问题