本文翻译自Coding-Geek文章:《 How does a relational database work》。原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies
本文翻译了如下章节, 介绍数据库查询优化器的数据访问方式:
Access Path–数据访问方法
在执行联表操作之前先要获取数据。现在讲一下获取数据有哪些方式。
Note:由于所有获取数据方式的关键都是磁盘I/O,所以我不会在这讨论时间复杂度的问题。
Full scan–全表扫描
如果你曾经阅读过介绍SQL执行方案的文档,你一定已知道full scan这个概念。
full scan是数据库将整张表的数据或者索引读取到内存。从磁盘I/O消耗来说,
全表数据扫描的成本明显比全表索引扫描要高很多。
Range Scan –区段扫描
还有其它的一些扫描方式,如:索引区段扫描。它用在数值范围做查询条件的时候(例如:WHERE AGE > 20 AND AGE <40)。当然,你必须得为AGE字段建立了索引才能使用索引区段扫描。
我们已在第一章讲了,区间查询的时间复杂度是log(N) +M,其中N是建立索引的数据条数,M是区间内的数据条数。M和N的值已经在数据特征统计时计算出来了(Note:M是条件断言AGE >20 AND AGE<40的可选元素)。对于区段扫描你甚者不需要读取全部的索引数据,因此它的磁盘I/O成本比全表数据扫描小得多。
Unique scan–唯一值扫描
当你仅需要查询指定索引的单条记录,你可以使用唯一值扫描。
Access by row id–根据行ID获取(数据)
大多数情况,如果数据库建立了索引,它将查询与索引关联的行记录,它将使用行ID去获取数据。
例如下面的SQL语句:
如果你已对person表的age字段建了索引,优化器将使用索引找到所有age是28(的行ID),然后从表中查询出对应的行数据记录。索引仅包含了age信息,你需要的是lastname和firstname,这些需要从原表中去拿。
但是,如果你执行下面的SQL:
SELECT TYPE_PERSON.CATEGORY from PERSON ,TYPE_PERSON WHERE PERSON.AGE = TYPE_PERSON.AGE
PERSON表的索引将用于与TYPE_PERSON表做关联,但不会用row id去查询数据,因为不需要查PERSON表中的其它信息。
在需要查询少量数据的时候没什么问题。关键的瓶颈在磁盘I/O,如果你需要根据row id查询太多数据,数据库可能会使用全表数据扫描(代替)。
Others paths–其它方法
我并未介绍所有的数据获取方式。你想了解更多可以阅读oracle官方文档。
上面讲的获取方式名称,在不同的数据库中可能有不同的叫法,但是背后的含义是一致的。