避免PostgreSQL中的嵌套循环

时间:2014-10-07 18:57:07

标签: postgresql loops join nested subquery

请参阅下面的查询

Select count(*) FROM
(Select distinct Student_ID, Name, Student_Age, CourseID from student) a1
JOIN
(Select distinct CourseID, CourseName, TeacherID from courses) a2
ON a1.CourseID=a2.CourseID
JOIN 
(Select distinct TeacherID, TeacherName, Teacher_Age from teachers) a3
ON a2.TeacherID=a3.TeacherID

子查询必须用于重复数据删除。

此查询在PostgreSQL中运行正常。但是,如果我在学生表和教师表之间添加条件,根据执行计划,Postgres将错误地嵌套循环加入学生并教授没有直接关系的表。例如:

Select count(*) FROM
(Select distinct Student_ID, Name, Student_Age, CourseID from student) a1
JOIN
(Select distinct CourseID, CourseName, TeacherID from courses) a2
ON a1.CourseID=a2.CourseID
JOIN 
(Select distinct TeacherID, TeacherName, Teacher_Age from teachers) a3 ON
 a2.TeacherID=a3.TeacherID
WHERE Teacher_Age>=Student_Age

此查询将永远运行。但是,如果我用表替换子查询,它会非常快地运行。如果不使用临时表存储重复数据删除结果,有没有办法在这种情况下避免嵌套循环?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您正在使数据库执行大量不必要的工作以实现您的目标。不是将3个不同的SELECT DISTINCT子查询全部连接在一起,而是尝试将基表直接相互连接,并让它只处理DISTINCT部分一次。如果你的表在ID字段上有适当的索引,这应该会很快运行。

SELECT COUNT(1)
    FROM (
    SELECT DISTINCT s.Student_ID, c.CourseID, t.TeacherID
        FROM student s
        JOIN courses c ON s.CourseID = c.CourseID
        JOIN teachers t ON c.TeacherID = t.TeacherID
        WHERE t.Teacher_Age >= s.StudentAge
     ) a