如何在单独的列上创建索引在内部工作?

时间:2017-10-27 12:35:47

标签: mysql database oracle database-indexes

我有一个包含10列的表Employee。在我的查询where子句中我使用column1和column2。如果我在两列上创建索引 即column1和column2。是否有可能利用两个指数?

可以有两种方法: -

  • 方法1:首先使用where子句索引,然后使用第二个where 第一个子句的子句结果返回进一步过滤而没有 使用第二个索引

  • 方法2:对于首先使用where子句索引,获取行ID。对于 使用第二个where子句索引,获取行ID并进行交集 两个rowIds

索引如何在这里工作?

更新: -

如果MySQL或Oracle的策略不同,请将oracle视为DB

2 个答案:

答案 0 :(得分:2)

对于Oracle,它取决于所使用的谓词的选择性。

情况下,一个谓词具有高选择性而另一个谓词,将只使用一个索引,第二个谓词将在表上进行过滤。

这里是执行计划的一个例子

 select * from tab where a = 250 and b = 2;

---------------------------------------------------------------------------------------------
| Id  | Operation                           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |       |     1 |   207 |     4   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TAB   |     1 |   207 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IDX_A |     1 |       |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

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

   1 - filter("B"=2)
   2 - access("A"=250)

这里A上的谓词只返回少数记录(1,但B上的谓词返回501行),只使用A列上的索引。

select 
sum(case when a = 250 and b = 2 then 1 end) as cnt_ab,
sum(case when a = 250  then 1 end) as cnt_a,
sum(case when b = 2 then 1 end) as cnt_b
from tab2;

    CNT_AB      CNT_A      CNT_B
---------- ---------- ----------
         1          1        501 

情况下,两个索引都不是非常有选择性,但谓词组合是选择性的 Oracle可以使用转换为BITMAP索引索引加入< / em>的。选择哪个访问路径取决于表统计信息和优化程序设置。在我的情况下,我获得了位图转换并使用INDEX_JOIN提示来获得另一个计划。 请注意,仅当查询仅返回索引中定义的列时,才可以进行索引连接。

 select  * from tab where a = 105 and b = 23;

谓词选择性

select 
sum(case when a = 105 and b = 23 then 1 end) as cnt_ab,
sum(case when a = 105  then 1 end) as cnt_a,
sum(case when b = 23 then 1 end) as cnt_b
from tab;

    CNT_AB      CNT_A      CNT_B
---------- ---------- ----------
       200      21700     100000 

转换为BITMAP

---------------------------------------------------------------------------------------------
    | Id  | Operation                           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                    |       |   829 |   167K|   434   (1)| 00:00:01 |
    |   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| TAB   |   829 |   167K|   434   (1)| 00:00:01 |
    |   2 |   BITMAP CONVERSION TO ROWIDS       |       |       |       |            |          |
    |   3 |    BITMAP AND                       |       |       |       |            |          |
    |   4 |     BITMAP CONVERSION FROM ROWIDS   |       |       |       |            |          |
    |*  5 |      INDEX RANGE SCAN               | IDX_A | 21552 |       |    45   (0)| 00:00:01 |
    |   6 |     BITMAP CONVERSION FROM ROWIDS   |       |       |       |            |          |
    |*  7 |      INDEX RANGE SCAN               | IDX_B | 21552 |       |   190   (1)| 00:00:01 |
    ---------------------------------------------------------------------------------------------

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

   5 - access("A"=105)
   7 - access("B"=23)

索引加入

 select /*+ INDEX_JOIN(a idx_a idx_b) */ a,b from tab where a = 105 and b = 23;

---------------------------------------------------------------------------------------
| Id  | Operation          | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                  |   829 |  5803 |   235   (1)| 00:00:01 |
|*  1 |  VIEW              | index$_join$_001 |   829 |  5803 |   235   (1)| 00:00:01 |
|*  2 |   HASH JOIN        |                  |       |       |            |          |
|*  3 |    INDEX RANGE SCAN| IDX_A            |   829 |  5803 |    45   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN| IDX_B            |   829 |  5803 |   190   (1)| 00:00:01 |
---------------------------------------------------------------------------------------    
Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"=105 AND "B"=23)
   2 - access(ROWID=ROWID)
   3 - access("A"=105)
   4 - access("B"=23)

答案 1 :(得分:0)

(MySQL)

“ rowid”方法在MySQL中非常罕见。这可能是因为PRIMARY KEY用于此操作,并且它直接进入行。

您要查询的是INDEX(a, b)

的“综合”索引
WHERE a=1 AND b=2  -- Good index
WHERE b=1 AND a=2  -- Good index  (order does not matter _in the WHERE_)
WHERE a=1 AND b>2  -- Good index
WHERE b=1 AND a>2  -- Will ignore `b` in the index, but still use `a`

更多:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

在其中可以使用row-id的地方:http://mysql.rjweb.org/doc.php/index1,但效率低于复合索引。