前因:

客户咨询,有一个业务sql(代表经常被执行且重要),全表扫描在系统占用资源很高(通过ash报告查询得到信息)

思路:

1.找到sql_text,sql_id

2.查看执行计划

3.查询sql涉及对象的对象数据量,段大小,行数量,where条件列,是否存在索引,列的选择读情况如何

4.总结,优化整改

1.找到sql_text,sql_id

094cmrxrahdy2
SELECT ~10个列名称(由于设计用户信息,因此部分信息不再详细说明)
FROM Prescription
WHERE ProcFlg= AND(Group_No= OR Group_No= OR Group_No=) AND MachineNo<> ORDER BY Presc_Class DESC, PrescriptionNo, SeqNo;

2.查看执行计划

SQL> select * from table(dbms_xplan.display_cursor('094cmrxrahdy2',format=>'IOSTATS LAST'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------
Plan hash value:
----------------------------------------------------
| Id | Operation | Name | E-Rows |
----------------------------------------------------
| | SELECT STATEMENT | | |
| | SORT ORDER BY | | 335K|
|* | TABLE ACCESS FULL| PRESCRIPTION | 335K|
----------------------------------------------------
PLAN_TABLE_OUTPUT
-----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
- filter(("PROCFLG"= AND INTERNAL_FUNCTION("GROUP_NO") AND "MACHINENO"<>))
INTERNAL_FUNCTION 内部函数,一般执行计划看到这个需要特殊关注,但是本次确认输入的数值类型等同于字段类型

GROUP_NO NOT NULL NUMBER(2)

3.查询sql涉及对象的对象数据量,段大小,行数量,where条件列,是否存在索引,列的选择读情况如何

1)查询表所在的用户
select owner,object_name,object_type,status from dba_objects where object_name='PRESCRIPTION'
OWNER OBJECT_NAME OBJECT_TYPE STATUS
-------------------- -------------------- ------------------- -------
PUBLIC PRESCRIPTION SYNONYM VALID
PHARMACY PRESCRIPTION TABLE VALID
2)查询表的段大小

select sum(bytes)/1024/1024 from dba_segments where segment_name='PRESCRIPTION' and owner='PHARMACY';
SUM(BYTES)/1024/1024
--------------------
450

3)查询表上的索引,及索引对应列名称

select index_owner,index_name,column_name,COLUMN_POSITION from dba_ind_columns where table_owner='PHARMACY' and table_name='PRESCRIPTION'

INDEX_OWNER INDEX_NAME COLUMN_NAME COLUMN_POSITION
------------------------------ -------------------- -------------------- ---------------
PHARMACY PRESCRIPTION_IDX1 PRESC_CLASS 1
PHARMACY PRESCRIPTION_IDX1 PRESCRIPTIONNO 2
PHARMACY PRESCRIPTION_IDX1 SEQNO 3
PHARMACY PRESCRIPTION_IDX2 PROCFLG 1
PHARMACY PRESCRIPTION_IDX3 PROCFLG 1
PHARMACY PRESCRIPTION_IDX3 GROUP_NO 2
PHARMACY PRESCRIPTION_IDX3 MACHINENO 3
PHARMACY PK_PRESCRIPTION PRESCRIPTIONNO 1
PHARMACY PK_PRESCRIPTION SEQNO 2

9 rows selected.

--第一,where 条件的三个列,再上述结果中,均存在对应的记录,所以基本可以排除无索引导致全表扫描的问题

--第二,产生疑问,存在索引,为何未使用索引???  猜测数据倾斜严重,SQL查询数据量过大,统计信息不准确等信息导致的问题,需要进一步进行分析

4)查询表行数量,及最后一次收集统计信息的时间

SQL> select num_rows,last_analyzed  from dba_tables where owner='PHARMACY' and table_name='PRESCRIPTION';

NUM_ROWS    LAST_ANALYZED
-----------------------------
1560341    2018-11-27 22:01:31

