2012-04-03 76 views
0

为什么这个MySQL查询需要永久(并且永远不会完成)在一个有17k行的表上?为什么这个简单的查询需要永久?

SELECT * FROM files_folders WHERE file IN (SELECT file FROM files_folders WHERE folder = 123); 

基本上,一个文件可以在几个文件夹(物理文件及其副本)中。我试图获取文件夹123中的所有文件。现在在我的示例中,文件夹123中有两个文件。ID#4222 & ID#7121。但是,这两个文件可能在其他文件夹以及文件夹123.

我在做这个错误的方式还是有什么我失踪?

编辑:这是一个表结构的例子。

+--------------+ 
| file | folder| 
+------+-------+ 
| 1 | 1  | 
| 2 | 1  | 
| 1 | 2  | 
| 3 | 2  | 
| 4 | 3  | 
+------+-------+ 

所以我想选择是在文件夹1中的所有文件(及复印件),这将返回:

+--------------+ 
| file | folder| 
+------+-------+ 
| 1 | 1  | 
| 2 | 1  | 
| 1 | 2  | 
+------+-------+ 

由于文件1既是文件夹1和2

谢谢。

+1

你有'文件夹'的索引吗? – 2012-04-03 19:40:32

+0

我错过了什么吗?为什么不只是:'SELECT * FROM files_folders WHERE Folder = 123;' – 2012-04-03 19:43:17

+0

为什么不只是'SELECT * FROM files_folders WHERE Folder = 123'?目前你选择'ID',其中'Folder = 123'然后选择'ID',其中'ID = ID'。 – David 2012-04-03 19:43:39

回答

1

使用自联接:

SELECT 
    ff.* 
FROM 
    files_folders AS ff 
    INNER jOIN files_folders AS f ON f.ID=ff.ID 
WHERE 
    f.Folder=123 
; 
+0

这样做。谢谢。 – ademers 2012-04-03 20:04:48

+0

我试图做的真正的查询是'DELETE'。 SELECT工作正常,但只要我将它合并到“DELETE”语句中,它就会永久使用。我已将查询中的'SELECT ff。*'替换为'DELETE ff'。任何想法为什么需要很长时间?谢谢。 – ademers 2012-04-03 21:08:43

+0

使用DELETE操作时,每次删除的行都会使自连接失效,这会取消性能。对于DELETE,最好的办法是在一个查询中选择文件夹ID,然后在生成的ID列表上运行DELETE查询。这样IN(...)的参数是不变的,导致快速删除。 – 2012-04-03 22:07:57

2

对于每个文件,MySQL需要检查子查询返回的结果是否为ID。它需要O(N)

需要完成N文件。

因此,您的查询的复杂性为O(N^2)。 17k^2 =〜4*10^8所以它应该需要一分钟左右,也许更少。

为什么你的查询不是

SELECT ID FROM files_folders WHERE Folder = 123 

+0

因为一个文件也可以在另一个文件夹中。我将用表结构的示例更新我的文章。 – ademers 2012-04-03 19:49:04

-1

你为什么要使用子查询?我不认为这是必要的。你可以从表中直接选择喜欢

SELECT * FROM files_folders WHERE Folder = 123 

和第二件事:

“因为一个文件可以在另一个文件夹也”

这是什么意思用子查询?

+0

请在下次回答问题时修正语法。如果你的语法不好,很难理解你想说的话。 – ragingasiancoder 2016-07-01 13:32:02

相关问题