这是我正在运行的查询(28小时过去了!):
drop table if exists temp_codes;
create temporary table temp_codes
select distinct CODE from Table1;
alter table temp_codes
add primary key (CODE);
drop table if exists temp_ids;
create temporary table temp_ids
select distinct ID from Table1;
alter table temp_ids
add primary key (ID);
drop table if exists temp_ids_codes;
create temporary table temp_ids_codes
select ID, CODE
from temp_ids, temp_codes;
alter table temp_ids_codes
add index idx_id(ID),
add index idx_code(CODE);
insert into Table2(ID,CODE,cnt)
select
a.ID, a.CODE, coalesce(count(t1.ID), 0)
from
temp_ids_codes as a
left join Table1 as t1 on (a.ID = t1.ID and a.CODE=t1.CODE)
group by
a.ID, a.CODE;
Run Code Online (Sandbox Code Playgroud)
我的表是这个(表1):
ID CODE
-----------------
0001 345
0001 345
0001 120
0002 567
0002 034
0002 567
0003 567
0004 533
0004 008
......
(millions of rows)
Run Code Online (Sandbox Code Playgroud)
我正在运行上面的查询,以获得这个(表2):
ID CODE CNT
1 008 0
1 034 0
1 120 1
1 345 2
1 533 0
1 567 0
2 008 0
2 034 1
...
Run Code Online (Sandbox Code Playgroud)
CNT是每个ID的每个代码的计数.如何以最佳方式实现这一点以提高性能而不使用磁盘空间?谢谢
您将数千个代码乘以数百万个ID,并想知道为什么要占用磁盘空间.您正在生成数十亿行.这将需要很长时间.
我可能会提出一些建议(如果您要重新启动流程或有资源并行运行).
首先,将中间结果保存在实际表中,可能在另一个数据库("myTmp")中,以便您可以监视进度.
其次,在最终查询中的连接之前进行聚合.实际上,因为您正在使用临时表,所以首先将它放在表中:
select t1.ID, t1.CODE, count(*) as cnt
from Table1 as t1
group by t1.ID, t1.CODE;
Run Code Online (Sandbox Code Playgroud)
现在,您通过包含所有其他代码然后分组来将原始数据相乘.
然后从完整表左边连接到这一个.
另一种方法是在原始表上有一个索引并尝试这样做:
insert into Table2(ID,CODE,cnt)
select a.ID, a.CODE,
(select count(*) from Table1 t1 where a.ID = t1.ID and a.CODE=t1.CODE) as cnt
from temp_ids_codes a
group by a.ID, a.CODE;
Run Code Online (Sandbox Code Playgroud)
这可能看起来有悖常理,但它会在table1上使用相关子查询的索引.我不喜欢用SQL玩这类游戏,但这可能会导致查询在我们的生命周期中完成.