为什么我的MySQL查询使用Subselect挂起?

时间:2009-10-21 16:20:34

标签: mysql subquery

以下查询挂起:(虽然分别执行的子查询很好)

我不知道如何使解释表看起来不错。如果有人告诉我,我会清理它。

select
sum(grades.points)) as p,  
from assignments 
left join grades using (assignmentID) 
where gradeID IN 

(select grades.gradeID 
from assignments 
left join grades using (assignmentID) 
where ... grades.date <= '1255503600' AND grades.date >= '984902400' 
group by     assignmentID order by grades.date DESC);

我认为问题出在第一等级表中......带有那么多行的类型ALL似乎是原因..所有内容都被编入索引。

我将表格上传为图片。无法正确格式化: http://imgur.com/AjX34.png

评论者需要完整的where子句:

explain extended select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
where gradeID IN 
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC);

6 个答案:

答案 0 :(得分:2)

参见“难以忍受的缓慢”: http://www.artfulsoftware.com/infotree/queries.php#568

答案 1 :(得分:1)

超级凌乱,但是:(感谢大家的帮助)

   SELECT * 
   FROM grades
   LEFT JOIN assignments ON grades.assignmentID = assignments.assignmentID
   RIGHT JOIN (

   SELECT g.gradeID
 FROM assignments a
 LEFT JOIN grades g
 USING ( assignmentID ) 
 WHERE a.classID =  '7815'
 AND (
 a.type =30170
 )
 AND g.contactID =7141
  g.points
 REGEXP  '^[-]?[0-9]+[-]?'
 AND g.points !=  '-'
 AND g.points !=  ''
 AND (
 g.pointsposs IS NULL 
 OR g.pointsposs =  ''
 )
 AND g.date <=  '1255503600'
 AND g.date >=  '984902400'
 GROUP BY assignmentID
 ORDER BY g.date DESC
 ) AS t1 ON t1.gradeID = grades.gradeID

答案 2 :(得分:1)

假设您使用Real Database(即除了MySQL之外的任何数据库,但我将使用Postgres作为示例)来执行此查询:

SELECT * FROM ta WHERE aid IN (SELECT subquery)

Real Database会查看子查询并估计其rowcount:

  • 如果行数很小(比如说,少于几百万)

它将运行子查询,然后构建一个内存中的ids哈希值,这也使它们成为唯一的,这是IN()的一个特性。

然后,如果从ta拉出的行数是ta的一小部分,它将使用合适的索引来拉动行。或者,如果选择了表的主要部分,它将完全扫描它,并在哈希中查找每个id,这非常快。

  • 但是,如果子查询rowcount非常大

数据库可能会将其重写为合并JOIN,为子查询添加Sort + Unique。

但是,您正在使用MySQL。在这种情况下,它不会执行任何操作(它将为表的每一行重新执行子查询),因此需要1000年。遗憾。

答案 3 :(得分:0)

确实没有足够的信息来回答你的问题,你已经把...放在where子句的中间,这很奇怪。涉及的表有多大,索引是什么?

话虽如此,如果in子句中的术语太多,您可以看到性能严重下降。 使用右连接替换使用in

对于初学者,不使用in子句中的表 as_types 。左加入它没有任何意义,所以摆脱它。

这使得in子句只包含外部查询中的赋值和成绩表。显然,修改赋值属于外部查询的where子句。您应该将 grade = whatever 的所有内容移动到左连接的on子句中以获得成绩。

答案 4 :(得分:0)

如果子查询在单独执行时执行正常,那么尝试使用JOIN而不是IN,如下所示:

select count(assignments.assignmentID) as asscount, sum(TRIM(TRAILING '-' FROM grades.points)) as p, sum(assignments.points) as t 
from assignments left join grades using (assignmentID) 
join
(select grades.gradeID from assignments left join grades using (assignmentID) left join as_types on as_types.ID = assignments.type 
where assignments.classID = '7815' 
and (assignments.type = 30170 ) 
and grades.contactID = 7141 
and grades.points REGEXP '^[-]?[0-9]+[-]?' 
and grades.points != '-' 
and grades.points != '' 
and (grades.pointsposs IS NULL or grades.pointsposs = '') 
and grades.date <= '1255503600' 
AND grades.date >= '984902400' 
group by assignmentID 
order by grades.date DESC) using (gradeID);

答案 5 :(得分:0)

查询有点难以遵循,但我怀疑子查询根本不是必需的。 看起来您的查询基本上就是这样:

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE gradeID IN 
(
SELECT grades.gradeID
FROM assignments LEFT JOIN grades USING (assignmentID)  
WHERE your_conditions = TRUE
);

但是,你在子查询中的where子句中没有做任何真正想象的事情。 我怀疑更像是

SELECT FOO()
FROM assignments LEFT JOIN grades USING (assignmentID)  
GROUP BY groupings
WHERE your_conditions_with_some_tweaks = TRUE;

也可以。

如果我在这里遗漏了一些关键逻辑,请回复评论,我会编辑/删除这篇文章。