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

How does index created on separate columns works internally?

我有一个 table 员工,它有 10 列。在我的查询 where 子句中,我使用 column1 和 column2 。如果我在两列上创建索引 即 column1 和 column2 。是否有可能同时使用两个索引?

可以有两种方法:-

索引在这里是如何工作的?

更新:-

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

对于 Oracle,这完全取决于所使用的 where 谓词的选择性。

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

这里是执行计划的例子

 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 return 上的谓词只有几条记录(1,但谓词B returns 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 索引 索引连接 。选择哪个访问路径取决于 table 统计信息和优化器设置。在我的例子中,我得到了位图转换并使用 INDEX_JOIN 提示来获得另一个计划。 请注意,索引连接仅在查询 return 仅索引中定义的列时才有可能。

 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)

(MySQL)

"rowid" 方法在 MySQL 中非常罕见。这可能是因为 PRIMARY KEY 用于此目的,它直接转到行。

你问的是 "composite" 索引,比方说,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,但效率低于复合索引。