3

As you can see Oracle could exploit two indexes and solve the entire query without accessing the table by rowid?

SELECT  'Scarti letture GAS' tipo, campo47 pdf, COUNT (1) n
  FROM out.CONSUMI_GEE_LC_T500_00 v
  WHERE stato = 'SC'
  AND stato is not null
  AND campo47 is not null
  GROUP BY 'Scarti letture GAS', campo47;

I've made a test adding the field campo47 to the STATO index. Performance boosts from 1' 49'' to 0,6s.

Index on stato is not selective. Index on campo47 (it means field47) is really selective.

enter image description here

enter image description here

enter image description here

4

1 回答 1

7

你说 CAMPO47 是高度选择性的。但是您只过滤 IS NOT NULL。所以不管它有多少不同的值,优化器都不会使用它作为入口点。

它的选择性如何?从解释计划中的基数可以看出,选择 STATO='SC' 会在表中找到 12856 行。这些行中有 12702 行明显具有带有值的 CAMPO47,因此只有 154 行被空值测试过滤掉。如果优化器已经为 CAMPO47 上的索引增加了多少行,那将返回多少行?可能还有很多。

优化器只能使用一个堆索引来访问表中的行。(当它们应用星形变换时,位图索引的机制是不同的)。因此,如果您认为额外的表访问是难以忍受的负担,那么您有一个选择:复合索引。如果 STATO 确实是非选择性的(相对较少的行),那么您可以安全地将现有索引替换为一个 on (STATO, CAMPO47)。


有一个古老的技巧可以推动数据库使用索引来访问 IS NOT NULL 操作,那就是使用一个操作数,该操作数只能在列包含值的情况下为真。例如,对于字符串列是这样的(我假设一个叫做 CAMPO47 的东西只是一个字符串):

AND campo47 >= chr(0)

这将匹配任何包含一个或多个 ascii 字符的列。不确定它是否会导致您描述的“双索引”优化,但值得一试。(我自己会对此进行测试,但我现在无法访问 Oracle 数据库,当我试图查看解释计划时,SQL Fiddle 猛烈抨击)

于 2012-04-04T08:59:56.120 回答