慢MySQL查询填满了我的磁盘空间

时间:2013-08-06 11:54:40

标签: mysql database

这是我正在运行的查询(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的每个代码的计数。 如何以最佳方式实现此目的以提高性能而不使用磁盘空间? 谢谢

3 个答案:

答案 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
  • 上设置PK

答案 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计数记录)。正确的指数也可能产生巨大的差异。

相关问题