我们的表格“客户”包含电子邮件和siteId列。并且有一个由这两列组成的索引。因此,相关查询在执行查询和通过电子邮件过滤时始终使用此索引,如下所示:
select * from customers where email = 'someEmail@gmail.com';
我们可以确保使用索引,因为我们已经使用解释计划检查了查询。现在,我们昨天有一个有趣的案例。带有子句“email ='random@gmail.com'的相同查询根本没有使用索引。解释计划显示oracle进行了全扫描。该表包含数百万条记录,因此这个没有索引的查询达到了30秒。有趣的部分是查询确实使用索引与任何其他电子邮件值(ransom@gmail.com,randon @ gmail.com)。为什么oracle没有使用索引?
我遇到的一个原因是索引不包含这样的值,所以首先oracle遍历索引然后进行全扫描,但是解释计划应该显示它执行了索引扫描。在我们的案例中,解释计划只显示完整扫描。另一个原因是它与db恢复有某种关系,但也不确定该索引是如何包含这样的值的。
更新恢复后的所有表格,其last_analyzed日期值为一周。在电子邮件的这种特殊情况下,由于更新后的客户隐私,所有电子邮件都会更新为一些随机值。客户表有几百万条记录,所以是的,恢复后有一个非常大的变化,但仍然不明白它与不使用电子邮件有什么关系,因为这个客户表在恢复之前已经拥有数百万条记录。
UPDATE2 在我们对表格收集统计信息后使用索引。
UDATE3 以及所有电子邮件值在客户表中都是唯一的,因此CBO不太可能决定使用此类特定电子邮件的行太多。只是有很多电子邮件具有相同的起始字符“随机......”但不应该被视为相同的值,对吧?
答案 0 :(得分:2)
服务器不会查看索引中的数据,如果找不到则会扫描表。在它执行任何操作之前,它将查看统计信息以查看它是否应使用索引或扫描表。我猜想,由于某种原因,通过电子邮件地址使得oracle认为扫描表比查看索引更好。有太多因素可以得出确切的结论。查看有关统计信息Oracle Doc on Stats的此信息。您可能会考虑更改索引统计信息所涵盖的数据量,这将有所帮助。
答案 1 :(得分:0)
直方图仅考虑第一个 32个字节。相同的起始字符有多大?有关详细信息,请参阅this Oracle Optimizer post。
将唯一字符移动到字符串的开头或禁用直方图,如下所示:
begin
dbms_stats.set_table_prefs
(
'<schema>',
'CUSTOMERS',
'METHOD_OPT',
'FOR ALL COLUMNS SIZE AUTO, FOR COLUMNS SIZE 1 EMAIL'
);
end;
/