5)查询where 条件列的选择性(及去重后的行数量)

WHERE ProcFlg=0 AND(Group_No=0 OR Group_No=1 OR Group_No=99) AND MachineNo<>99 

看起来最差的选择性<>条件MachineNo列

查询发现,表总160万行,MachineNo列只有一个值1,也不存在Null值,where条件<>99,是无价值的条件,但是不至于影想走索引,此条件近乎无用

SQL> select count(*),count(distinct MachineNo) from PHARMACY.PRESCRIPTION;
COUNT(*) COUNT(DISTINCTMACHINENO)
---------- ------------------------
1604912 1
--
SQL> select MachineNo,count(*) from PHARMACY.PRESCRIPTION group by MachineNo;
MACHINENO COUNT(*)
---------- ----------
1 1604912

看起来选择性最好的条件ProcFlg=0, 符合这个条件的数值表中存在49万条记录,占表中记录的1/4,选择性已经很差了

SQL> select count(*),count(distinct ProcFlg) from PHARMACY.PRESCRIPTION;
COUNT(*) COUNT(DISTINCTPROCFLG)
---------- ----------------------
1604912 4
select ProcFlg,count(*) from PHARMACY.PRESCRIPTION group by ProcFlg;
PROCFLG COUNT(*)
---------- ----------
-1 7
1 1110365
2 995
0 493545

看起来选择性中等的Group_No=0 OR Group_No=1 OR Group_No=99--符合条件的数值足有110万条记录

select count(*),count(distinct Group_No) from PHARMACY.PRESCRIPTION;
COUNT(*) COUNT(DISTINCTGROUP_NO)
---------- -----------------------
1604912 2
select Group_No,count(*) from PHARMACY.PRESCRIPTION group by Group_No;
GROUP_NO COUNT(*)
---------- ----------
1 1111367
2 493545

--组合过滤后,只有4种可能性,对于本次sql,

--条件ProcFlg=0 存在50万条记录
--Group_No 1 or 0 or 99 返回110万行记录

--全表 1604912 --160万行记录,提取记录110/160=68.5%数据量,执行效率过低,还不如走全表扫描

SQL> select count(*),count(distinct ProcFlg||' '||Group_No) from PHARMACY.PRESCRIPTION;

COUNT(*) COUNT(DISTINCTPROCFLG||''||GROUP_NO)
---------- ------------------------------------
1604914 4

4.总结,优化整改

1)该SQL走全表扫描是正确的,全表扫描比回表查询65%全表数据量更快

2)提高该SQL性能,无法从索引入手,因为SQL是查询10个列,且数据量过大,不适用索引快速检索数据

3)建议开发人员,重新针对业务逻辑,规划新表:

01对每个表建立主键约束(唯一值),让业务SQL能快速定位一个唯一的记录,通过索引,快速检索少量数据,减少资源的消耗(逻辑读等消耗);

02或者根据应用需求,将此表进行拆分多个小表,这样即使是全表扫描,相对来说量级别减少,查询时间可能会提升,但是资源消耗并未降低(逻辑读等消耗);

