简体   繁体   English

如何理解避免全表扫描

[英]How to understand avoid FULL TABLE SCAN

I have a table that is responsible to store log. 我有一个表负责存储日志。 The DDL is this: 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")
 );

with these two indices: 有这两个指数:

CREATE INDEX STRUCTURE_CODE ON LOG ("OPERATOR_CODE");

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

but this query produce a 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';

Why I see always a FULL TABLE SCAN on column DATA and STRUCTURE_CODE ? 为什么我总是在DATASTRUCTURE_CODE列上看到FULL TABLE SCAN

(I have tried also on create two different index for STRUCTURE_CODE and DATA but I have always a full table scan) (我也试过为STRUCTURE_CODEDATA创建两个不同的索引,但我总是进行全表扫描)

Did you run stats on your new index and the table? 您是否在新索引和表上运行统计信息?

How much data is in that table and what percentage of it is likely to be returned by that query? 该表中有多少数据,该查询可能返回多少百分比? Sometimes a full table scan is better for small tables or for queries that will return a large percentage of the data. 有时,对于小型表或将返回大部分数据的查询,全表扫描更好。

  1. How many rows do you have in that table? 你在那张表中有多少行?
  2. How many is returned by this query? 此查询返回了多少?
  3. Please include the explain plan. 请包括解释计划。

If loading the table and doing a full table scan (FTS) is cheaper (in IO cost) than utilizing an index, the table will be loaded and FTS will happen. 如果加载表并进行全表扫描(FTS)比使用索引更便宜(在IO成本中),则将加载表并且将发生FTS。 [Basically the same what Necreaux said] [基本上与Necreaux所说的相同]

This can happen either if the table is small, or the expected result set size is big. 这适用于以下情况如果表很小, 或者预期的结果集的大小大。

What is small? 什么小? FTS will almost always happen if the table is smaller than DB_FILE_MULTIBLOCK_READ_COUNT . 如果表小于DB_FILE_MULTIBLOCK_READ_COUNT,则几乎总会发生FTS。 This case, the table usually can be loaded into memory with one big read. 在这种情况下,通常可以通过一次大读取将表加载到内存中。 It's not always an issue, check the IO cost in the explain plan. 这并不总是一个问题,请在解释计划中检查IO成本。

What is big? 什么大? If the table is pretty big, and you'll return the most of it, it is cheaper to read up the whole table in a few large IO calls, than making some index reads then making a lot of tiny IO calls all around to the table. 如果表格非常大,并且您将返回大部分内容,那么在几个大型IO调用中读取整个表会比在一些索引读取时更便宜,然后在周围进行大量微小的IO调用。表。

Blind guessing from your query (without the explain plan results), I think it would first consider an index range scan (over LOG_01), followed by a table access by rowid (to get the OPERATOR_CODE as it is not in the index), but either it decides that your table is too small, or that there are so many rows to be returned from that date range/structure_code, that rolling through the table is cheaper (in IO Cost terms). 从您的查询中盲目猜测(没有解释计划结果),我认为它首先会考虑索引范围扫描(通过LOG_01),然后是rowid的表访问(以获取OPERATOR_CODE,因为它不在索引中),但是要么它决定你的表太小,要么从那个日期范围/ structure_code返回那么多行,那么滚动表就更便宜了(在IO Cost术语中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM