SELECT * FROM table WHERE A BETWEEN 3 AND 7 AND B = 10
(A,B)是复合索引, 数据库首先找到 A 在 3 到 7 之间的所有记录,然后对于每个 A 的值,再检查 B 是否等于 10。 在范围查询的情况下,数据库需要扫描 A 的多个值,对于每个 A 的值,再去检查 B。这意味着数据库不能直接利用索引来精确定位 B 的值,而是需要对每个 A 的值进行额外的检查。这会导致索引扫描的效率降低 问: 为什么索引B不能像在A的结果里进行索引精确查找呢
在复合索引 (A, B)
中,索引的结构是按照 (A, B)
的顺序进行组织的。这意味着索引首先按照列 A
排序,然后在每个 A
的值范围内,再按照列 B
排序。因此,当你进行查询 SELECT * FROM table WHERE A BETWEEN 3 AND 7 AND B = 10
时,数据库的处理过程如下:
找到 A 在 3 到 7 之间的所有记录:由于索引是按照 A
排序的,数据库可以高效地找到 A
在 3 到 7 之间的所有记录。这一步利用了索引的排序特性,可以快速定位到 A
的范围。
检查 B 是否等于 10:在找到 A
的范围之后,数据库需���检查每个记录的 B
值是否等于 10。虽然在每个 A
的值范围内,B
是有序的,但由于 A
的范围查询可能会返回多个不同的 A
值,数据库需要对每个 A
的值进行检查。
问题的关键在于,复合索引 (A, B)
的排序是基于 (A, B)
的组合键,而不是单独的 B
。当你进行范围查询 A BETWEEN 3 AND 7
时,数据库会找到多个 A
的值范围。在这些范围内,B
的值是有序的,但数据库不能直接跳到 B = 10
的位置,因为它需要先确定 A
的值范围。
具体来说,假设索引结构如下:
(A, B)
(3, 5)
(3, 10)
(3, 15)
(4, 10)
(5, 10)
(6, 8)
(6, 10)
(7, 10)
对于查询 A BETWEEN 3 AND 7 AND B = 10
,数据库会执行以下步骤:
找到 A
在 3 到 7 之间的所有记录:
(3, 5)
(3, 10)
(3, 15)
(4, 10)
(5, 10)
(6, 8)
(6, 10)
(7, 10)
对每个 A
的值范围内,检查 B
是否等于 10:
(3, 10)
(4, 10)
(5, 10)
(6, 10)
(7, 10)
虽然 B
在每个 A
的值范围内是有序的,但数据库需要逐个检查每个 A
的值范围内的 B
,因为它不能直接跳到 B = 10
的位置。
如果你希望在这种情况下提高查询效率,可以考虑以下几种方法:
B
创建单独的索引,这样在检查 B
的值时可以更高效。A
值范围,减少需要检查的记录数量。总之,复合索引 (A, B)
的排序方式决定了在范围查询 A
时,数据库需要对每个 A
的值范围内的 B
进行检查,而不能直接跳到 B = 10
的位置。