sql查询未走索引问题分析之查询数据量过大的更多相关文章

  1. sql server 大数据, 统计分组查询,数据量比较大计算每秒钟执行数据执行次数

    -- 数据量比较大的情况,统计十分钟内每秒钟执行次数 ); -- 开始时间 ); -- 结束时间 declare @num int; -- 结束时间 set @begintime = '2019-08 ...

  2. sql server编写通用脚本自动统计各表数据量心得

    工作过程中,如果一个数据库的表比较多,手工编写统计脚本就会比较繁琐,于是摸索出自动生成各表统计数据量脚本的通用方法,直接上代码: /* 脚本来源:https://www.cnblogs.com/zha ...

  3. Mysql中使用JDBC流式查询避免数据量过大导致OOM

    一.前言 java 中MySQL JDBC 封装了流式查询操作,通过设置几个参数,就可以避免一次返回数据过大导致 OOM. 二.如何使用 2.1 之前查询 public void selectData ...

  4. mysql慢查询Slow Query Log和未使用索引(Not Using Indexes)查询配置和使用

    mysql的“慢查询”指的是超过了允许的最大查询时间(long_query_time)的sql语句,而“未使用索引”查询顾名思义就是查询语句没有使用到索引的sql语句. 慢查询配置和使用 在msyql ...

  5. SQL IN 一定走索引吗?

    摘要 IN 一定走索引吗?那当然了,不走索引还能全部扫描吗?好像之前有看到过什么Exist,IN走不走索引的讨论.但是好像看的太久了,又忘记了.哈哈,如果你也忘记了MySQL中IN是如何查询的,就来复 ...

  6. oracle like模糊查询不能走索引?

    这里要纠正一个网上很多教程说的模糊匹配不能走索引的说法,因为在看<收获,不止SQL优化>一书,里面举例说到了,并且自己也跟着例子实践了一下,确实like一些特殊情况也是可以走索引的 例子来 ...

  7. like模糊查询是否走索引

    1.模糊查询 后通配 走索引 前通配 走全表 2.where条件用in或or 不会走索引索引的本质是平衡b+数,是为了方便查询的平衡多路查找树 B-Tree相比,B+Tree有以下不同点: 每个节点的 ...

  8. (转)SQL server 2005查询数据库表的数量和表的数据量

    本文转载自:http://hi.baidu.com/ajyajyajy/item/4e2a7f4dc83393d2c1a592c1 use DBNAMEgoselect * from sysobjec ...

  9. excel 数据量较大边查询边输入到excel表格中

    public Resultmodel getexpenseMessagx(HttpServletResponse response, String date1, String date2) { lon ...

随机推荐

  1. [luogu P2324] [SCOI2005]骑士精神

    [luogu P2324] [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1 ...

  2. [codechef July Challenge 2017] Pishty and tree

    PSHTTR: Pishty 和城堡题目描述Pishty 是生活在胡斯特市的一个小男孩.胡斯特是胡克兰境内的一个古城,以其中世纪风格的古堡和非常聪明的熊闻名全国.胡斯特的镇城之宝是就是这么一座古堡,历 ...

  3. sessionStorage在项目中的应用

    1. 本地存储 Cookie(局限性):用户可以禁用cookie,最多只能存储4kb,cookie有过期时间的(一般我们设置的时间最长1个月,用户使用杀毒软件也可以清除我们的cookie)LocalS ...

  4. windows开机锁定小键盘

    1.启动注册表编缉器 按下windows+R键,输入regedit回车启动注册表编缉器 2.修改注册表默认值 展开HKEY_USERS\.DEFAULT\Control Panel\Keyboard将 ...

  5. laravel的日志服务

    日志服务使用: $app=app(); $log=$app->make('log'); $log->info('post_index',['data'=>'this is post ...

  6. frameset的固定放置模式,不能放入<form runat="server">中

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="admin_default.as ...

  7. linux操作系统及命令Part 1

    1.关于linux系统的安装与流程     (1)下载Vmware workstation 与 linux系统(centos版本.redhat版本.Ubuntu版本...)镜像. (2)详细安装见有道 ...

  8. Ubuntu下如何访问Windows磁盘?

    有些同学的电脑原来是Windows系统的,但为了需要,又下载了一个Ubuntu系统,变成双系统的电脑. 但是,在Ubuntu下,Windows的磁盘是打不开的,用网盘或者U盘又是很不方便,所以ljn教 ...

  9. Jdbc连接Oracle12C集群环境

    jdbc.url=jdbc:Oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 192.31.0. ...

  10. Jenkins详细安装与构建部署使用教程

    版权声明:本文为博主林炳文Evankaka原创文章,转载请注明出处http://blog.csdn.net/evankaka   目录(?)[+]   Jenkins是一个开源软件项目,旨在提供一个开 ...