每秒执行6000的简单SQL优化(一)

    最近看到一个系统的负载比较高,引起了我的注意,查看AWR报告发现,竟然是因为两条很简单的SQL语句导致。
    语句有多简单呢,就是下面的两个SQL语句。

select companyname from license

select supdepid from hrmdepartment where id
=''
    突然发现以前也发现了这个问题,但是最后也是不了了之,还是因为单纯从数据库的层面调整要灵活快捷的多,从业务层面来推动还是有一定的难度和阻力。之前的分析:关于CPU使用率高的awr分析 http://blog.itpub.net/23718752/viewspace-2062157/

   表License的数据只有1行,表hrmdepartment对的数据有2000多行,id是主键,含有非空约束。
    为什么这么小数量的表,含有主键,怎么还会导致严重的性能问题呢。
看执行计划第一个语句是全表扫描,里面只有1行记录,全表和索引扫描应该差别很小。
    
就是这样一个语句,在一个小时的时间里竟然执行了近2000多万次。

这样一条SQL的影响被无限放大,就导致了数据库的负载很高。
如此来看,每秒钟的执行频率极高,1秒钟差不多是6000多次的频率。什么系统有如此之高的业务需求。
和开发的同学交涉,原以为分析已经到位,剩下的就是快刀斩乱麻似的解决问题了。但是发现问题比我想象的要糟糕很多。
目前的情况是,大家都认为这是一个问题,但是让人很无奈的情况是这个系统是一个外部系统,目前还没有源码,所以也就意味着这是一个黑盒的环境了。
我看了下出问题的用户的结构信息,真让我大跌眼镜,大量的存储过程和触发器,表竟然有1万多个,我倒吸一口冷气,这个问题的情况确实比我想的难,准确的说是糟糕。
 sh findobj.sh USERV6|grep TABLE|wc -l
11904
$ sh findobj.sh USERV6|grep TRIGG|wc -l
1580
$ sh findobj.sh USERV6|grep INDEX|wc -l
1542
$ sh findobj.sh USERV6|grep PROC|wc -l
2149
换句话说,从应用层面来调整SQL的可能性极小。碰到这种情况真是无语了。但是抱怨和牢骚解决不了问题。我一边和开发的同学沟通,一边想数据库层面能不能做点什么。
select companyname from license这样一个语句,不能动SQL还有什么优化空间了。目前来看有一个改进之处是索引,表里有10多个字段,输出只有一个字段,表里存在一行记录。所以也就尽可能提高访问的效率,10%的改进被无限放大也是一个很理想的值。
    而且如果SQL语句能够修改的情况下,我有什么好的办法来改进,这都是我需要考虑的问题。
我用一个新的用户来做了一番测试。
create table license tablespace users as select * from  USERV6.LICENSE ;
exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'LICENSE');
可以看到执行计划是走了全表扫描
SQL> set autot trace exp stat

尝试1:
因为这个表只存在1行记录,而且从表结构信息来看数据是唯一的,于是我尝试创建一个唯一性索引。
create unique index index_lic_companyname on license(companyname);
重新收集统计信息
SQL> exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'LICENSE');
再次查看,发现CBO还是走了全表扫描。执行计划没有发生改变。


尝试2:
尝试添加hint,设置cardinality都是一样的结果,没有任何改变。
select /*+index( license index_lic_companyname)*/ companyname from license
select /*+cardinality( license,1)*/ companyname from license
尝试3:
我想到了一个新的改进方法,就是sample,可以根据随机算法得到数据。但是尝试结果依旧没有任何变化
select companyname from license sample(1);

尝试4:
尝试rownum的形式,结果依旧。
SQL> select companyname from license where rownum<=1;
尝试5:
启用cache选项,把数据牢牢放入cache里面,减少被换出的概率,但是在这个极端场景下,还是没有任何的改进。
SQL> alter table license cache;
尝试6:
如果我启用了Unique Index的时候,即SQL语句改为下面的形式,结果不言而喻,肯定是非常理想了。
select companyname from license where companyname='xxxx'

但是改动成为上面的情况的可能性我几乎为0,想想挺美好,总是有巨大的差距。
尝试7:
既然在这个特殊场景中,我们需要查询的是companyname这个字段,有什么办法把索引和表结合起来呢。一种方式就是IOT,即索引组织表了。
重新创建表
  CREATE TABLE "CYDBA"."LICENSE_IOT"
   (    "COMPANYNAME" VARCHAR2(100) primary key,
        ...
        "DOCUMENT" CHAR(1)
   ) organization index
  TABLESPACE "USERS" ;
插入1行数据。
SQL> insert into LICENSE_IOT select * from license;
1 row created.
SQL> commit;
收集统计信息。
SQL>exec dbms_stats.gather_table_stats(ownname=>null,tabname=>'LICENSE_IOT');
可以看到还是有了不小的改进。

这个结果让我还是充满信息,准备近期部署上去对比一下,希望看到鲜明的差距。第2条SQL继续优化,还是一块不好啃的骨头。

时间: 2024-10-29 10:30:57

每秒执行6000的简单SQL优化(一)的相关文章

每秒执行6000的简单SQL优化(二)

