我在学习索引概念时感到困惑,
代表:我有这个简单的查询
select productId,productName from product where productId='11107' and productName='Watch';
和产品是非常大的表,productId和productName是产品表的两个属性,11107和Watch是两个值。
我认为productId上的主索引和productName上的二级索引假设1000条记录满足条件
productId ='11107',50条记录满足条件productName ='Watch',每个数据页可存储100条记录
并且随机IO的成本是顺序I / O的10倍。
现在使用两个索引中的哪一个来评估此查询?
溶液:
根据我的理解,它应该是主索引,因为主索引属性“productId”返回多个记录,例如1000, 与seconday索引属性“productName”相比,后者只返回50条记录。
同样,每个数据页面存储100条记录,然后对于主索引,我们需要10页,而二级索引1页。
由于表“”产品“非常大,因此只有较少的记录表示50满足顺序访问的条件(记录一次扫描一次)。
我的评价是正确的,或者需要添加任何内容。有什么建议。
答案 0 :(得分:0)
在评估Oracle的最佳执行计划时,会考虑很多事情。
来自dba_indexes视图的统计信息
LEAF_BLOCKS
DISTINCT_KEYS
clustering_factor的
NUM_ROWS
例如,对于相同条件,Oracle为DISTINCT_KEYS更接近NUM_ROWS的索引提供更低的成本
在您的情况下,假设两者都是正常索引并且所有统计信息都是当前索引 - 具有更多不同密钥的索引可能优先于另一个。
答案 1 :(得分:0)
如果我理解正确,那么您的基本逻辑似乎是倒退的。您似乎在说主要索引将被使用,因为它将返回更多行,这与基本经验法则相反 - 通常更喜欢选择性指数。
但是,你的逻辑中存在另一个潜在的缺陷:
因为每个数据页面存储100条记录,然后对于主索引,我们需要10条记录 页面和二级索引1页
你应该说"在10到1000之间"和"介于1到50"之间。仅仅因为 n 记录可以放入单个"数据页" (或在Oracle术语中阻止)并不意味着您要查找的任何 n 记录实际上都在同一个块中。在您的示例中,10个块是最小容纳1000行;但是给定productId的1000行可能实际上是1000个不同的块。 (假设该表的大小至少为1000个块。)
问题并不在于每个索引将返回多少行("行选择性"),而是有多少个块这些行是in("块选择性)。优化器使用每个索引的CLUSTERING_FACTOR值来估计行和块选择性彼此匹配的程度;低聚类因子通常意味着更好的块选择性。
超出了你的问题的范围,优化器也完全有可能既不使用索引,也不使用两者。
在某些时候,扫描索引(也需要I / O)然后读取相应的表块所需的工作量可能超过简单读取整个表所需的工作量。同样,CLUSTERING_FACTOR和其他统计数据也会影响这一决定。
在某些情况下,包括您的示例,优化程序也可能选择对两个索引执行扫描,并通过ROWID值连接生成的索引条目,而根本不访问表块。这是可能的,因为查询仅使用索引中的列;如果您在选择列表中添加了另一列,则查询必须读取表块以获取该数据。