我有一个大约有50M行和格式的表:
CREATE TABLE `big_table` (
`id` BIGINT NOT NULL,
`t1` DATETIME NOT NULL,
`a` BIGINT NOT NULL,
`type` VARCHAR(10) NOT NULL,
`b` BIGINT NOT NULL,
`is_c` BOOLEAN NOT NULL,
PRIMARY KEY (`id`),
INDEX `a_b_index` (a,b)
) ENGINE=InnoDB;
然后我定义了表t2
,没有索引:
Create table `t2` (
`id` BIGINT NOT NULL,
`a` BIGINT NOT NULL,
`b` BIGINT NOT NULL,
`t1min` DATETIME NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后我使用t2
中的查询填充big_table
(这将添加大约12M行)。
insert into opportunities
(id, a,b,t1min)
SELECT id,a,b,min(t1)
FROM big_table use index (a_b_index)
where type='SUBMIT' and is_c=1
GROUP BY a,b;
我发现在(a,b)
中处理5000个不同的big_table
需要大约一分钟的查询。
由于(a,b)
中有12M不同的big_table
,因此运行大约需要40个小时
查询所有big_table
。
出了什么问题?
如果我只做SELECT ...
,那么查询会在大约2s内完成5000行。如果我SELECT ... INTO OUTFILE ...
,则查询仍需要60秒,即5000行。
EXPLAIN SELECT ...
给出:
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,stdnt_intctn_t,index,NULL,a_b_index,16,NULL,46214255,"Using where"
答案 0 :(得分:1)
我发现问题是GROUP_BY
导致big_table
的随机读取次数过多。以下策略允许通过big_table
进行一次顺序旅行。首先,我们为t2
添加一个密钥:
Create table `t2` (
`id` BIGINT NOT NULL,
`a` BIGINT NOT NULL,
`b` BIGINT NOT NULL,
`t1min` DATETIME NOT NULL,
PRIMARY KEY (a,b),
INDEX `id` (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后我们使用以下内容填充t2
insert into t2
(id, a,b,t1min)
SELECT id,a,b,t1
FROM big_table
where type='SUBMIT' and is_c=1
ON DUPLICATE KEY UPDATE
t1min=if(t1<t1min,t1,t1min),
id=if(t1<t1min,big_table.id,t2.id);
由此产生的加速是几个数量级。
答案 1 :(得分:0)
小组可能是问题的一部分。您正在使用(a,b)上的索引,但您的位置未被使用。
我会有一个索引(type,is_c,a,b)
此外,您正在获取“ID”,但没有指定哪个......您可能希望使用MIN(ID)来获得一致的结果。