避免对表 Oracle 进行全表扫描

Posted

技术标签:

【中文标题】避免对表 Oracle 进行全表扫描【英文标题】:Avoid full table scan on a table Oracle 【发布时间】:2015-02-27 19:25:31 【问题描述】:

我有一个有 70 列的表,其中主键是 15 列的组合(包括数字和 varchar2)。请看下面的查询

select * from tab1 where k1=1234567889; 

Plan hash value: 1179808636
---------------------------------------------------------------------------------
| Id  | Operation         | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |             |  6044 |  2201K|  4585K  (1)| 15:17:04 |
|*  1 |  TABLE ACCESS FULL| tab1        |  6044 |  2201K|  4585K  (1)| 15:17:04 |
---------------------------------------------------------------------------------

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

   1 – filter ("K1"=30064825087)

其中 tab1 是上面提到的表,k1 是作为主键一部分的列。表未分区。插入数据后,还会分析表(表、索引和列)。上述查询的输出返回 100000 多条记录。问题是即使在 k1 列上进行 PK 后,查询仍在进行全表扫描,这是不可接受的。另一方面,使用索引提示并不能真正加快进程。

请告知可能的解决方案。

【问题讨论】:

请显示K1的定义和K1上的索引定义。 如果有 100,000+ 行具有特定的 K1 值并且使用索引提示强制使用索引不会提高性能(我假设您成功强制索引被使用),为什么你认为全表扫描是不可接受的?看来您是在说优化器的估计是准确的,并且完全扫描是最有效的方法。您可以通过将表创建为索引组织表或在K1 上对表进行分区(额外的许可成本)来提高此查询的性能(尽管它可能会对其他查询产生负面影响)。 【参考方案1】:

对于这个查询:

select *
from tab1
where k1 = 1234567889;

最佳索引是将k1 作为索引中的 first 键的索引。可以有一个复合索引,k1 必须是第一个键。听起来您有一个复合主键,k1 不是第一个键。

我建议您简单地定义另一个索引:

create index idx_tab1_k1 on tab1(k1);

【讨论】:

不能在 PK 的前导列名称中包含 k1,因为我已经有另一个 imp 列作为 k0 作为前导列。 @Amod 。 . .这就是为什么我建议为该列创建另一个索引。

以上是关于避免对表 Oracle 进行全表扫描的主要内容,如果未能解决你的问题,请参考以下文章

避免全表扫描

Oracle SQL优化必要的全表扫描思路分析

为啥 oracle 表索引但仍然进行全表扫描?

避免全表扫描的sql优化

避免全表扫描的sql优化

避免在 MySQL 中使用 OR 对简单连接进行全表扫描