sql查询未走索引问题分析之查询数据量过大

前因:

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

思路:

1.找到sql_text,sql_id

2.查看执行计划

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

4.总结,优化整改

1.找到sql_text,sql_id

094cmrxrahdy2
SELECT 8~10个列名称(由于设计用户信息,因此部分信息不再详细说明)
FROM Prescription
WHERE ProcFlg=0 AND(Group_No=0 OR Group_No=1 OR Group_No=99) AND MachineNo<>99 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: 1208083363
----------------------------------------------------
| Id | Operation | Name | E-Rows |
----------------------------------------------------
| 0 | SELECT STATEMENT | | |
| 1 | SORT ORDER BY | | 335K|
|* 2 | TABLE ACCESS FULL| PRESCRIPTION | 335K|
----------------------------------------------------
PLAN_TABLE_OUTPUT
-----------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("PROCFLG"=0 AND INTERNAL_FUNCTION("GROUP_NO") AND "MACHINENO"<>99))
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               VALID2)查询表的段大小

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

原文地址:https://www.cnblogs.com/lvcha001/p/10140016.html

时间: 2024-12-13 18:00:50

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

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

本文转载自:http://hi.baidu.com/ajyajyajy/item/4e2a7f4dc83393d2c1a592c1 use DBNAMEgoselect * from sysobjects where xtype='U'; --这是查询所有表的信息select count(*) from sysobjects where xtype='U' --这是查询表的数量 ‍select a.name, b.rows from sysobjects a with(nolock) join

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

-- 数据量比较大的情况,统计十分钟内每秒钟执行次数 declare @begintime varchar(100); -- 开始时间 declare @endtime varchar(100); -- 结束时间 declare @num int; -- 结束时间 set @begintime = '2019-08-10 09:10:00' -- 开始时间 set @endtime = '2019-08-10 09:20:00' -- 结束时间 set @num = (select count(

es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?

面试题es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?面试官心理分析这个问题是肯定要问的,说白了,就是看你有没有实际干过 es,因为啥?其实 es 性能并没有你想象中那么好的.很多时候数据量大了,特别是有几亿条数据的时候,可能你会懵逼的发现,跑个搜索怎么一下 5~10s,坑爹了.第一次搜索的时候,是 5~10s,后面反而就快了,可能就几百毫秒.你就很懵,每个用户第一次访问都会比较慢,比较卡么?所以你要是没玩儿过 es,或者就是自己玩玩儿 demo,被问到这个问题容易懵逼,显示出你对

MongoDB数据量较大时如何构建索引--减少业务最少影响

在数据量较大或请求量较大,直接建立索引对性能有显著影响时,可以利用复制集(数据量较大时一般为线上环境,使用复制集为必然选择或者使用分片.)中部分机器宕机不影响复制集工作的特性,继而建立索引. 备注:添加索引的表使用WT引擎,数据量有1.5亿左右. 1. 副本集配置参数 节点1: $ more shard1.conf dbpath=/data/users/mgousr01/mongodb/dbdata/shard1_1 logpath=/data/users/mgousr01/mongodb/lo

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

mysql的“慢查询”指的是超过了允许的最大查询时间(long_query_time)的sql语句,而“未使用索引”查询顾名思义就是查询语句没有使用到索引的sql语句. 慢查询配置和使用 在msyqld的启动配置文件或命令行参数中增加以下参数 long_query_time=1 log-slow-queries=/var/mysql/logs/slow.log long_query_time参数表示的是慢查询的度量时间,单位是秒,最小是1,缺省值是10,凡是执行时间超过long_query_ti

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

这里要纠正一个网上很多教程说的模糊匹配不能走索引的说法,因为在看<收获,不止SQL优化>一书,里面举例说到了,并且自己也跟着例子实践了一下,确实like一些特殊情况也是可以走索引的 例子来自<收获,不止SQL优化>一书,实践准备: //建表,注意要非空数据 drop table t purge; create table t as select * from dba_objects where object_id is not null; select * from t; //更新

like模糊查询是否走索引

1.模糊查询,后通配 走索引 ,前通配 走全表 2.where条件用in或or 不会走索引 3.order by 排序时,如果碰到相同的值,则会随机进行排序,排序出来的结果集不是固定的.建议使用id序列进行排序(唯一的值).   原文地址:https://www.cnblogs.com/chenglangpofeng/p/10643387.html

关于mysql当中给数据量特别大的两个表做关联查询的时候解决查询速度很慢的解决方法

今天碰到了两个表做关联查询的mysql,这两个表的数据量都是特别大的,有一个表的数据是上亿条的数据,有一个是几百万的数据, 查询的速度是特别慢,然后我看了一下执行计划,下面是执行执行计划: 看到上面这个图这个数据量是特别大的,这个查询起来的肯定是非常慢的,而且他的类型都是ALL类型,也就是都是全表进行扫描的.然后在网上找资料,然后发现我们可以给关联的字段建索引. 于是我给关联字段建立了索引,然后就发生了下面的变化: 整个的行数就成不知道多少个数量级的情况在下降,整个的查询速度也是加快了额很多,现

现身说法:实际业务出发分析百亿数据量下的多表查询优化

今天给大家带来的讨论主题是通过实战经验来对百亿数据量下的多表数据查询进行优化,俗话说的好,一切脱离业务的架构都是耍流氓,接下来我就整理一下今天早上微信群里石头哥给大家分享的百亿数据量多表查询架构以及优化思路.由于本文内容整理自微信群,爬楼不易,整理更不易,如果有遗漏,欢迎大家在评论区留言. 作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/10530223.html 简单的例子 这里我们先举个简单的例子,来个开胃菜,然后再引出今天的访谈主题. 举例:比如