带范围条件的Oracle复合索引

问题描述 投票:0回答:1

我正在从 mysql DB 切换到使用 oracle 19c 我需要创建/调整索引以支持范围条件: 我有这样的疑问:

select * from mytable where mydate>? and mytype=?

我在 mytavble(mydate,mytype) 上有一个索引 根据 MySQL,一旦达到第一个范围条件,查询中的任何后续条件将不会使用任何其他列。

为什么 mysql 不能也使用第二个索引列 mytype? 甲骨文也是如此吗?

oracle indexing query-optimization composite-index
1个回答
0
投票

Oracle 将打开一个

INDEX RANGE SCAN
,但会扫描
mydate
高于绑定变量的所有条目,并跳过(过滤)具有不同
mytype
的条目。

如果每个

mydate
都有大量数量的
mytype
,这将非常无效。

你可以在执行计划中看到它

EXPLAIN PLAN  SET STATEMENT_ID = 'jara1' into    plan_table  FOR
select * from mytable where mydate>:1 and mytype=:2;

SELECT * FROM table(DBMS_XPLAN.DISPLAY('plan_table', 'jara1','ALL'));

-----------------------------------------------------------------------------------------------
| Id  | Operation                           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |         |   500 |   982K|    61   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| MYTABLE |   500 |   982K|    61   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IDX     |    90 |       |    30   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("MYDATE">:1 AND "MYTYPE"=TO_NUMBER(:2) AND "MYDATE" IS NOT NULL)
       filter("MYTYPE"=TO_NUMBER(:2))

显然更好的查询索引是列顺序相反的索引 - 首先是具有相等谓词的列

create index idx2 on mytable (mytype,mydate);

-----------------------------------------------------------------------------------------------
| Id  | Operation                           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |         |   500 |   982K|    93   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| MYTABLE |   500 |   982K|    93   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IDX2    |    90 |       |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("MYTYPE"=TO_NUMBER(:2) AND "MYDATE">:1 AND "MYDATE" IS NOT NULL)

您会看到没有过滤器,仅选择了适当的行。与

3
相比,预计成本也更低
30

我不能代表 MySQL,但怀疑这会是相同的行为。

© www.soinside.com 2019 - 2024. All rights reserved.