我有一个如下表:
student_score
id int
student_id int
score int
type int
is_repeat boolean
created_at int
假设我想获取类型<10的学生的最新考试成绩,并且is_repeat等于false,所以我有这样的观点:
CREATE VIEW view_latest_student_score
AS
SELECT
s1.*
FROM student_score s1
LEFT JOIN student_score s2
ON s1.student_id = s2.student_id
AND s2.type < 10
AND s2.is_repeat = FALSE
AND s1.id < s2.id
WHERE s1.type < 10
AND s1.is_repeat = FALSE
AND s2.id IS NULL;
那么如何为这种视图创建索引?目前,我在student_id
上有索引(id
是pk)。这种自我加入是否有一些最佳实践?
有时,我将使用列分数或类型查询类似此视图的视图。那么我应该添加诸如(student_id,score)或(score,student_id)的索引吗?
答案 0 :(得分:0)
在is_repeat + type
上创建多列索引(列的顺序很重要)。
可以使用它来满足针对s
表的这一条件,以使用索引范围扫描过滤掉某些行:
WHERE s1.type < 10
AND s1.is_repeat = FALSE
(可能被使用-但不一定必须使用-它取决于查询的选择性,当WHERE条件选择的值大于5时,数据库可能更喜欢全表扫描而不是使用此索引表中约10%的行):
为此联接条件在student_id
列上也创建第二个索引:
ON s1.student_id = s2.student_id
AND s2.type < 10
AND s2.is_repeat = FALSE
AND s1.id < s2.id
对于这种情况,您也可以考虑在以下位置创建student_id + is_repeat + type
(按此列的特定顺序)上的多列索引,但是我猜测student_id
上的索引就足够了。
答案 1 :(得分:0)
由于只处理类型<10并且is_repeat = FALSE的行,因此部分索引就足够了。 (在部分索引中,WHERE条件可以将索引行限制为类型<10并且is_repeat = FALSE的那些行,因此优化程序不需要查找这些行)。
CREATE INDEX idx_test ON student_score
(student_id, score, type, is_repeat, created_at)
WHERE TYPE < 10 AND is_repeat = FALSE