【发布时间】:2014-01-29 15:08:56
【问题描述】:
我们有包含 email 和 siteId 列的“Customers”表。并且有一个由这两列组成的索引。因此,在通过电子邮件执行查询和过滤时,相关查询总是使用此索引,例如:
select * from customers where email = 'someEmail@gmail.com';
我们可以确保使用了索引,因为我们已经使用解释计划检查了查询。现在,我们昨天有一个有趣的案例。带有子句“email = 'random@gmail.com'”的相同查询根本没有使用索引。解释计划显示 oracle 进行了全面扫描。该表包含数百万条记录,因此这个没有索引的查询达到 30 秒。有趣的部分查询是否将索引与任何其他电子邮件值一起使用(ransom@gmail.com、randon@gmail.com)。oracle 不使用索引的原因是什么?
我的一个原因是索引不包含这样的值,所以首先 oracle 遍历索引然后进行全扫描,但随后解释计划应该显示它执行了索引扫描。在我们的例子中,解释计划只显示完整扫描。另一个原因是它与 db restore 有某种关系,但也不确定索引怎么可能不包含这样的值。
UPDATE 恢复后的所有表的 last_analyzed 日期值为一周前。在电子邮件的这种特殊情况下,由于客户隐私,所有电子邮件在更新后都会更新为一些随机值。客户表有几百万条记录,所以是的,恢复后发生了相当大的变化,但仍然不明白它与不使用电子邮件有什么关系,因为这个客户表在恢复之前已经有数百万条记录。
UPDATE2在我们对表执行收集统计信息后使用索引。
UDATE3 好吧,客户表中的所有电子邮件值都是唯一的,因此 CBO 不太可能决定此类特定电子邮件的行数过多。只是有很多电子邮件具有相同的起始字符“随机...”,但这不应该被视为相同的值,对吧?
【问题讨论】:
-
表是否包含频繁的插入和删除?
-
如果没有找到索引命中就不会进行全扫描;它会做一个或另一个,而不是两者兼而有之。 (它是进行全索引扫描还是全表扫描?)假设您的统计数据是最新的,索引是否有直方图,并且您是否有很多与行为不同的地址相似的地址?
-
我同意 Alex 的观点,这可能是由于特定电子邮件 ID 的基数很高,Oracle 将进行全表扫描。
-
是在电子邮件更新为随机值之前最后一次收集的统计信息吗?如果是这样,最初可能有很多相似(或相同)的值,而您的更新/随机值恰好与流行的原始选择一致。如果收集统计数据解决了它,那就太好了*8-)