我曾被一家顶级公司问过以下问题,但我无法回答。
刚刚回复:我需要就这个话题更新自己
经过我的研究,我陷入了这一点:
Index Skip Scan
Composite indexing
和Index Skip Scan
有什么关系
为了让我困惑,有人问?以下问题的任何解决方案非常感谢?
问题:
如果您在 3 列( eid 、 ename 、 esal )上创建复合索引?
如果我在where子句后只提到eid=10,索引会被调用吗?
select * from emp where eid=10
;
如果我只提到 eid=10 和 ename='Raj' 是否会调用索引?
select * from emp where eid=10 and ename='Raj';
如果我以不同的顺序提及,例如 esal=1000 和 eid=10 是否会调用索引?
select * from emp where esal=1000 and eid=10;
如果我以相反的顺序提及,例如 esal = 1000 和 ename = 'Raj' 和 eid = 10 ,索引会被调用吗?
select * from emp where esal=1000 and enam='Raj' and eid=10;
需要一个带有详细表格表示和数据的解决方案吗?
将为您提供的出色解决方案点赞
在您提出的所有四种情况下,Oracle 都会在前导列上执行正常的索引查找(二叉树搜索)
eid
,因为在您的每种情况下都为此列提供了相等谓词。但它对索引的其他作用取决于您要过滤的其他列:
eid
:Oracle 将从第一个 eid=10
条目开始扫描叶块,并使用链表遍历每个块(单个块读取),直到找到第一个不为 10 的 eid
值。这样做时,它会收集包含表段物理行地址的 ROWID,并通过 ROWID 发出单块读取来获取该行的其余部分。
eid
和ename
:因为ename
是索引中的第二列,Oracle在执行二分搜索(seek)时会同时使用eid
和ename
来查找第一个叶子块条目,其中 eid=10
和 ename='raj'
。然后它将像上面一样扫描叶子块,直到找到这些列具有不同值的第一行。
eid
和 esal
:因为 esal
是第三 列,并且您要跳过第二列,Oracle 无法对 esal
使用单个二分搜索/查找操作。它有两个选择:
3a。它仅在前导列
eid
上进行二分搜索/查找,但一旦找到叶块中的第一个 eid=10
值,它将对该链表后面的叶块进行正常扫描 - 浏览 all eid=10
行,但抓住 ROWID
仅适用于具有 esal=1000
的人。
3b。或者,它执行跳跃扫描:对于缺失的中间列(
ename
)的每个不同值,它将对组合的eid=10 / esal=1000
值进行单独的二分搜索/查找。这是一次查找而不是扫描,但它可能是多次查找。如果有很多 ename
值,则会导致大量不必要的单块 I/O,并且性能可能会很差。但如果只有几个值,它的效果就很好。
您的最后一个示例将对所有三列进行一次二分搜索/查找。
您没有提供此示例,而是为了完成研究:
如果您仅查询
esal=1000
,Oracle 可以执行以下操作之一:
5a。忘记索引并扫描表本身(最有可能)
5b。对索引的 100% 叶块进行完整扫描(分散读取)
5c。进行跳跃扫描,这意味着对前面未过滤列(
esal=1000
和 eid
)的每个不同组合进行二分搜索/查找 ename
。这将需要大量的搜索,因此优化器不太可能选择它。
每当 Oracle 有选择时,这一切都取决于每个操作的统计数据和预期基数,这在很大程度上是由每列已知的最小/最大和 # 不同值以及整个表行计数驱动的。当然,如果您认为您比统计数据更了解,您可以通过提示来强制它,但建议不要进行提示,直到您充分掌握 Oracle 查询的内部工作方式,因为您可以轻松地告诉它执行以下操作:错误的事情。