好的,在过去 6 年转向 MongoDB 之前,我使用 MySQL/postgres 多年,现在我正在画一些空白。我一直在寻找执行此操作的最佳方法,使用我非常简单的数据集,查询时间平均为 20 毫秒。 < 100 行似乎很疯狂。我可能以 super 复杂的方式做到了这一点 :)
因此这里的想法是获取用户有权访问的类(class)列表,以及他们的最新测验分数和最新类(class)进度(他们在类(class)中完成了多少)。
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 重写。性能下降到平均 15 毫秒。它看起来确实干净多了,但我仍然觉得对于这么少的数据来说它太高了。
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
最佳答案
GROUP BY 和 DISTINCT 通常实现相同的目标。您确定需要 DISTINCT 吗?如果需要,删除它后它的性能会更好吗?
感谢您提供查询计划。也许时间戳 DESC 列上的索引会有所帮助?似乎大部分时间都花在了排序上。
关于Postgresql 连接多个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47253887/