我为column_x
上的表创建了一个位图索引。请记住,列x的基数很低,100,000行数据中只有20个唯一值。
那我问
SELECT * FROM table_1
WHERE column_x = 'xyz'
但是它没有执行索引扫描,而是使用了全表扫描。
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 53295 | 8483K| 3413 (1)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMPLOYEE | 53295 | 8483K| 3413 (1)| 00:00:01 |
----------------------------------------------------------------------------------
现在,如果我为另一列y
添加了索引,那么我使用
SELECT column_x,column_y FROM table_1
WHERE column_x = 'xyz'
其结果将是
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 53295 | 676K| 8 (75)| 00:00:01 |
|* 1 | VIEW | index$_join$_001 | 53295 | 676K| 8 (75)| 00:00:01 |
|* 2 | HASH JOIN | | | | | |
| 3 | BITMAP CONVERSION TO ROWIDS| | 53295 | 676K| 1 (0)| 00:00:01 |
|* 4 | BITMAP INDEX SINGLE VALUE | DIVISION_IDX | | | | |
| 5 | BITMAP CONVERSION TO ROWIDS| | 53295 | 676K| 1 (0)| 00:00:01 |
| 6 | BITMAP INDEX FULL SCAN | STATUS_IDX | | | | |
--------------------------------------------------------------------------------------------------
为什么不能选择所有列?我不可能为每一列都创建一个索引,对吧?因为有些列具有很高的基数,或者不太符合 where 条件。而且我的查询只返回了所有数据的5%。
我做错什么了吗?
1条答案
按热度按时间rdlzhqv91#
你没做错什么甲骨文正在做正确的事情。索引并不总是让事情变得更好。Oracle试图变得智能化,只在索引有用的时候使用索引,而不是在索引没用的时候。
当您选择 * 所有 * 列时,获取这些列的唯一方法是从表本身获取。如果它要使用索引来访问基于 predicate (
WHERE
子句)的数据,那么它将对索引中找到的每个ROWID执行一次单块读取,这将是大约5%的行(1/20),这是非常重要的。那么多低效的单块读取(如果不考虑缓存,这意味着每行都要进行整个I/O操作!)将真正加起来,并使这是一个昂贵的操作在高容量。全表扫描可以比索引访问快5%的速度读取表,因为它使用了更有效的I/O方法,这些方法针对大量数据进行了优化。当您只选择 * 一个 * 列 *,而该列恰好也被索引 * 时,Oracle可以满足您的整个查询,而根本不使用表。它使用一个索引进行选择,另一个索引用于获取所需的列,并在它们的公共键(ROWID)上将这两个索引相交。根本不需要访问表,因此它不需要执行所有这些单块读取。因此,它发现在这种情况下使用位图索引更可取。
你不应该试图强迫Oracle对所有事情都使用索引。当它认为这是更好的路径时,让它使用全表扫描。通常,全表扫描是正确的选择。有时它会出错,需要轻推(通常通过暗示),但大多数时候你可以让它做它的事情。只有当SQL在运行时实际上执行得不可接受时,才需要投入时间进行性能调优。