如前所述,索引是加快查询速度的强大工具。然而,索引的顺序非常重要。
按 (ExamEntry) 然后 (Student_ID) 然后 (Grade) 顺序排列的索引对于查找学生通过的考试几乎没有用处。
如果您只想查找已通过哪些考试,则相反顺序的索引将非常适合。这将使查询引擎能够快速识别已通过考试的行,并对其进行处理。
在 MS SQL Server 中,这可以通过...完成...
CREATE INDEX [IX_results] ON [dbo].[results]
(
[Grade],
[Student_ID],
[ExamEntry]
)
ON [PRIMARY]
(我建议阅读更多关于索引的内容,看看还有哪些其他选项,例如 ClusterdIndexes 等)
使用该索引,以下查询将能够非常快速地忽略“失败”的考试,而只显示曾经通过考试的学生...
(这假设如果您超过 60 岁,即使您随后再次参加考试并获得 27 岁,也将被视为及格。)
SELECT
Student_ID
FROM
[results]
WHERE
Grade >= 60
GROUP BY
Student_ID
如果您确实需要最近的值,那么您需要将索引的顺序改回类似...
CREATE INDEX [IX_results] ON [dbo].[results]
(
[Student_ID],
[ExamEntry],
[Grade]
)
ON [PRIMARY]
这是因为我们首先感兴趣的是任何给定学生的最新考试条目。可以使用以下查询来实现...
SELECT
*
FROM
[results]
WHERE
[results].ExamEntry = (
SELECT
MAX([student_results].ExamEntry)
FROM
[results] AS [student_results]
WHERE
[student_results].Student_ID = [results].student_id
)
AND [results].Grade > 60
这样的子查询可能看起来很慢,尤其是因为它似乎是为 [results] 中的每一行执行的。
然而,事实并非如此......
- 主查询和子查询都引用同一个表
- 查询引擎通过索引扫描每个唯一的 Student_ID
- 为那个 Student_ID
执行子查询
- 查询引擎已经在索引的那部分
- 所以不需要新的索引查找
编辑:
有评论指出,在 1000 条记录中,索引不相关。需要注意的是,问题说明有 1000 条记录返回,而不是表包含 1000 条记录。对于一个基本查询,只要声明的时间,我敢打赌表中有超过 1000 条记录。也许这可以澄清?
编辑:
我刚刚调查了 3 个查询,每个查询有 999 条记录(333 名学生每人 3 个考试结果)
方法 1:WHERE a.ExamEntry = (SELECT MAX(b.ExamEntry) FROM results [a] WHERE a.Student_ID = b.student_id)
方法 2:WHERE a.ExamEntry IN (SELECT MAX(ExamEntry) FROM resuls GROUP BY Student_ID)
方法 3:使用 INNER JOIN 代替 IN 子句
找到了以下时间:
Method QueryCost(No Index) QueryCost(WithIndex)
1 23% 9%
2 38% 46%
3 38% 46%
因此,无论索引如何,查询 1 都更快,但索引也肯定会使方法 1 大大加快。
这样做的原因是索引允许查找,否则您需要扫描。线性定律和平方定律的区别。