`
mikixiyou
  • 浏览: 1088200 次
  • 性别: Icon_minigender_1
  • 来自: 南京
博客专栏
C3c8d188-c0ab-3396-821d-b68331e21226
Oracle管理和开发
浏览量:349937
社区版块
存档分类
最新评论

一个分组统计SQL的优化过程(2)

阅读更多


我们对这个SQL执行做抽丝剥茧的分析。 (接一个分组统计SQL的优化过程(1) http://mikixiyou.iteye.com/blog/1491153  

分析执行计划

| Id   | Operation             | Name          | Rows   | Bytes | Cost (%CPU)| Time      |

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

|    0 | SELECT STATEMENT     |               |      1 |     21 |    540   (1)| 00:00:07 |

|    1 |   SORT AGGREGATE     |               |      1 |     21 |      |           |

|*   2 | TABLE ACCESS BY INDEX ROWID | CUST_INFO |   1866 | 39186 |    540   (1)|00:00:07 |

|    3 | BITMAP CONVERSION TO ROWIDS|          |        |        |      |           |

|*   4 | BITMAP INDEX SINGLE VALUE|IND_CUST_INFO_5 |     |     |      |           |

执行计划是 SQL 在数据库系统的执行轨迹,是从下向上,从右向左,从里向外的执行。

因此,我们首先看 ID 4 的这行操作记录。

在对象“ ND_CUST_INFO_5 “上执行“ BITMAP INDEX SINGLE VALUE ”操作。这个对象根据 dba_objects 可以查出它是一个位图索引,而操作是取出一个符合条件的位图。

位图索引的结构我这里先大概描述一下。

位图索引的物理结构和普通索引一样,也是 B-tree 结构。它存储的数据记录的逻辑结构为“ key_value,start_rowid,end_rowid,bitmap “。

其内容类似这样:

’8088’,00000000000,10000034441,1001000100001111000

Bitmap 是一个二进制,表示 START_ROWID END_ROWID 的记录, 1 表示等于 key_value 即‘ 8088 ‘的 ROWID 记录, 0 则表示不是这个记录。

我们了解 bitmap 的结构,就很容易理解,根据 key_value ,系统遍历一下,就能找到符合条件的记录的 ROWID

执行计划中 ID 为“ 3 ”的行,就是这种转换过程,转换出来的 ROWID 就是符合 BRHID=’8088’ 的记录的 ROWID

结果集就是这个语句“ select ROWID from cust_info where brhid=’8088’; “的执行结果。

ID 为“ 4 ”的那行,我们还注意到,“ 4 ”前面加了个“ * ”。此“ * “表示它有条件判断。

Predicate Information (identified by operation id):

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

    2 - filter("ASSET">50000 AND "MOBILE" IS NOT NULL AND TO_NUMBER("T1"."LOCKFLA

G")=0)

    4 - access("BRHID"='8088')

根据位图索引的结构,只要 key_value 的值很少,那么位图索引里保存的记录就会很小。业务上这里保存营业部代码,表中营业部代码也只有几百个,所以位图索引里的记录数就很小。

执行计划遍历位图索引时,只需要扫描有限的几个数据块。

位图索引中的 ROWID 去查找 CUST_INFO 表,得出所有 ROWID 相同的表的数据记录。此记录再按照过滤条件“ filter("ASSET">50000 AND "MOBILE" IS NOT NULL AND TO_NUMBER("T1"."LOCKFLAG")=0) 进行过滤,即得出所求的结果集。

大家注意一下:

这里的过滤条件,系统做了一个 to_number 的转换。表的字段 lockflag 数据类型为 varchar ,参数值却是 number ,所以不得不转换。

这种写法也是不合理的,额外增加 CPU 运行。若此字段上有索引,如此操作也将导致索引不会被使用。

回到执行计划中,可看出 rows 一列中,显示符合条件的记录数为 1866 条,但执行时间为 7 秒。

这个时间是指过滤操作和 ROWID 查找的时间之和。

在位图索引中得出的 ROWID 数量和“ select count(*) from cust_info where brhid=’8088’; “查询结果相等,约 1W 条,查询出来的结果将过滤成 1866 条记录。总计时间为 7 秒。

对于 WEB 应用的数据库而言, 7 秒种就是 7,000,000 微秒。这是一个非常漫长的时间。

正常情况下,一个数据块从内存读取所需的时间约是 10 微秒到 100 微秒不等,从磁盘读取所需的时间约 10 毫秒左右。若磁盘读超过 10 毫秒,则表示磁盘很忙或磁盘性能很差。

注:这个数值是我估计的,不一定正确,具体值还是要看环境。

最后一步是将将得到的记录进行聚合统计。

执行计划为

|    1 |   SORT AGGREGATE     |               |      1 |     21 |      |           |

这步很简单,仅是将过滤出来的 1866 条记录做记录数求和,使用的时间应该是微秒级别的,以至于这里都没有显示。

经过以上对执行计划的分析,我们可以判定,语句执行在“ TABLE ACCESS BY INDEX ROWID ”操作上消耗了绝大部分的时间。

这个操作是根据 ROWID 来读取记录,一共读取记录数约 1W 多条,使用时间为 7 秒钟。我们算一下,每条时间约 739 微秒。

这个 SQL 的运行成本统计信息显示一致性读( consistent gets

,也叫内存读)为 10630*8KB ,物理读(磁盘读)为 745*8KB

       10630   consistent gets

         745   physical reads

 

745 个物理读, 10630 个一致性读。如果按照每个物理读消耗 10 毫秒,则这些物理读就需要约 7 秒的时间。

我们分析的执行计划是第一次查询操作时生成的执行计划。在第二次执行时, SQL 快是因为没有物理读,所有记录都缓存在内存中。

我们有个疑问,为什么读取个 1W 行记录的操作,需要 7000 毫秒时间?

分享到:
评论

相关推荐

    sql脚本优化

    下面是sql语句优化的一些提示要点,主要讲述的是操作符优化过程。 IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。 但是用IN的SQL性能总是比较低的,从sql执行的步骤来...

    sql server2005/2008 性能优化大全 .pptx

    SQL2005性能优化大全,sqlserver性能优化,包括:什么叫做索引、利用索引优化sqlserver查询、使用数据库分区表提高程序检索效率、提高数据库查询效率的实用方法、SQL数据进行排序、分组、统计技巧;SQL Server查询...

    SQL基础编写与调试优化

    第五部分 SQL优化 优化器 SQL语句执行过程 SQL优化术语 第一部分 SQL基础 SQL简介 发展历史 SQL语句分类 DDL[Data Definition Language] DML[Data Manipulation Language] DQL [Data Query Language] DCL [Data...

    SQL性能优化

    由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。  NOT IN  此操作是强列推荐不使用的,因为不能应用表的索引。  推荐方案:用NOT EXISTS 或...

    Oracle数据库SQL语句优化策略

    基本的Sql编写注意事项 尽量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替 用IN写出来...由此可见用 IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。

    Microsoft SQL Server 2008技术内幕:T-SQL查询(第二卷)

    4.6 基于集合的方法和迭代/过程方法的比较,以及一个优化练习2 4.7 总结 第5章 算法和复杂性 5.1 你有一个1夸特的硬币吗? 5.1.1 如何从零钱罐中取回1夸特钱 5.1.2 有时零钱罐中没有1夸特的硬币 5.2 如何度量...

    SQLServer2008技术内幕T-SQL查询包含源代码及附录A

    4.6 基于集合的方法和迭代/过程方法的比较,以及一个优化练习208 4.7 总结214 第5章 算法和复杂性215 5.1 你有一个1夸特的硬币吗?215 5.1.1 如何从零钱罐中取回1夸特钱216 5.1.2 有时零钱罐中没有1夸特的硬币216 ...

    SQL培训第一期

    当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值;如果表之间有匹配行,则整个结果集行包含基表的数据值。 1.6.4.2 语法 select A.*, B.* from student_A A full outer join student_B B on A.Uuid...

    SQLServer 优化SQL语句 in 和not in的替代方案

    由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。 推荐在业务密集的SQL当中尽量不采用IN操作符 NOT IN 此操作是强列推荐不使用的,因为它不能应用...

    Microsoft+SQL+Server+2008技术内幕:T-SQL查询_源代码及附录 中文版

    4.6 基于集合的方法和迭代/过程方法的比较,以及一个优化练习208 4.7 总结214 第5章 算法和复杂性215 5.1 你有一个1夸特的硬币吗?215 5.1.1 如何从零钱罐中取回1夸特钱216 5.1.2 有时零钱罐中没有1夸特的硬币...

    程序员的SQL金典.rar

    通过对实际案例开发过程的详细分析,使读者掌握 SQL的综合应用技巧。 内容简介 本书主要介绍SQL的语法规则及在实际开发中的应用,并且对SQL在MySQL、MS SQL Server、Oracle和DB2中的差异进行了分析。本书分为3部分:...

    Oracle数据库SQL语句优化总结

    由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL不能转换了。  推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。  

    ORACLE SQL语句优化技术要点解析

    由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。  推荐方案:在业务密集的SQL当中尽量不采用IN操作符。 NOT IN操作符  

    Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐)--随书源代码

    10.2 SQL优化 257 10.2.1 测试执行计划 257 10.2.2 跨多个执行的测试 260 10.2.3 测试查询改变的影响 263 10.2.4 寻找其他优化机会 266 10.2.5 将子查询因子化应用到PL/SQL中 270 10.3 递归子查询 273 ...

    SQL sever 实训

    --创建存储过程P_Sale2,能够根据指定客户统计,汇总该客户购买每种产品的数量和花费金额 CREATE PROCEDURE P_Sale2 @CusNo nvarchar(3) AS SELECT Product.ProNO,ProName,Price ,SUM(Quantity),SUM(Price*Quantity...

    数据库调试工具

    3、可执行多条sql语句,或各种分组统计语句。前提是数据库支持该语法。 例1、执行简单的Sql语句:select,insert,delete,update 等 例2、[sqlserver2008]执行T-Sql语句: declare @aa int set @aa=123*2+456*3-...

    oracle实验报告

    2、 定义一个为修改职工表(emp)中某职工工资的存储过程子程序,职工名作为形参,若该职工名在职工表中查找不到,就在屏幕上提示“查无此人”然后结束子程序的执行;否则若工种为MANAGER的,则工资加$1000;工种为...

Global site tag (gtag.js) - Google Analytics