Postgresql在很多表之间连接

时间:2017-11-12 20:57:03

标签: postgresql

好的,我在过去6年转移到MongoDB之前已经使用了MySQL / postgres很多年了,现在我正在绘制一些空白。我一直在寻找最好的方法来实现这一点,并且使用我非常简单的数据集,查询时间平均为20毫秒。对于<似乎很疯狂100行。我可能以超级复杂的方式做到了这一点:)

因此,这里的想法是获取用户可以访问的课程列表,以及他们的最新测验分数和最新课程进度(他们在课程中取得的成绩)。

SELECT DISTINCT ON (m.id) m.id,m.lesson_name,m.course_name,m.order,m.progress,m.thumb,m.media_id,m.length,m.quiz_id,m.score FROM (SELECT
    lessons.id,lessons.name AS lesson_name,courses.name AS course_name, lesson_courses."order", less_prog.progress, lessons.thumb, lessons.media_id, lessons.length, lesson_quiz.id as quiz_id, acclessq.score,acclessq.timestamp as atime, less_prog.timestamp as ltime
    FROM lessons
    INNER JOIN lesson_courses ON lessons."id" = lesson_courses.lessons_id
    INNER JOIN plan_courses ON plan_courses.courses_id = lesson_courses.courses_id
    INNER JOIN courses ON courses.id = lesson_courses.courses_id
    LEFT JOIN (
        SELECT progress,lessons_id,timestamp FROM lesson_progress WHERE accounts_id = 1
    ) as less_prog ON less_prog.lessons_id = lessons.id
    LEFT JOIN (
        SELECT lesson_quiz.id,lesson_quiz.lessons_id FROM lesson_quiz
    ) as lesson_quiz ON lessons.id=lesson_quiz.lessons_id
    LEFT JOIN (
        SELECT score,lesson_quiz_id,account_lesson_quiz.timestamp FROM account_lesson_quiz WHERE account_lesson_quiz.accounts_id = 1
    ) as acclessq ON lesson_quiz.id=acclessq.lesson_quiz_id
    LEFT JOIN (
        SELECT accounts_id,plans_id FROM account_plans WHERE accounts_id = 1
    ) as account_plans ON account_plans.plans_id = plan_courses.plans_id
    GROUP BY lessons.id,courses.id,courses.name,lesson_courses.order,less_prog.progress, lessons.thumb, lessons.media_id, lessons.length, quiz_id, acclessq.score,atime,ltime
    ORDER BY courses.id, lesson_courses."order",atime DESC,ltime DESC) m

我确信我做得过于疯狂,但我得到了正确的结果......那么,当我们有更多结果时,如何简化它并降低性能呢?

更新:尝试使用WITH重写。垂直下降到平均15ms。它确实看起来更干净,但我仍觉得这对于少量数据来说太高了。

WITH lesson_quiz AS (SELECT lesson_quiz.id,lesson_quiz.lessons_id FROM 
lesson_quiz),
less_prog AS (SELECT progress,lessons_id,timestamp FROM lesson_progress 
WHERE accounts_id = 1),
acclessq AS (SELECT score,lesson_quiz_id,account_lesson_quiz.timestamp 
FROM account_lesson_quiz WHERE account_lesson_quiz.accounts_id = 1),
acc_plans AS (SELECT accounts_id,plans_id FROM account_plans WHERE 
accounts_id = 1)

SELECT DISTINCT ON (lessons.id)
lessons.id,lessons.name AS lesson_name,courses.name AS course_name, lesson_courses."order", less_prog.progress, lessons.thumb, lessons.media_id, lessons.length, lesson_quiz.id as quiz_id, acclessq.score
FROM lessons
INNER JOIN lesson_courses ON lessons."id" = lesson_courses.lessons_id
INNER JOIN plan_courses ON plan_courses.courses_id = lesson_courses.courses_id
INNER JOIN courses ON courses.id = lesson_courses.courses_id
LEFT JOIN less_prog ON less_prog.lessons_id = lessons.id
LEFT JOIN lesson_quiz ON lessons.id=lesson_quiz.lessons_id
LEFT JOIN acclessq ON lesson_quiz.id=acclessq.lesson_quiz_id
LEFT JOIN acc_plans ON acc_plans.plans_id = plan_courses.plans_id
ORDER BY id, acclessq.timestamp DESC, less_prog.timestamp DESC

以下是查询计划:https://explain.depesz.com/s/IvPl

3 个答案:

答案 0 :(得分:2)

GROUP BY和DISTINCT经常达到同样的目的。你确定你需要DISTINCT,如果是这样的话,你删除它时效果会更好吗?

感谢您的查询计划。也许时间戳DESC列上的索引会有帮助吗?似乎大部分时间都用于排序。

答案 1 :(得分:1)

WITH查询可能看起来更优雅。另一个选择是创建一个视图。

答案 2 :(得分:0)

它最终落到了电脑上。我正在测试我的最新版本,完全最大化的Macbook Pro。切换到我的桌面,我并不总是得到> 0.9ms。