select *
from sometable
where column1='somevalue' and column2='someothervalue'
对于上述查询,如果column1和column2都有索引表ix1和ix2,那么上面的例子使用哪个索引?假设' somevalue'和另外一些价值'是表中的现有值,column1和column2具有非唯一值。
如果和被替换为?
,它会有什么不同?答案 0 :(得分:5)
使用的索引是oracle优化器认为最适合查询的索引。 "最佳"在这种情况下意味着最具选择性 - 也就是说,哪个单一条件与最少的行匹配(根据表中的统计数据估计)。
对于您的查询,最佳索引为Event
或sometable(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