文档章节

分区字段不在SQL过滤中,悲剧

Vimeo
 Vimeo
发布于 2016/05/06 18:17
字数 867
阅读 114
收藏 4



快下班了,朋友发来SQL,说要跑900秒。

  SELECT
         T_01."ANLN1",
         T_01."ANLN2",
         T_01."APLZL",
         T_01."AUFNR",
         T_01."AUFPL",
         T_00."BKTXT",
         T_00."BLDAT",
         T_01."BPMNG",
         T_01."BPRME",
         T_01."BSTME",
         T_01."BSTMG",
         T_00."BUDAT",
         T_01."BUKRS",
         T_01."BWART",
         T_01."BWTAR",
         T_01."CHARG",
         T_00."CPUDT",
         T_00."CPUTM",
         T_01."DMBTR",
         T_01."EBELN",
         T_01."EBELP",
         T_01."ERFME",
         T_01."ERFMG",
         T_01."EXBWR",
         T_01."EXVKW",
         T_01."GRUND",
         T_01."KDAUF",
         T_01."KDEIN",
         T_01."KDPOS",
         T_01."KOSTL",
         T_01."KUNNR",
         T_01."KZBEW",
         T_01."KZVBR",
         T_01."KZZUG",
         T_01."LGORT",
         T_01."LIFNR",
         T_01."MATNR",
         T_00."MBLNR",
         T_01."MEINS",
         T_01."MENGE",
         T_00."MJAHR",
         T_01."NPLNR",
         T_01."PS_PSP_PNR",
         T_01."RSNUM",
         T_01."RSPOS",
         T_01."SHKZG",
         T_01."SOBKZ",
         T_00."USNAM",
         T_00."VGART",
         T_01."VKWRT",
         T_01."WAERS",
         T_01."WERKS",
         T_00."XABLN",
         T_01."XAUTO",
         T_00."XBLNR",
         T_01."ZEILE"
    FROM SAPSR3."MKPF" T_00
   INNER JOIN SAPSR3."MSEG" T_01
      ON T_01."MANDT" = '800'
     AND T_00."MANDT" = T_01."MANDT"
     AND T_00."MBLNR" = T_01."MBLNR"
     AND T_00."MJAHR" = T_01."MJAHR"
   WHERE T_00."MANDT" = '800'
     AND T_00."BUDAT" BETWEEN '20150303' AND '20150930'
     AND T_01."WERKS" = 'YH25'

看看执行计划:

已用时间:  00: 00: 18.82

执行计划
----------------------------------------------------------
Plan hash value: 445835420

-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time  | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |           |   185K|    52M|       |   132K  (1)| 00:26:34 |       |       |
|*  1 |  HASH JOIN                          |           |   185K|    52M|    15M|   132K  (1)| 00:26:34 |       |       |
|   2 |   PARTITION RANGE ALL               |           |   173K|    13M|       | 10779   (1)| 00:02:10 |     1 |    11 |
|*  3 |    TABLE ACCESS FULL                | MKPF      |   173K|    13M|       | 10779   (1)| 00:02:10 |     1 |    11 |
|   4 |   PARTITION RANGE ALL               |           |   337K|    69M|       |   117K  (1)| 00:23:32 |     1 |    11 |
|   5 |    TABLE ACCESS BY LOCAL INDEX ROWID| MSEG      |   337K|    69M|       |   117K  (1)| 00:23:32 |     1 |    11 |
|*  6 |     INDEX RANGE SCAN                | MSEG_MMWB |   337K|       |       | 25064   (1)| 00:05:01 |     1 |    11 |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T_00"."MANDT"="T_01"."MANDT" AND "T_00"."MBLNR"="T_01"."MBLNR" AND "T_00"."MJAHR"="T_01"."MJAHR")
   3 - filter("T_00"."BUDAT">='20150303' AND "T_00"."MANDT"='800' AND "T_00"."BUDAT"<='20150930')
   6 - access("T_01"."MANDT"='800' AND "T_01"."WERKS"='YH25')
       filter("T_01"."WERKS"='YH25')


统计信息
----------------------------------------------------------
          1  recursive calls
          1  db block gets
     222451  consistent gets
          0  physical reads
          0  redo size
    8571412  bytes sent via SQL*Net to client
      89800  bytes received via SQL*Net from client
       8118  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
     121741  rows processed

     T_00 : 总数据-1796465
      
T_01 : 总数据-6261512
      
MKPF、MSEG 都为分区表,分区字段-MJAHR(按日期分区)
MSEG:索引 MSEG_MMWB(MANDT, MBLNR, WERKS, BWART)



仔细看:

PARTITION RANGE ALL

这玩意走的是全表扫描,典型的过滤条件不包含分区字段,必然是个死。


解决方法:


