Sql 如何向以下示例添加索引

Sql 如何向以下示例添加索引,sql,oracle,oracle-sqldeveloper,datagrip,Sql,Oracle,Oracle Sqldeveloper,Datagrip,我的问题是: SELECT UNIT_PRICE FROM ORDER_DETAIL WHERE QUANTITY IN (100, 200, 300) OR DISCOUNT = 0.01; 在这种情况下,如何正确添加索引?您的查询包含或这就是为什么您无法获得索引范围扫描。 您可以为折扣再创建一个索引并添加提示或扩展,在这种情况下,您将通过2个索引范围扫描或扩展转换获得UNION ALL Oracle 12.2+: 或者,如果您的oracle版本非常旧,您可以使用提示使用_concat: C

我的问题是:

SELECT UNIT_PRICE
FROM ORDER_DETAIL
WHERE QUANTITY IN (100, 200, 300) OR
DISCOUNT = 0.01;

在这种情况下,如何正确添加索引?

您的查询包含或这就是为什么您无法获得索引范围扫描。 您可以为折扣再创建一个索引并添加提示或扩展,在这种情况下,您将通过2个索引范围扫描或扩展转换获得UNION ALL

Oracle 12.2+:

或者,如果您的oracle版本非常旧,您可以使用提示使用_concat:

CREATE INDEX OD_IDX_D ON ORDER_DETAIL(DISCOUNT);

EXPLAIN PLAN FOR 
SELECT/*+ or_expand */ UNIT_PRICE FROM ORDER_DETAIL WHERE QUANTITY IN (100, 200, 300) OR DISCOUNT = 0.01;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- output
Plan hash value: 4033578183
 
----------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                 |     4 |    52 |     5   (0)| 00:00:01 |
|   1 |  VIEW                                  | VW_ORE_1606201E |     4 |    52 |     5   (0)| 00:00:01 |
|   2 |   UNION-ALL                            |                 |       |       |            |          |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED | ORDER_DETAIL    |     1 |    26 |     2   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN                   | OD_IDX_D        |     1 |       |     1   (0)| 00:00:01 |
|   5 |    INLIST ITERATOR                     |                 |       |       |            |          |
|   6 |     TABLE ACCESS BY INDEX ROWID BATCHED| ORDER_DETAIL    |     3 |    90 |     3   (0)| 00:00:01 |
|*  7 |      INDEX RANGE SCAN                  | OD_IDX_QD       |     3 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - access("DISCOUNT"=0.01)
   7 - access("QUANTITY"=100 OR "QUANTITY"=200 OR "QUANTITY"=300)
       filter(LNNVL("DISCOUNT"=0.01))
更新:评论不方便回答您的其他问题,因此我在这里回答:


因为您的查询包含或:

CREATE INDEX OD_IDX_D ON ORDER_DETAIL(DISCOUNT);

EXPLAIN PLAN FOR 
SELECT/*+ use_concat */ UNIT_PRICE 
FROM ORDER_DETAIL OD
WHERE QUANTITY IN (100, 200, 300) OR DISCOUNT = 0.01;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
Plan hash value: 819751077
 
------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |              |     4 |   120 |     5   (0)| 00:00:01 |
|   1 |  CONCATENATION                        |              |       |       |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED | ORDER_DETAIL |     1 |    30 |     2   (0)| 00:00:01 |
|*  3 |    INDEX RANGE SCAN                   | OD_IDX_D     |     1 |       |     1   (0)| 00:00:01 |
|   4 |   INLIST ITERATOR                     |              |       |       |            |          |
|   5 |    TABLE ACCESS BY INDEX ROWID BATCHED| ORDER_DETAIL |     3 |    90 |     3   (0)| 00:00:01 |
|*  6 |     INDEX RANGE SCAN                  | OD_IDX_QD    |     3 |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - access("DISCOUNT"=0.01)
   6 - access("QUANTITY"=100 OR "QUANTITY"=200 OR "QUANTITY"=300)
       filter(LNNVL("DISCOUNT"=0.01))
如果您分析您的查询,您可以发现它与

WHERE QUANTITY IN (100, 200, 300) OR DISCOUNT = 0.01;
联合的第一部分都可以使用您的索引,因为它从该列开始 但不是第二部分,因为您没有为索引的第一列提供范围。在这种情况下,oracle可以使用索引跳过扫描,但在这种情况下无效。
因此,您需要另一个索引。

Hi,根据您成功创建索引的代码段。如果您的问题是为什么在这个特定实例中不使用索引,那么可能是由于许多因素造成的。例如:如果大部分记录都是在select查询中返回的,那么优化器将正确地评估使用索引可能会更昂贵。另一点通常是索引快速查询它取决于许多因素,对象的统计信息,缓存计划,查询的选择性,歪斜的数据等等是的,我的问题是为什么这个索引没有在这个特定的实例中使用。我的表是空的,原因是什么。如果表是空的,则直接导航到表会更容易,而不是使用索引。我以前的索引基于数量和折扣,我不理解如何创建折扣索引。因为您的查询包含或:从订单详细信息中选择单价,其中数量为100、200,300或折扣=0.01`谢谢你,我需要一些时间来完全理解它。将索引分别添加到“数量”和“折扣”中如何。我刚刚在我的帖子中添加了扩展答案,因为评论不允许长答案。>将指数分别添加到“数量”和“折扣”中如何取决于。。。是-如果您没有使用AND:的查询谓词,例如。。。数量=…我以前的指数是基于数量和折扣。。在多个列上创建索引时,索引的选择性是按索引中的列的顺序,而不是分别在每一列上。而且,无论使用何种索引,优化器都可能会很好地判断索引的选择性不足以证明额外的索引读取是正确的,而不是简单地扫描表。
WHERE QUANTITY IN (100, 200, 300) OR DISCOUNT = 0.01;
select UNIT_PRICE 
from (
    SELECT rowid, UNIT_PRICE FROM ORDER_DETAIL WHERE QUANTITY IN (100, 200, 300) 
    union
    SELECT rowid, UNIT_PRICE FROM ORDER_DETAIL WHERE DISCOUNT = 0.01
)