`
445822357
  • 浏览: 730973 次
文章分类
社区版块
存档分类
最新评论

表扫描与索引扫描返回的行数不一致

 
阅读更多

某个应用最近总出现死锁,其中一些是因为报了索引和数据行存在不匹配的问题,MOS中有如下文档可以参考。


ORA-1499. Table/Index row count mismatch(文档 ID 563070.1)
现象
使用“validate structure cascade”分析表时报ORA-1499的错误,trace文件中包含“Table/Index row count mismatch”的错误信息。例如:
SQL> analyze table test validate structure cascade;
analyze table test validate structure cascade
*
ERROR at line 1:
ORA-01499: table/index cross reference failure - see trace file


trace文件中包含:
Table/Index row count mismatch
table 6559 : index 10000, 0
Index root = tsn: 6 rdba: 0x01400091
意味着扫描表返回6559行数据,索引扫描返回10000行数据。“Index root”是索引的段头信息。rdba: 0x01400091是相对于数据块地址的索引段头。他是十进制的20971665,Rfile#=5,Block#=145。

SQL> select dbms_utility.data_block_address_file(20971665) "Rfile#" ,dbms_utility.data_block_address_block(20971665) "Block#" from dual;
Rfile# Block#
---------- ----------
5 145


运行下面的查询明确关联的索引:

SQL>selectowner,segment_name,segment_type from dba_segments whereheader_file=5 andheader_block=145;

OWNER SEGMENT_NAMESEGMENT_TYPE
-----------------------------------------
SCOTTI_TEST INDEX
这种逻辑不一致性也能通过10g以上版本的ORA-600 [kdsgrp1]错误或低版本的ORA-600 [12700]错误来说明。

原因
这是一种表与索引之间的逻辑不一致。这种逻辑不一致通常是因为表上的高水位(HWM)出现了问题,全表扫描比索引扫描返回了更少的行。这种不一致性也可能是由于Oracle的defect或会引起IO丢失的OS/硬件问题导致的。

解决方案
可以通过下面的语句查询出全表扫描时未扫出的索引行:
select/*+INDEX_FFS(<tablename><indexnameidentifiedin2.1>)*/rowid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
from<tablename>
where<indexedcolumn>isnotnull
minus
select/*+FULL(<tablename>)*/rowid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
from<tablename>;

实例:
select/*+INDEX_FFS(TESTI_TEST)*/rowid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
fromtest
wherec2isnotnull
minus
select/*+FULL(TEST)*/rowid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
fromtest;

使用下面PLSQ中的索引,可以将全表扫描丢失的行存储到另一张表中:

droptabletest_copy;

createtabletest_copyasselect*fromtestwhere1=2;

declare
cursormissing_rowsis
select/*+INDEX_FFS(TESTI_TEST)*/rowidrid
fromtest
wherec2isnotnull
minus
select/*+FULL(TEST)*/rowidrid
fromtest;
begin
foriinmissing_rowsloop
insertintoTEST_COPY
select/*+ROWID(TEST)*/*fromTESTwhererowid=i.rid;
endloop;
end;
/

- 当索引返回的比表记录少时,重建索引可以解决这个问题。
- 当索引返回的比表记录多时,重建索引或执行虚拟insert插入该表的操作以提高HWM,可以最终解决这种逻辑错误。在以上这个案例中,修复了逻辑错误,但这些行也还是可能丢失了,因为是在执行这里提到的方法之前运行了上述PLSQL脚本。

如果从Oracle Support需要额外的帮助,请提供:
1. analyze语句分析的trace文件。

2. 第一个查询语句的结果。

3. dump基表段头产生的trace文件。
selectheader_file,header_block,tablespace_name fromdba_segments
whereowner=upper('&table_owner')andsegment_name=upper('&table_name');

altersystemdumpdatafile&header_fileblock&header_block;

trace文件用来明确HWM。
@ExamplefromablockdumpnotusingASSM(AutomaticSegmentSpaceManagement):
@
@ExtentControlHeader
@-----------------------------------------------------------------
@ExtentHeader::spare1:0spare2:0#extents:4#blocks:31
@lastmap0x00000000#maps:0offset:4128
@Highwater::0x014000d6ext#:3blk#:5extsize:8
@
@So,HWMislocatedatRDBA0x014000d6inextent_id=5andblock#=5inthatextent.

4. 这个查询结果可以明确索引多返回的行的区id:
selectrid,a.relative_fno,a.block,e.owner,e.segment_name,e.segment_type,e.extent_id,e.blocks
from(select/*+INDEX_FFS(<tablename><indexname>)*/rowidrid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
from<tableowner.tablename>
where<indexedcolumn>isnotnull
minus
select/*+FULL(<tablename>)*/rowidrid
,dbms_rowid.ROWID_RELATIVE_FNO(rowid)relative_fno
,dbms_rowid.ROWID_BLOCK_NUMBER(rowid)block
from<tableowner.tablename>
)a
,dba_extentse
wherea.relative_fno=e.relative_fno
ande.tablespace_name=upper('&tablespace_name')
andv.ts#=&tablespace_number
and(a.blockbetweene.block_idande.block_id+blocks-1);

注意:
- 以上SQL中请替换owner、表名、索引名和索引列。
- 表空间是上述步骤3提供的。
- 这个SQL查询提供了索引返回行位置的区extent。

分享到:
评论

相关推荐

    关于MySQL索引的深入解析

    一般优化器选择索引考虑的因素有:扫描行数,是否排序,是否使用临时表。 使用explain分析sql explain是很好的自测命令,勤于使用explain有助于我们写出更合理的sql语句以及建立更合理的索引: mysql&gt; explain ...

    统计分析信息拷贝

    ORACLE执行成本分析时首先取出所应用表及索引的统计数据进行分析,其中数据行数是一个重要的参数,因为ORACLE在分析表大小时行数为主要参数,如果进行两个表联合时,ORACLE会通过分析表的大小,决定应用小表进行全表...

    SQL查询安全性及性能优化

    因此查找效率高于索引扫描效率 执行计划的意义 对于我们开发高质量SQL是很有帮助的 首先可以帮助我们查看SQL语句是否利用到索引,比如很复杂的SQL语句中有些用到索引,但是执行计划中却没有索引查找,我们就可以...

    innoDB 索引结构详解

    1、数据库索引 innoDB和MyISAM对比 ...需要扫描全表,统计所有数据 只需要从计数器中读取保存好都行数  注意:MyISAM在mysql 8.0版本将  2、InnoDB 2-1、InnoDB的体系结构有:内存结构,线程,

    yapgt:另一个PostgreSQL工具

    索引/顺序读取(seq_idx) 获取每个表启动的索引/顺序扫描的数量获取通过每个表的索引/顺序扫描( Hello缺少索引)接收的行数插入更新删除(ins_upd_del) 哪张桌子上有多少插入物哪个表正在进行多少更新哪个表正在...

    使用索引统计信息优化查询语句,提高查询效率

    例如,查询优化器可以使用基数估计选择索引查找运算符而不是耗费更多资源的索引扫描运算符,从而提高查询性能。  每个统计信息对象都在包含一个或多个表列的列表上创建,并且包括显示值在第一列中的分布的直方图...

    MyISAM InnoDB 区别

     ◆2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时...

    小米soar SQL 优化建议工具

    大家都知道数据库中的explain执行计划工具,能帮我们分析自己所编写SQL的性能,如索引是否使用了、临时表是否使用了、文件排序是否使用了、扫描的行数以及各个查询的执行顺序等一些SQL执行反馈信息,但这个explain...

    浅谈MyISAM 和 InnoDB 的区别与优化

    2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件时,两...

    MySQL面试必备+Explain的讲解+简单优化+MyISAM、InnoDB存储引擎区别+MySQL为什么选择B+树索引+MySQL中的锁

    3,innodb不保存表的具体行数,执行 select count(*)from table时会全表扫描,而myisam用一个变量保存了整个表的行数,执行上述语句只需读出该变量的值就行,速度很快 4,innodb不支持全文检索,而myisam支持全文...

    开源bbs源码java-MySQL:关于MySQL相关内容复习

    应尽量避免全表扫描,首先应考虑在 where 及 order by ,group by 涉及的列上建立索引。 2.优化 SQL 语句      2.1 通过 explain(查询优化神器)用来查看 SQL 语句的执行效果, 可以帮助选择更好的索引和优化查询...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

     事务控制语言(Transactional Control Language,TCL),用于维护数据的一致性,包括COMMIT(提交事务)、ROLLBACK(回滚事务)和SAVEPOINT(设置保存点)3条语句 二、 Oracle的数据类型 类型 参数 描述 字符类型...

    mysql 中InnoDB和MyISAM的区别分析小结

    2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含 where条件...

    MySQL InnoDB和MyISAM数据引擎的差别分析

    MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持... 2.InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计

    SQL21日自学通

    计算所有的表中的行数354 为多个用户赋予系统权限359 将你的表的权限赋予其它的用户361 在载入数据时解除对数的约束363 一次创建多个同义字364 为你的表创建视图368 在一个计划中清除其所有的表的内容369 使用SQL 来...

    MySQL优化笔记-整理版.doc

    语句的扫描行数减少了多少? 没有大量的数据供测试,一般在学习环境中,只是手工添加几百上万条数据, 数据量小,看不出语句之间的明确区别. Q: 如何提高MySQL的性能? A: 需要优化,则说明效率不够理想. 因此我们首先要...

    hbase phoenix sql

    直接使用HBase API、协同处理器与自定义过滤器,对于简单查询来说,其性能量级是毫秒,对于百万级别的行数来说,其性能量级是秒。 Phoenix最值得关注的一些特性有: 嵌入式的JDBC驱动,实现了大部分的java.sql...

    MySQL存储引擎中MyISAM和InnoDB区别详解

    InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,... ◆2.InnoDB 中不保存表的具体行数,也就是说,执行select count() from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyI

    利用纯C语言解析单色位图文件获取颜色值的代码

    遍历行数和列数,根据索引计算出当前像素在pData数组中的位置: 像素位置 = 行索引 * 总字节数 根据列索引计算当前像素所在的BIT位在一个BYTE中的偏移量: 偏移量 = 7 - (列索引 % 8) 根据位运算的方式,将当前...

Global site tag (gtag.js) - Google Analytics