1、如果该记录在数据库表(user)的第一条。在oracle中是不是就不会再去查询下面的记录?还是把表中的所有记录加载到缓存中再进行过滤? 答: 因为没有索引, Oracle 不知道 满足 username='test' 条件的, 总共有多少个, 所以全表还是要继续的。 2、如果username这个字段有索引的话,情况又是什么样子? 如果是 RBO(基于规则的优化), 那么自动强制使用索引。 也就是先去索引那里找, 有哪些索引记录是 username='test' 的。 通过这些索引的 信息,拿到相关的 行的 物理位置的ID。 然后再通过这些 行的物理位置的ID, 去表里面,提取出相应的行。返回。 如果是 CBO(基于成本的优化),那么首先分析,索引有没有使用的价值。 例如一百万条记录里面, 只有10个 username='test' 的记录,那么Oracle 将使用这个索引。(使用索引的操作步骤,同RBO) 假如一百万条记录里面,有50万条记录的username='test' 的记录,那么Oracle 发现使用索引,产生的工作量,比全表扫描还慢,因为要读取50W条索引,+50W条记录。于是就会选择直接全表扫描,不使用索引。
-
追问
-
全表扫描是在数据库文件中进行的吗,还是加载到某个地方进行的? 如果存在索引,默认是RBO还是CBO,又如何进行设置?
-
回答
-
全表扫描, 看你那个表有多大 表如果小的话, 可能上次检索过, 还在内存缓冲区域里面的话, 可能文件都不需要读取. 如果缓存里面没有,那么就去读取物理文件. 表如果很大的话, 那么缓存里面肯定是不够的,那就必须去读取物理文件了. Oracle 9的时候,(Oracle 10 / 11 没仔细测试过) 默认是使用 RBO, 也就是默认使用 基于规则的优化。 假如你对表进行了分析。 例如下面这一类型的语句 analyze table user compute statistics 那么,当 SELECT * FROM user WHERE username='test' 的时候。 Oracle 会检测到 user 表上面,有统计信息。 这种情况下, Oracle 将自动切换到 使用 CBO 的优化策略。 当然了,使用 CBO,就是要周期的更新统计信息。 否则会出现 统计信息 与 实际信息不匹配的情况。 例如 统计信息里面,可能记录着,这个表有100W条记录,username='test' 的记录只有10条 但是可能经过多次 INSERT/UPDATE后,username='test' 的记录已经有 20W条了。 但是统计信息里面,还是只有10条。 那么在查询的时候, Oracle 看到统计信息的数据,就去使用索引了。