这是我正在运行的查询(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;
我的表是这个(表1):
ID CODE
-----------------
0001 345
0001 345
0001 120
0002 567
0002 034
0002 567
0003 567
0004 533
0004 008
......
(millions of rows)
我正在运行上述查询以获得此结果(表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
...
CNT是每个ID的每个代码的计数。 如何以最佳方式实现此目的以提高性能而不使用磁盘空间? 谢谢
答案 0 :(得分:5)
您将数千个代码乘以数百万个ID,并想知道为什么要占用磁盘空间。您正在生成数十亿行。这将需要很长时间。
我可能会提出一些建议(如果您要重新启动流程或有资源并行运行)。
首先,将中间结果保存在实际表中,可能保存在另一个数据库(“myTmp”)中,这样就可以监控进度。
其次,在最终查询中的连接之前进行聚合。实际上,因为您正在使用临时表,所以首先将它放在表中:
select t1.ID, t1.CODE, count(*) as cnt
from Table1 as t1
group by t1.ID, t1.CODE;
现在,您通过包含所有其他代码然后分组来将原始数据相乘。
然后从完整表格左侧加入到此表格。
另一种方法是在原始表上设置索引并尝试:
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;
这可能看起来有悖常理,但它会在table1上使用相关子查询的索引。我不喜欢用SQL玩这类游戏,但这可能会导致查询在我们的生命周期中完成。
答案 1 :(得分:0)
其中是WHERE
子句:
create temporary table temp_ids_codes
select ID, CODE
from temp_ids, temp_codes;
ID, CODE
答案 2 :(得分:0)
您可以尝试以下几行(未经测试的查询):
select a.ID,
a.CODE,
coalesce(b.countvalue), 0)
from temp_ids_codes as a
left join ( select count(t1.ID) as countvalue
from Table1 as t1
group by a.ID, a.CODE
) b
现在,您的group by将仅运行需要分组的记录(而不是所有0计数记录)。正确的指数也可能产生巨大的差异。