如何理解避免全表扫描

时间:2015-03-10 14:37:25

标签: sql oracle query-optimization full-table-scan

我有一个负责存储日志的表。 DDL是这样的:

CREATE TABLE LOG(
    "ID_LOG" NUMBER(12,0) NOT NULL ENABLE, 
    "DATA" DATE NOT NULL ENABLE, 
    "OPERATOR_CODE" VARCHAR2(20 BYTE), 
    "STRUCTURE_CODE" VARCHAR2(20 BYTE), 

     CONSTRAINT "LOG_PK" PRIMARY KEY ("ID_LOG")
 );

有这两个指数:

CREATE INDEX STRUCTURE_CODE ON LOG ("OPERATOR_CODE");

CREATE INDEX LOG_01 ON LOG ("STRUCTURE_CODE", "DATA") ;

但是这个查询产生了一个FULL TABLE SCAN:

SELECT log.data AS data1, 
       OPERATOR_CODE,
       STRUCTURE_CODE
  FROM log
 WHERE data BETWEEN to_date('03/03/2008', 'DD-MM-YYYY')
                AND to_date('08/03/2015', 'DD-MM-YYYY')
   AND STRUCTURE_CODE = '1601';

为什么我始终在FULL TABLE SCANDATA列上看到STRUCTURE_CODE

(我也试过为STRUCTURE_CODEDATA创建两个不同的索引,但我总是进行全表扫描)

2 个答案:

答案 0 :(得分:7)

您是否在新索引和表格上运行了统计信息?

该表中有多少数据以及该查询可能返回的百分比是多少?有时,对于小型表或将返回大部分数据的查询,全表扫描更好。

答案 1 :(得分:0)

  1. 该表中有多少行?
  2. 此查询返回了多少个?
  3. 请提供解释计划。
  4. 如果加载表并进行全表扫描(FTS)比使用索引更便宜(在IO成本中),则表将被加载并且将发生FTS。 [基本上与Necreaux所说的相同]

    如果表格很小, 预期结果集大小很大,就会发生

    什么是小?如果表格小于DB_FILE_MULTIBLOCK_READ_COUNT,则几乎总会发生FTS。这种情况下,表通常可以通过一次大读取加载到内存中。这并不总是一个问题,请在解释计划中检查IO成本。

    有什么大不了?如果表格很大,并且您将返回大部分内容,那么在一些大型IO调用中读取整个表格要比制作一些表格更便宜index读取然后在表格周围进行大量微小的IO调用。

    从您的查询中盲目猜测(没有解释计划结果),我认为它首先会考虑索引范围扫描(通过LOG_01),然后是rowid的表访问(以获取OPERATOR_CODE,因为它不在索引中) ),但是要么它决定你的表太小,要么从那个日期范围/ structure_code返回那么多行,那么滚动表就更便宜了(用IO成本术语)。