表A中有4列,id,name,create_time和content。
create table A
(
id int primary key,
name varchar(20),
create_time datetime,
content varchar(4000)
);
create table B like A;
我想在同一个create_time
中选择最多name
个记录,然后插入另一个表格B
。
执行sql如下,但时间消耗是不可接受的。
insert into B
select A.*
from A,
(select name, max(create_time) create_time from B group by name) tmp
where A.name = tmp.name
and A.create_time = tmp.create_time;
一个表有1000W行和10GB,执行sql花费200s。
有没有办法更快地完成这项工作,或者更改MySQL Server中哪些参数运行得更快。
号码: 表A可以是任何类型,paration表或其他一些。
答案 0 :(得分:1)
首先确保你对A(name,create_time)和B(name,create_time)有适当的索引 然后尝试使用显式连接和condtion
insert into B
select A.*
from A
inner join (
select name, max(create_time) create_time
from B
group by name) tmp on ( A.name = tmp.name and A.create_time = tmp.create_time)
答案 1 :(得分:1)
您需要的查询是:
INSERT INTO B
SELECT m.*
FROM A m # m from "max"
LEFT JOIN A l # l from "later"
ON m.name = l.name # the same name
AND m.create_time < l.create_time # "l" was created later than "m"
WHERE l.name IS NULL # there is no "later"
它将A
别名作为m
(来自“max”)与其自身别名为l
(来自“later”比“max”)。 LEFT JOIN
确保在没有WHERE
子句的情况下,m
中的所有行都出现在结果集中。 m
中的每一行都与l
中具有相同name
(m.name = l.name
)的所有行相结合,并在m
的行之后创建({{ 1}})。 m.create_time < l.create_time
条件仅在结果集中保留WHERE
中m
中没有任何匹配项的行(没有相同名称和更长创建时间的记录)。
如果l
中有多个行具有相同的A
和name
,则查询将返回所有行。为了只保留其中一个,需要额外的条件。
添加:
creation_time
到OR (m.create_time = l.create_time AND m.id < l.id)
子句(在ON
之前)。调整/替换条件的WHERE
部分以满足您的需要(此版本支持在表格中先前插入的行)。
确保表m.id < l.id
在查询使用的列上有索引(A
和name
)。否则与原始列表相比性能提升查询不重要。