SQL 性能解析:SQL慢索引 -1
接上篇
尽管有树遍历的效率,还是存在索引搜索不如预期那样快的情况。长期以来,这种矛盾助长了“未生成索引”的神话。这个神话将重建索引作为神奇的解决方案。<神话篇>对这一神话和其他神话做了更详细的描述。目前,您可以理所当然地认为,从长远来看,重建索引并不能提高性能。即使在使用索引时,琐碎语句也可能很慢的真正原因可以在前面的部分的基础上解释。
慢索引查询的第一个原因是叶节点链。假设在图 1.3 中再次搜索 57。很明显在索引中有两条匹配。至少有两个条目是相同的,更准确的是:下一叶几点可能有更多”57“的条目。数据库必须读取下一个叶节点去看是否有更多匹配的条目。也就是说一次索引查询不只需要树遍历,还需要遍历叶节点的链条。
慢索引查询的第二个因素是访问表。即使是单个叶节点都可能包含多个命中 — 通常上百。对应的表数据通常分散在许多表块中(参考图 1.1,”索引叶节点及对应的表数据“)。这意味着每个命中都有额外的表访问。
索引搜索需要 3 个步骤:(1)树遍历;(2)遍历着树节点链;(3)获取表数据。树遍历是唯一一个对访问的块数和索引深度有上限的步骤。另外两个步骤可能需要访问许多块,这会导致索引查找缓慢。
”慢索引“神话起源于对索引查询只是树遍历的误解,因此觉得慢查询只是因为树被”破坏“或”不平衡“导致。事实上,你需要了解大多数数据库是如何使用索引。Oracle 数据库在这方面相当冗长,有三个不同的操作来描述基本的索引查找:
INDEX UNIQUE SCAN(索引唯一性扫描)
索引唯一性扫描只执行树搜索。Oracle 数据库在有一个 unique 约束保证搜索条件最多匹配一个条目时,执行这一操作
INDEX RANGE SCAN(索引范围查询)
索引范围扫描执行树遍历以及并进入叶节点链遍历,以查找所有匹配的条目。如果多个条目可能匹配搜索条件的话,这就是一个回退操作。
TABLE ACCESS BY INDEX ROWID(通过索引 ROWID 访问表)
这一操作从表中检索数据。通常是从之前的索引扫描操作中执行获取所有匹配的记录。
重点是,索引范围扫描有潜在的可能需要读取很大一部分索引。如果有多次表访问,即使用了索引,查询也可能变慢。