使用哪个索引? ORACLE DB SQL

时间:2016-01-27 14:14:56

标签: sql oracle

select *
from sometable 
where column1='somevalue' and column2='someothervalue'

对于上述查询,如果column1和column2都有索引表ix1和ix2,那么上面的例子使用哪个索引?假设' somevalue'和另外一些价值'是表中的现有值,column1和column2具有非唯一值。

如果和被替换为?

,它会有什么不同?

3 个答案:

答案 0 :(得分:5)

使用的索引是oracle优化器认为最适合查询的索引。 "最佳"在这种情况下意味着最具选择性 - 也就是说,哪个单一条件与最少的行匹配(根据表中的统计数据估计)。

对于您的查询,最佳索引为Eventsometable(column1, column2)。在相等条件下,要么匹配somtable(column2, column1)子句。

对于where,情况非常棘手。我认为Oracle可以使用这两个索引进行查询(查看解释计划),但更有可能使用or / union

union all

答案 1 :(得分:2)

完全不可能说,取决于许多因素;例如:

create table someTable ( column1 number, column2 number);
create index someIndex1 on someTable(column1);
create index someIndex2 on someTable(column2);
insert into sometable values ( 1,10);
insert into sometable values ( 2,10);
insert into sometable values ( 3,10);
insert into sometable values ( 4,20);
insert into sometable values ( 5,30);
insert into sometable values ( 5,40);
insert into sometable values ( 5,50);
commit;

现在我看到以下内容:

    SQL> select * from sometable where column1 = 1 and column2 = 10;

Execution Plan
----------------------------------------------------------
Plan hash value: 1247292719

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |    26 |     1   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| SOMETABLE  |     1 |    26 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | SOMEINDEX1 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COLUMN2"=10)
   2 - access("COLUMN1"=1)
使用不同过滤器的

相同行为

SQL> select * from sometable where column1 = 5 and column2 = 40;

Execution Plan
----------------------------------------------------------
Plan hash value: 1247292719

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |    26 |     1   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| SOMETABLE  |     1 |    26 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | SOMEINDEX1 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COLUMN2"=40)
   2 - access("COLUMN1"=5)

现在我计算统计数据,然后重试:

    SQL> select * from sometable where column1 = 5 and column2 = 40;

Execution Plan
----------------------------------------------------------
Plan hash value: 2029385636

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |     6 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| SOMETABLE  |     1 |     6 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | SOMEINDEX2 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COLUMN1"=5)
   2 - access("COLUMN2"=40)

现在我的桌子上有统计数据,所以它决定使用第二个索引,这对我给出的过滤器效果更好。 现在我尝试再次更改过滤器:

SQL> select * from sometable where column1 = 2 and column2 = 10;

Execution Plan
----------------------------------------------------------
Plan hash value: 1247292719

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     1 |     6 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| SOMETABLE  |     1 |     6 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | SOMEINDEX1 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("COLUMN2"=10)
   2 - access("COLUMN1"=2)

...它再次使用第一个索引,这是最符合我条件的。

即使在这个简单的序列中,您也可以看到不同的运行查询的方式,具体取决于数据,统计信息等。

答案 2 :(得分:0)

对于第一个查询,可能(通常情况下)它将是记录集(1)x(2)的交集,其中(1)column1 =' somevalue' (2)column2 =' someothervalue'。

最后它将是union(1)+(2)。

两个记录集都可以由"它的"索引。

一些额外的话

CREATE TABLE test as select * from user_objects;
CREATE index ndxOt on test(object_type);
CREATE index ndxC on test(created);
SELECT * FROM TEST where OBJECT_TYPE LIKE 'VIEW' or CREATED = TO_DATE('12.12.2014 16:40:57', 'DD.MM.YYYY HH24:MI:SS');

以及' OR'

的计划
SELECT STATEMENT Step 6 of 6     ALL_ROWS    6 18  38548 419
  CONCATENATION Step 5 of 6          5 0 0 0   
    TEST_USER.TEST TABLE ACCESS (BY INDEX ROWID BATCHED) Step 2 of 6 TEST_USER  TEST  ANALYZED  BY INDEX ROWID BATCHED  2 2 736 8   
      TEST_USER.NDXC INDEX (RANGE SCAN) Step 1 of 6  TEST_USER  NDXC  ANALYZED  RANGE SCAN  1 1 0 8
    TEST_USER.TEST TABLE ACCESS (BY INDEX ROWID BATCHED) Step 4 of 6 TEST_USER  TEST  ANALYZED  BY INDEX ROWID BATCHED  4 16  37812 411
      TEST_USER.NDXOT INDEX (RANGE SCAN) Step 3 of 6 TEST_USER  NDXOT ANALYZED  RANGE SCAN  3 1 0 411