正如您所看到的,Oracle可以利用两个索引来解决整个查询而无需通过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;
我做了一个测试,将campo47字段添加到STATO索引中。性能从1 '49'上升到0,6s。
stato的索引不是选择性的。 campo47上的索引(表示field47)非常具有选择性。
答案 0 :(得分:7)
你说CAMPO47是高度选择性的。但是你只是在IS NOT NULL上过滤。因此,它具有多少不同的值并不重要,优化器不会将其用作入口点。
它的选择性如何?从解释计划中的基数可以看出,选择STATO ='SC'会在表中找到12856行。这些行中有12702个明显具有CAMPO47值,因此只有154行被无效测试过滤掉。如果优化器已经为CAMPO47上的索引进行了操作,那么返回的行数是多少?可能还有很多。
优化器只能使用一个堆索引来访问表上的行。 (当应用星形转换时,位图索引的机制不同)。因此,如果您认为额外的表访问是一个令人难以忍受的负担,那么您有一个选项:复合索引。如果STATO真的是非选择性的(相对较少的行),那么你可以安全地用一个on(STATO,CAMPO47)替换现有的索引。
有一个老技巧,用于将数据库轻推使用索引来访问IS NOT NULL操作,这就是使用一个操作数,只有在列包含值时才能为true。例如,对于字符串列这样的东西(我假设一个名为CAMPO47的东西只是一个字符串):
AND campo47 >= chr(0)
这将匹配包含一个或多个ascii字符的任何列。不确定它是否会导致您描述的“两个索引”优化,但它值得一试。 (我会自己测试一下,但我现在无法访问Oracle数据库,当我试图查看解释计划时,SQL Fiddle投掷了)