优化这个MySQL查询?

时间:2010-04-13 00:47:27

标签: sql mysql

以下查询需要执行FOREVER(在Macbook上使用4gig ram时超过30小时) - 我正在寻找使其更有效运行的方法。任何想法都表示赞赏!

CREATE TABLE fc AS 
SELECT  threadid,
    title,
    body,
    date,
    userlogin
FROM f 
WHERE pid 
    NOT IN (SELECT pid FROM ft) ORDER BY date;

(表“f”为~1 Gig / 1,843,000行,表“ft”为168mb,216,000行))

6 个答案:

答案 0 :(得分:5)

尝试外连接(我认为MySQL现在支持它们)而不是不在:

create table fc as 
select f.threadid
     , f.title
     , f.body
     , f.date
     , f.userlogin 
from f 
left outer join ft 
  on f.pid = ft.pid 
where ft.pid is null 
order by date

答案 1 :(得分:2)

从EXPLAIN PLAN开始,查看优化程序的用途。然后在进行更改时重新运行它以查看它们是否有用。

我敢打赌,正确的查询将在几分钟内完成。

答案 2 :(得分:1)

在fc和ft表上的pid上添加聚簇索引。

答案 3 :(得分:0)

确保你在ft上有一个pid索引。听起来你正在获得完整的交叉产品,而不是索引的连接。

答案 4 :(得分:0)

可能会有一些隐藏的成本。运行它需要多长时间:

SELECT  count(*)
FROM f 
WHERE pid 
    NOT IN (SELECT pid FROM ft);

如果不花很长时间,那么你的命令的缓慢可能是MySQL在语句执行时复制所有数据,以防它失败并且必须回滚它。 (我在SQL Server上看过这个。)

另外:如果你拿出ORDER BY子句会有什么不同吗?

答案 5 :(得分:0)

f中有多少行与ft中的行不匹配?在最极端的情况下,如果pid中的f是唯一的,那么您的目标表fc将包含> 1.6米的行。如果大部分行将以fc结尾,那么最好分两个阶段执行此操作:

CREATE TABLE fc AS 
SELECT  threadid,
    title,
    body,
    date,
    userlogin
FROM f
ORDER BY date;

DELETE FROM fc
WHERE pid 
     IN (SELECT pid FROM ft);

顺便说一句,你可以放弃ORDER BY子句吗?那种类型可能需要花费很多周期,这取决于目标表中有多少行。

要考虑的另一件事是EXISTS条款......

CREATE TABLE fc AS 
SELECT  threadid,
    title,
    body,
    date,
    userlogin
FROM f 
WHERE NOT EXISTS 
    (SELECT pid FROM ft 
     WHERE ft.pid = f.id)
ORDER BY date;

......或者我的两步版......

DELETE FROM fc
WHERE EXISTS
     (SELECT pid FROM ft 
 WHERE ft.pid = f.id);

当子查询生成大量行时,EXISTS可以比IN快很多。然而,正如调整一样,基准测试是关键。