Mysql从大型两个表中找到不匹配的记录

时间:2013-06-28 22:12:25

标签: php mysql sql

我有两个表包含现有文件名和下载文件名。现有文件表上的61k +记录和下载文件表上的34k +记录。我正在使用此查询来查找尚未下载的文件名!

  

SELECT * FROM files WHERE filename<> ''和filename不在   (SELECT filename FROM downloads

当记录很少但现在不能正常工作,几天前,当有50k和20k记录时,这种情况正常,但是在5/6分钟内获得结果变慢,但现在它显示了这个错误:

  

内部服务器错误500
  子进程(php)没有响应退出信号:0

filename字段是表的文件​​名字段(varchar 255),并且这两个字段都被编入索引。任何帮助PLZ?

3 个答案:

答案 0 :(得分:1)

首先,在filesdownloads上添加索引。这将使搜索速度更快。这可能需要几分钟时间。

ALTER TABLE files ADD INDEX (filename);
ALTER TABLE downloads ADD INDEX (filename);

然后,使用LEFT JOIN代替子查询。

SELECT f.*
FROM files f
LEFT JOIN downloads d ON
    d.filename = f.filename
WHERE
    d.filename IS NULL
    AND f.filename <> ''

完成这些更改后,搜索时间不到一秒。

答案 1 :(得分:0)

left_join 2表会更好,因此,我们从files表中获取所有记录,并从下载中添加适当的记录。来自下载的空对象文件的文件名是我们需要的文件名,因此,我们过滤只获得这些文件名。

select f.filename from files as f left join downloads as d on f.filename=d.filename where d.filename is null and f.filename<>''

我的实现只是两个简单的扫描:

mysql> explain select f.filename from files as f left join downloads as d on f.filename=d.filename where d.filename is null and f.filename<>'';
   SIMPLE   f   Using where; Using index; 
   SIMPLE   d   Using where; Using index; Not exists

原始的使用子查询:

mysql> explain SELECT * FROM files WHERE filename <> '' AND filename NOT IN (SELECT filename FROM downloads);
   PRIMARY              files
   DEPENDENT SUBQUERY   downloads

答案 2 :(得分:0)

编写查询的更好方法是(假设您有一个id列):

SELECT a.*
FROM files a
LEFT JOIN downloads b ON b.filename = a.filename
WHERE b.id IS NULL
AND a.filename != ''

由于PHP脚本超时,可能会返回错误。如果此查询仍然运行得不够快,请在开头使用EXPLAIN发布上述查询的输出,以便我们可以看到MySQL正在做什么。