继续前几天的一次性能调优,这次调优难度不小,而且空间很小,看起来简直就是绝处逢生的感觉.下面的两条SQL语句执行频率极高,每秒达到6000次,希望能够优化. select companyname from license select supdepid from hrmdepartment where id ='' 前几天分析了一下,也尝试了很多种方法,但是始终无法启用索引,最后采用IOT的形式才看到效果,这是其一. 还有一点很多明眼人看出来了,为什么创建了唯一性索引,表license中存在1行

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一2.5 执行计划中其他信息的含义

2.5 执行计划中其他信息的含义 通过DBMS_XPLAN输出执行计划,除了计划本身外,还可以获得一些其他信息帮助我们进一步分析执行计划及语句性能. 2.5.1 查询块和对象别名 在使用DBMS_XPLAN显示执行计划时,选择'ADVANCED'预定义格式作为参数或者加入'ALIAS'控制字符串,可以在输出中看到以下内容: Query Block Name / Object Alias (identified by operation id): -------------------------

从简单Sql探索优化之道

本文需要优化的语句是select count(*) from t,这简单的统计语句一出,估计不少人纳闷了,能有啥优化空间,还优化之道,什么gui.   哦,其实简单的背后不简单,来,跟作者一起看看如何"不择手段",让count(*) 飞起来.不过我们用意的关键是让读者去思考,为什么能飞.   为什么能飞?嗯,因为我们掌握了Sql优化之道.那优化之道是什么?不着急,来,随我们来看看Sql飞的过程吧.   一 .优化过程     1. 普通思路   用了啥手段:啥没用!     性能啥情况

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.1 生成执行计划

1.1 生成执行计划 在Oracle中,任何一条语句在解析过程中都会生成一个唯一的数值标识,即SQL_ID.而同一条语句,在解析过程中,可能会因为执行环境的改变(例如某些优化参数被改变)而生成多个版本的游标,不同的游标会有不同的执行计划.每个游标都会按顺序赋予一个序列号,即CHILD_NUMBER,一条语句生成的第一个游标的CHILD_NUMBER为0:相应的,Oracle会为每个执行计划生成一个哈希值以作区分.而多个不同版本的游标,其执行计划可能会相同,也可能不同. 因此,我们可以知道,一条合

《Oracle高性能SQL引擎剖析:SQL优化与调优机制详解》一1.2 显示执行计划

1.2 显示执行计划 我们现在知道,有三个途径可以获取查询计划:v$sql_plan.dba_hist_sql_plan和PLAN_TABLE.如果需要读取一条SQL语句的执行计划,就需要知道该条语句的SQL_ID,如果该语句存在多个游标或者执行计划,则还需要知道游标的CHILD_NUMBER或计划的哈希值(可选).而无论我们通过哪个途径来获取执行计划,显示方式主要是两种:语句查询和包DBMS_XPLAN显示. 1.2.1 通过查询语句显示计划 通过查询语句从一些视图里读出执行计划并作格式化输出

一次耐人寻味的SQL优化:除了SQL改写,还要考虑什么?

作者介绍 黄浩,现任职于中国惠普,从业十年,始终专注于SQL.在华为做项目的两年多,做过大大小小的SQL多达1500个.闲暇之余,喜欢将部分案例写成博客发表在华为内部数据库官方社区,反响强烈,已连续四个月蝉联该社区最佳博主.目前已开设专栏"优哉悠斋",成为首个受邀社区"专家访谈"的外协人员.   这是一次值得纪念的优化,值得回忆的内容非常丰富,虽然这个SQL本身并不复杂,几乎是一个相对规范式的SQL,所以,这次优化的重点并不是SQL的改写,而更多的是业务需求.物理模

SQL优化一例

  今天闲的 看awr,发现一条SQL 每次执行40多秒,语句如下 ? 1 SELECT a.bill_class AS pol_code , b.bill_name AS pol_name , a.bill_no AS card_no , '网站' AS buy_path , a.rev_clerk_code AS agent_code , a.rev_clerk_type AS agent_type , to_char(a.regist_date, 'yyyy-mm-dd') AS reci

掌握SQL Monitoring这些特性,SQL优化通通不在话下

目录 术语说明 概述 什么SQL会被SQL MONITORING监控到 找到Real Time SQL Monitoring入口 详解Real Time SQL Monitoring     1术语说明   在正式介绍Real Time SQL Monitoring之前,我们先对接下来要用到一些术语做集中的介绍.   Table Queue,消息缓冲区,在并行操作中使用,用于PX进程之间的通信,或者PX进程与QC进程之间的通信,是内存中的一些page,每个消息缓冲区的大小由参数parallel_

被埋没的SQL优化利器——Oracle SQL monitor

转载声明:本文为DBA+社群原创文章,转载必须连同本订阅号二维码全文转载,并注明作者名字及来源:DBA+社群(dbaplus).    据说,在Oracle企业版数据库中有一个免费的工具,乃SQL优化之利器,那就是Oracle SQL monitor.下面,由DBA+社群原创专家周俊,给大家科普一下这一被埋没的神器.   专家简介    周俊 DBA+社群原创专家   具有14年以上Oracle数据库技术支持经验,在IBM的7年间担任华东区非IBM logo产品技术支持团队team leader