0

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

SELECT * FROM filesWHERE filename<> '' AND filenameNOT IN (SELECT filenameFROM downloads)

这在记录很少时工作正常,但现在不工作,几天前,当有 50k 和 20k 记录时,它变得很慢,就像在 5/6 分钟内得到结果一样,但现在它显示了这个错误:

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

文件名字段是表的文件​​名字段(varchar 255),并且两个字段都被索引。有什么帮助吗?

4

3 回答 3

1

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

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

然后,使用 aLEFT JOIN而不是子查询。

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

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

于 2013-06-28T22:17:36.113 回答
0

最好 left_join 2 个表,因此,我们从 files 表中获取所有记录,并从下载中添加适当的记录。下载文件中包含 null 的文件名是我们需要的文件名,因此,我们过滤以仅获取这些文件名。

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<>''

我的实现只是 2 次简单的扫描:

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
于 2013-06-28T22:16:17.277 回答
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 正在做什么。

于 2013-06-28T22:16:28.860 回答