`
zybing
  • 浏览: 456023 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【实践、技术】解决一起索引字段经常更新造成的索引效率低下的问题

阅读更多

 

 

 

 

操作系统:

数据库版本:

 

 

数据库机器读盘厉害,由于没有完整的检测手段以及历史累计数据,因此只能用简单的方式先进行检查:

 

检查消耗磁盘多的SQL语句:

 

V$SQLAREA中查询最占用资源的查询

select b.username username

        ,a.disk_reads reads

        ,a.executions exec

        ,a.disk_reads/decode(a.executions,0,1,a.executions) rds_exec_ratio

        ,a.sql_text Statement
from  v$sqlarea a,dba_users b
where a.parsing_user_id=b.user_id
       and a.disk_reads > 100000
order by a.disk_reads desc;

 

发现排名前几位的,有一句不应该出现的语句:

select * from (

   select * from user_message_send

    where  SEND_FLAG =?

         and   SEND_COUNT <3

    order by id

   )

where rownum<100

 

这个sql从表A中获取,type为特定值,coutn<3,同时按照时间排序的最早100条(IDsequence生成,等同于时间)。

进行trace,发现这句sql语句physical reads 要有700 而取出来的数据却不多。

 

第一次trace结果

执行分析:

 

Elapsed: 00:00:12.63

 

Execution Plan

----------------------------------------------------------

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=10 Card=1 Bytes=1164)

   1    0   COUNT (STOPKEY)

   2    1     VIEW (Cost=10 Card=1 Bytes=1164)

   3    2       SORT (ORDER BY STOPKEY) (Cost=10 Card=1 Bytes=122)

   4    3         TABLE ACCESS (BY INDEX ROWID) OF 'USER_MESSAGE_SEND'(Cost=1 Card=1 Bytes=122)

   5    4           INDEX (RANGE SCAN) OF 'I_SENDFLAG' (NON-UNIQUE) (Cost=1 Card=1)

 

Statistics

----------------------------------------------------------

          7  recursive calls

          0  db block gets

        716  consistent gets

        683  physical reads

          0  redo size

        936  bytes sent via SQL*Net to client

        373  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

          0  rows processed

 

Consistent getsphysical reads 特备高。

 

而且查询过程中,使用到了索引

” INDEX (RANGE SCAN) OF 'I_SENDFLAG' (NON-UNIQUE) (Cost=1 Card=1)”

 

通过2个不同工具,进行的分析结果

 

 

 

索引 I_SENDFLAG中,只包含了  SEND_FLAG字段,没有其他的字段

 

===============================================

 

原来以为是这个原因,新建了一个索引:

create index i_flagcount on user_message_send (SEND_FLAG, SEND_COUNT)

 

再进行trace的时候,发现还是使用到了第一个索引;

 

HINT,让SQL强行使用新索引,进行trace,结果出人意料:

 

Execution Plan

----------------------------------------------------------

   0   SELECT STATEMENT Optimizer=CHOOSE (Cost=10 Card=1 Bytes=1164 )

   1    0  COUNT (STOPKEY)

   2    1    VIEW (Cost=10 Card=1 Bytes=1164)

   3    2      SORT (ORDER BY STOPKEY) (Cost=10 Card=1 Bytes=122)

   4    3        TABLE ACCESS (BY INDEX ROWID) OF 'USER_MESSAGE_SEND'           (Cost=2 Card=1 Bytes=122)

   5    4          INDEX (RANGE SCAN) OF 'I_FLAGCOUNT' (NON-UNIQUE) ( Cost=2 Card=1)

 

Statistics

----------------------------------------------------------

          7  recursive calls

          0  db block gets

          4  consistent gets

          0  physical reads

          0  redo size

        936  bytes sent via SQL*Net to client

        373  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

          0  rows processed

 

发觉physical reads一下子没有了,而且consistent gets也只有个位数。

 

===============================================

 

但是感觉不对劲,又把原来的索引重建了一次,发现得到的结果也是如此。只是consistent gets多了一些

 

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=10 Card=1 Bytes=1164  )

   1    0   COUNT (STOPKEY)

   2    1     VIEW (Cost=10 Card=1 Bytes=1164)

   3    2       SORT (ORDER BY STOPKEY) (Cost=10 Card=1 Bytes=122)

   4    3         TABLE ACCESS (BY INDEX ROWID) OF 'USER_MESSAGE_SEND'  (Cost=1 Card=1 Bytes=122)

   5    4           INDEX (RANGE SCAN) OF 'I_SENDFLAG' (NON-UNIQUE) (Cost=1 Card=1)

 

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

         31  consistent gets

          0  physical reads

          0  redo size

        936  bytes sent via SQL*Net to client

        373  bytes received via SQL*Net from client

          1  SQL*Net roundtrips to/from client

          1  sorts (memory)

          0  sorts (disk)

          0  rows processed

 

 

 

===============================================

 

分析问题:

<!--[if !supportLists]-->1.  <!--[endif]-->SEND_FLAG这个字段,会根据状态进行变化的,而且几乎每条记录的FLAG都会有所变动,因此当日积月累后,索引表中,浪费的空间会原来越多(FLAG字段就几个选择项,而且最终几乎都会归到成功上去)。

<!--[if !supportLists]-->2.  <!--[endif]-->SEND_FLAG, SEND_COUNT)索引,比(SEND_FLAG)索引效果要好,consistent gets要低,是因为SEND_COUNT放在了索引中,因此开销更省;

 

注意:

<!--[if !supportLists]-->1.  <!--[endif]-->当时手快,把索引'I_SENDFLAG'给重新编译了一次,是不是由于索引变动的缘故,无据可查了;

 

===============================================

比较2个索引,为什么选择第一个(SEND_FLAG):

 

看一下2个索引的执行计划:

(SEND_FLAG)

INDEX (RANGE SCAN) OF 'I_SENDFLAG' (NON-UNIQUE) (Cost=1 Card=1)

 

(SEND_FLAG, SEND_COUNT)

INDEX (RANGE SCAN) OF 'I_FLAGCOUNT' (NON-UNIQUE) ( Cost=2 Card=1)

 

相对而言,选择第一个索引,Cost1,选择第二个索引Cost2,所以选择第一个

===============================================

 

 

 

资料:

关于EXPLAIN PLAN中的COST CARD解释

<!--[if !supportLists]-->1.  <!--[endif]-->Oracle -- EXPLAIN PLAN 分析SQL语句(转载): http://javabeezer.iteye.com/blog/560230

<!--[if !supportLists]-->2.  <!--[endif]-->cost[++] : http://www.cnblogs.com/afant/archive/2008/06/02/1211968.html

<!--[if !supportLists]-->3.  <!--[endif]-->plan cost: http://www.cnblogs.com/afant/archive/2008/06/02/1211946.html

 

 

 

COST

根据优化程序的基于开销的方法所估计出的操作开销值对于使用基于规则方法的语句该列为空该列值没有特定的测量单位它只是一个用于比较执行规划开销大小的权重值

 

CARDINALITYCARD

根据基于开销的方法对操作所访问行数的估计值

 

recursive calls

循环递归次数

 

db block gets

请求的数据块在buffer能满足的个数

 

consistent gets

逻辑IO用于读表并计算行数, 数据请求总数在回滚段Buffer 

 

 

 

 

 

 

 

 

  

 

分享到:
评论

相关推荐

    关于oracle clob 类型字段重建索引SQL及修复用户表空间索引空间的存储过程

    以下是一个简单的重建CLOB类型字段索引的SQL语句示例: ```sql BEGIN EXECUTE IMMEDIATE 'DROP INDEX your_clob_index_name'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END; / ...

    SqlServer-查看所有表、行数、索引名称、索引的字段

    系统跑久了,对于所有的索引想做一个具体的确认,所以写了这么一段, 可以用来分析自己数据的表及索引详情 针对记录数比较大的表,尤其要注意索引的情况,非常影响性能

    MySQL SQL高级特性 字段约束-索引-视图-外键学习实践

    本内容指出索引不存储NULL值,因此,字段允许NULL将降低索引效率。合理的索引设计是数据库优化的关键步骤。 接着,视图是虚拟的表,它实际上并不存储数据,而是根据SQL语句定义或查询得到的结果集。视图可以简化...

    SuperMap Objects .NET 创建字段索引

    例如,如果经常需要根据某地区的名称来查找对应的地理信息,为这个“地区名称”字段创建索引将会大大提高查询效率。 创建字段索引的过程通常包括以下步骤: 1. **初始化工作环境**:首先,你需要导入SuperMap ...

    SuperMap Objects Java 6R创建字段索引

    本文将深入探讨如何利用SuperMap Objects Java 6R创建字段索引,以及它对程序运行效率的影响。 首先,我们需要理解字段索引的概念。在关系型数据库中,索引是一种特殊的数据结构,用于快速查找和访问表中的特定记录...

    Mybatis Plus 自定义批量插入或批量更新(根据唯一索引)

    总的来说,Mybatis Plus 的自定义批量插入和更新功能允许开发者灵活地处理数据,尤其是结合唯一索引,可以有效地避免数据冲突,提高数据处理的准确性和效率。在实际开发中,应根据项目需求适当调整这些方法,以满足...

    SQL应用:研究SqlServer中Bit字段索引性能问题.

    ### SQL应用:研究SqlServer中Bit字段索引性能问题 #### 前言 在数据库设计与优化领域,字段类型的选择及是否为特定字段创建索引是两个非常关键的问题。特别是对于像`Bit`这种用于存储布尔值的数据类型,是否应该...

    如何在SQLITE中使用时间字段作索引

    在SQLite数据库中,时间字段作为索引的使用是优化查询性能的重要策略,特别是在处理大量时间序列数据时。本文将深入探讨如何在SQLite中创建带有时间字段的索引,以及如何利用这些索引来执行高效的SQL插入和查询操作...

    goldengate同步无主键无唯一索引表的问题以及解决方案.docx

    GoldenGate 同步无主键无唯一索引表的问题及解决方案 在数据同步中,无主键无唯一索引表的同步问题是常见的困扰, GoldenGate 作为一款优秀的数据同步工具,也遇到了这个问题。因此,本文将讨论 GoldenGate 同步无...

    mysql查询优化之索引优化

    - **选择合适的索引列**:索引应该建在经常出现在WHERE子句、JOIN条件和ORDER BY子句中的列上。 - **避免过度索引**:过多的索引会增加写操作的开销,因此需要权衡读写性能。 - **复合索引**:如果一个查询涉及多...

    MySQL索引最佳实践

    ### MySQL索引最佳实践 #### 一、理解MySQL索引的重要性 索引是数据库性能优化中最常用也是最重要的手段之一。合理的索引设计可以显著提高查询效率,减少服务器资源的消耗。在MySQL中,索引的选择与配置对于开发...

    MySQLSQL高级特性字段约束-索引-视图-外键学习实践.rar

    本教程主要探讨MySQL中的四大核心高级特性:字段约束、索引、视图和外键。这四个概念是数据库设计和管理的基础,对于提升数据库性能和确保数据完整性至关重要。 ### 字段约束 字段约束是定义数据库表结构时用来限制...

    MySQL 索引最佳实践

    标题:“MySQL 索引最佳实践” 描述:“提高mysql数据库性能必备。详细讲解mysql优化过程。” 在MySQL数据库中,索引扮演着至关重要的角色,它不仅能够显著提升数据查询的速度,还能帮助执行某些约束(如唯一性和...

    奇虎360 HBASE 二级索引的设计与实践

    结合上文提供的部分内容,我们可以看出奇虎360在设计和实践HBASE二级索引时,面对的挑战和解决这些问题时所采取的策略。首先是数据量巨大,其次是查询需求复杂,包括多维字段查询和实时查询。通用模式中的结构化存储...

    索引介绍聚集索引和非聚集索引

    - 对于经常用于查询条件的字段,建立非聚集索引可以提高查询速度。 - 当需要对多个列进行组合查询时,可以考虑建立复合非聚集索引。 #### 四、索引的性能比较 - **查询性能**:对于单列查询,聚集索引通常比非...

    70 针对主键之外的字段建立的二级索引,又是如何运作的?l.pdf

    对于联合索引,叶子节点中会存储被索引字段的组合值(例如,id+name+age)。在联合索引的B+树中,会先按照第一个字段排序,如果第一个字段相同,则按照下一个字段排序。如果想查询name和age的组合条件,那么数据库就...

    mysql存储与索引技术

    例如,如果查询多涉及时间戳字段,可以针对该字段建立索引,以加快查询速度。但是,索引并非没有代价,它们占用磁盘空间,并可能影响插入和更新操作的速度。对于 InnoDB 引擎,当表空间文件(ibdata1)过大且无法...

    SQLServer索引调优实践

    ### SQL Server索引调优实践 #### 索引的重要性 在数据库性能优化的过程中,索引扮演着极其重要的角色。不恰当的索引使用会导致其他优化措施的效果大打折扣,甚至变得毫无意义。因此,了解如何正确地创建、管理和...

    基于lucene技术的增量索引

    本文将深入探讨如何利用Lucene实现增量索引,这是一种在数据库或文件系统更新时仅对新数据或变化数据进行索引的技术,以降低资源消耗并保持搜索性能。 **1. Lucene基础知识** Lucene首先需要理解的是它的核心概念,...

Global site tag (gtag.js) - Google Analytics