现在假设我执行一个查询,如SELECT * FROM soMetable WHERE foo =’hello’AND bar =’world’;我的桌子有很多行,其中foo是“hello”,少量的行是“世界”.
因此,数据库服务器在引擎盖下最有效的方法是使用bar索引来查找bar是“world”的所有字段,然后只返回foo为“hello”的那些行.这是O(n)其中n是bar是“world”的行数.
但是,我想象的是,这个过程可能会发生在相反的情况下,使用了fo索引并搜索结果.这将是O(m)其中m是foo是“hello”的行数.
那么Oracle智能足以在这里高效搜索?其他数据库呢?还是有一些我可以在我的查询中告诉我要按正确的顺序搜索?也许把WHERE子句中的bar =’world’放在第一位?
解决方法
此外,Oracle可以通过几种方式组合使用两个索引 – 它可以将btree索引转换为位图,并对其执行位图ANd操作,也可以对两个索引返回的rowid执行散列连接.
这里的一个重要考虑可能是被查询的值之间的任何相关性.如果foo =’hello’占表中的80%的值,并且bar =’world’占10%,那么Oracle将会估计该查询将返回0.8 * 0.1 = 8%的表行.但是这可能不正确 – 查询可能实际上返回rwos的10%甚至0%的行,具体取决于值的相关性.现在,根据整个表中这些行的分布情况,使用索引找到它们可能并不有效.您可能仍然需要访问(例如)70%或表块来检索所需的行(“for”集群因子“),在这种情况下,如果得到正确的估计,Oracle将执行完整的表扫描.
在11g你可以收集多列统计数据,以帮助我相信这种情况.在9i和10g中,您可以使用动态采样来获取要检索的行数的非常好的估计.
要得到执行计划,请执行以下操作:
explain plan for SELECT * FROM soMetable WHERE foo='hello' AND bar='world' / select * from table(dbms_xplan.display) /
对比:
explain plan for SELECT /*+ dynamic_sampling(4) */ * FROM soMetable WHERE foo='hello' AND bar='world' / select * from table(dbms_xplan.display) /