Oracle SQL:使用非唯一索引返回的子集中的行是否也可以使用第二个非唯一索引进行查询?

Oracle SQL:使用非唯一索引返回的子集中的行是否也可以使用第二个非唯一索引进行查询?,sql,oracle,indexing,Sql,Oracle,Indexing,对不起,如果标题混淆,我发现很难清楚地表达我的问题 以下是我的设想: 我有一个名为SUBSCRIBERS的表,它有两个非唯一索引。索引的列是区域ID和订阅日期 现在,我想(高效地)查询特定区域中在给定日期之后订阅的所有订户。SQL示例: SELECT * FROM subscribers WHERE area_id = 'areaID' AND subscription_date > to_date(some_date) 假设要执行这个查询,Oracle首先获取所有具有给定areaID的

对不起,如果标题混淆,我发现很难清楚地表达我的问题

以下是我的设想: 我有一个名为SUBSCRIBERS的表,它有两个非唯一索引。索引的列是区域ID和订阅日期

现在,我想(高效地)查询特定区域中在给定日期之后订阅的所有订户。SQL示例:

SELECT *
FROM subscribers
WHERE area_id = 'areaID'
AND subscription_date > to_date(some_date)
假设要执行这个查询,Oracle首先获取所有具有给定areaID的行,假设这仍然是非常多的行。Oracle是否能够在订阅日期之前对该行子集进行范围扫描?或者非唯一的subscription_date索引是否只适用于完整表,这意味着Oracle必须对子集进行线性扫描


另外,我不确定用什么技术术语来描述集合上的索引,它也适用于子集。如果有人知道正确的术语,这将是一个很酷的奖励。

根据Oracle版本的不同,这两个索引都可以使用。但是,为了做到这一点,Oracle必须将两个b树索引转换为位图索引,并在这两个索引上进行位图合并。这不是一个特别有效的操作,因此它通常不是您想要的查询计划

Oracle b树索引通过将键和ROWID存储在键所在的表中来工作。为了组合索引,Oracle首先将它们转换为位图索引,位图索引本质上是一个二维数组,用于指示哪一行符合哪一标准。然后,它可以相对轻松地组合两个位图索引。此操作的复杂性在于将b树索引初始转换为位图索引。原则上,没有什么可以阻止Oracle实现一个查询计划,该计划从两个索引中获取所有rowid,并执行两个集合的交集。但是,我假设位图转换路径通常更有效,因为Oracle就是这样实现的

乔纳森·刘易斯(Jonathan Lewis)在其著作《基于成本的甲骨文基础知识》(Cost-Based Oracle Fundamentals)中有一节介绍了甲骨文


几乎可以肯定,在(
AREA\u ID
SUBSCRIPTION\u DATE
)上有一个综合索引会更有效。这将允许您对单个复合索引执行索引范围扫描。在
AREA\u ID
上有谓词的查询将能够使用此复合索引,因此
AREA\u ID
上的索引通常是多余的

根据Oracle版本的不同,两个索引都可以使用。但是,为了做到这一点,Oracle必须将两个b树索引转换为位图索引,并在这两个索引上进行位图合并。这不是一个特别有效的操作,因此它通常不是您想要的查询计划

Oracle b树索引通过将键和ROWID存储在键所在的表中来工作。为了组合索引,Oracle首先将它们转换为位图索引,位图索引本质上是一个二维数组,用于指示哪一行符合哪一标准。然后,它可以相对轻松地组合两个位图索引。此操作的复杂性在于将b树索引初始转换为位图索引。原则上,没有什么可以阻止Oracle实现一个查询计划,该计划从两个索引中获取所有rowid,并执行两个集合的交集。但是,我假设位图转换路径通常更有效,因为Oracle就是这样实现的

乔纳森·刘易斯(Jonathan Lewis)在其著作《基于成本的甲骨文基础知识》(Cost-Based Oracle Fundamentals)中有一节介绍了甲骨文


几乎可以肯定,在(
AREA\u ID
SUBSCRIPTION\u DATE
)上有一个综合索引会更有效。这将允许您对单个复合索引执行索引范围扫描。在
AREA\u ID
上有谓词的查询将能够使用此复合索引,因此
AREA\u ID
上的索引通常是多余的

为了完整起见,我想发布来自Markus Winand网站的摘录,这直观地解释了为什么查询引擎不能同时使用多个不同的b树索引:

…一条只有一个轴的链条 支持一个范围条件作为访问谓词。支持两个 作为访问谓词的范围条件意味着扫描 棋盘。然而,B树索引是一个没有第二个索引的链 轴心国

资料来源:

和有用的图表:

换句话说,b-树索引仅基于一个数据字段构造排序树。索引的节点是n元组,但索引的条目是1元组

似乎要用第二个b-tree索引查询一个b-tree索引返回的子集,第一个b-tree索引的条目需要另外存储对第二个b-tree索引中每行位置的引用。但是,我不确定这是否可行,因为b树索引是基于值而不是位置进行检索的——它们不是数据结构


乍一看,我不确定这会带来多大的复杂性,但我敢肯定,如果有多个索引,这将是一场噩梦。您需要一种机制来添加额外的索引位置引用(每个额外的索引都会将索引中的条目从n元组转换为(n+1)-元组),您需要一种机制来对其他索引应用过滤器以跳过未引用的位置,您需要一种机制来在表上执行创建/更新/删除操作时同步索引间的引用。

为了完整起见,我想发布来自Markus Winand网站的这篇摘录,它直观地解释了为什么查询引擎不能同时使用多个不同的b树索引:

…一条只有一个轴的链条 支持一个范围条件作为访问谓词。苏