Sql 如何理解避免全表扫描
我有一个负责存储日志的表。 DDL是这样的:Sql 如何理解避免全表扫描,sql,oracle,query-optimization,full-table-scan,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 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") ;
但此查询会生成完整的表扫描:
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';
为什么我总是在列数据和结构\u代码上看到全表扫描
(我也尝试过为结构\u code
和数据创建两个不同的索引,但我总是进行完整的表扫描)您对新索引和表运行了统计信息吗
该表中有多少数据,该查询可能返回的数据百分比是多少?有时,对于小表或返回大量数据的查询,完整表扫描更好
那张桌子上有多少行
这个查询返回了多少
请包括解释计划
如果加载表并进行完整表扫描(FTS)比使用索引便宜(IO成本),则会加载表并进行FTS。[基本上和Necreaux说的一样]
如果表很小,或者预期的结果集大小很大,则可能会发生这种情况
什么是小的?如果表小于,FTS几乎总是会发生。在这种情况下,通常可以通过一次大读取将表加载到内存中。这并不总是一个问题,检查解释计划中的IO成本
什么是大的?如果表相当大,并且您将返回大部分,那么在几个大IO调用中读取整个表要比进行一些索引读取然后在表周围进行大量小IO调用便宜
< Blind >从您的查询中猜出(没有解释计划结果),我认为它首先会考虑索引范围扫描(LogLog01),接着是RoWID的表访问(以获取运算符代码,因为它不在索引中),但是或者它决定您的表太小,或者从该日期范围/结构代码返回的行太多,因此在表中滚动比较便宜(按IO成本计算)。主表中有多少行,以及此SELECT
查询返回多少行?正如@Necreaux所说,收集指数的数据。你的日期范围很广(2008年至2015年),因此指数不太可能有足够的选择性。