在SQL中加入分区字段

 SELECT
         T_01."ANLN1",
         T_01."ANLN2",
         T_01."APLZL",
         T_01."AUFNR",
         T_01."AUFPL",
         T_00."BKTXT",
         T_00."BLDAT",
         T_01."BPMNG",
         T_01."BPRME",
         T_01."BSTME",
         T_01."BSTMG",
         T_00."BUDAT",
         T_01."BUKRS",
         T_01."BWART",
         T_01."BWTAR",
         T_01."CHARG",
         T_00."CPUDT",
         T_00."CPUTM",
         T_01."DMBTR",
         T_01."EBELN",
         T_01."EBELP",
         T_01."ERFME",
         T_01."ERFMG",
         T_01."EXBWR",
         T_01."EXVKW",
         T_01."GRUND",
         T_01."KDAUF",
         T_01."KDEIN",
         T_01."KDPOS",
         T_01."KOSTL",
         T_01."KUNNR",
         T_01."KZBEW",
         T_01."KZVBR",
         T_01."KZZUG",
         T_01."LGORT",
         T_01."LIFNR",
         T_01."MATNR",
         T_00."MBLNR",
         T_01."MEINS",
         T_01."MENGE",
         T_00."MJAHR",
         T_01."NPLNR",
         T_01."PS_PSP_PNR",
         T_01."RSNUM",
         T_01."RSPOS",
         T_01."SHKZG",
         T_01."SOBKZ",
         T_00."USNAM",
         T_00."VGART",
         T_01."VKWRT",
         T_01."WAERS",
         T_01."WERKS",
         T_00."XABLN",
         T_01."XAUTO",
         T_00."XBLNR",
         T_01."ZEILE"
    FROM SAPSR3."MKPF" T_00
   INNER JOIN SAPSR3."MSEG" T_01
      ON T_01."MANDT" = '800'
     AND T_00."MANDT" = T_01."MANDT"
     AND T_00."MBLNR" = T_01."MBLNR"
     AND T_00."MJAHR" = T_01."MJAHR"
   WHERE T_00."MANDT" = '800'
     AND T_00."BUDAT" BETWEEN '20150303' AND '20150930'
     AND T_01."WERKS" = 'YH25'
     AND MJAHR='2015' ---将分区字段加进来

再跑下执行计划如下:


走了分区全表,逻辑读为之前的二分之一。



后续问题:

根据优化后的执行计划,这个SQL还可以通过索引继续优化的,这里就不介绍了。





© 著作权归作者所有

Vimeo
粉丝 5
博文 107
码字总数 35893
作品 0
南昌
数据库管理员
私信 提问
加载中

评论(2)

Vimeo
Vimeo

引用来自“首席”的评论

-_-||sap?
是的。
首席
-_-||sap?
(部分转载)Presto上使用SQL遇到的一些坑

遇到过的问题: 很多的时候,在Presto上对数据库跨库查询,例如Mysql数据库。这个时候Presto的做法是从MySQL数据库端拉取最基本的数据,然后再去做进一步的处理,例如统计等聚合操作。 举个栗...

Avner
2018/08/07
0
0
生产环境大型sql语句调优实战第一篇(二)

对这条大sql的性能瓶颈进行了分析。主要瓶颈在于一个很大的业务表,数据量在亿级。如果通过时间条件来过滤,会有5%以内的数据被过滤出来。 但是没有时间相关的索引字段,所以会走全表扫描,在...

青夜之衫
2017/12/04
0
0
Presto介绍与常用查询优化方法

Presto Hive使用MapReduce作为底层计算框架,是专为批处理设计的。但随着数据越来越多,使用Hive进行一个简单的数据查询可能要花费几分到几小时,显然不能满足交互式查询的需求。 2012年秋季...

高广超
2018/10/10
0
0
HBase应用 | 云HBase Spark分析引擎对接云数据库POLARDB

HBase Spark分析引擎是云数据库HBase版提供的分析引擎,基于Spark提供的复杂分析、流式处理、机器学习的能力。Spark分析引擎可以对接阿里云的多种数据源,例如:云HBase数据库、MongoDB、Pho...

HBase技术社区
02/21
0
0
MySQL优化的奇技淫巧之STRAIGHT_JOIN

最近没怎么搞SQL优化,碰巧数据库被慢查询搞挂了,于是拿来练练手。 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: 说明:因为post和tag是多对多的关系,所以存在一...

爱情经纬线
2014/01/15
458
2

没有更多内容

加载失败,请刷新页面

加载更多

思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
41分钟前
6
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
5
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
3
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
10
0
高德API入门教程

项目需求 1、实现打开地图就能定位到中心显示标注点 2、点击标注显示保利可爱岛的详细信息 3、实现导航功能 <!doctype html><html><head> <meta charset="utf-8"> <meta http-......

我叫小糖主
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部