MERGE INTO 性能问题疑问

今天同事碰到一个SQL的性能问题,主要是MERGE INTO的性能问题,执行脚本的时候,居然耗时50多分钟,汗!简直让人抓狂,脚本如下:

MERGE  INTO EDS.TW_DP_B_TDTERM_IMEI_DAY DM                   
        USING T_IMEI_DAY_1111 TEMP                                                 
                    ON(                                                            
                        DM.DATE_CD      =  TEMP.DATE_CD          AND               
                        DM.CITY_ID      = TEMP.CITY_ID           AND                
                        DM.IMEI          =  TEMP.IMEI AND                          
                        DM.USR_NBR      =  TEMP.USR_NBR                            
                      )                                                            
  WHEN MATCHED THEN  UPDATE SET                                                    
                      DM.GSM_FLUX        =  TEMP.GSM_FLUX           ,          
                      DM.TD_FLUX         =  TEMP.TD_FLUX            ,            
                      DM.GPRS_FLUX       =  TEMP.GPRS_FLUX                         
  WHEN NOT MATCHED THEN INSERT(                                                    
                      DM.DATE_CD                                    ,              
                      DM.CITY_ID                                    ,              
                      DM.IMEI                                       ,             
                      DM.BUSS_CITY_ID                               ,             
                      DM.TYPE_ID                                    ,              
                      DM.USR_NBR                                    ,              
                      DM.GSM_FLUX                                   ,             
                      DM.TD_FLUX                                    ,              
                      DM.GPRS_FLUX                                                 
                      )                                                            
                VALUES(                                                            
                      TEMP.DATE_CD                                  ,              
                      TEMP.CITY_ID                                  ,              
                      TEMP.IMEI                                     ,             
                      TEMP.BUSS_CITY_ID                             ,             
                      TEMP.TYPE_ID                                  ,              
                      TEMP.USR_NBR                                  ,              
                      TEMP.GSM_FLUX                                 ,              
                      TEMP.TD_FLUX                                  ,              
                      TEMP.GPRS_FLUX                                               
                      );  


两个表的数据量大致如下:
T_IMEI_DAY_1111  三十多万,  EDS.TW_DP_B_TDTERM_IMEI_DAY  三百多万数据,跑数前都做过表的相关信息
收集。 EDS.TW_DP_B_TDTERM_IMEI_DAY表的索引有效,碎片很少:

SQL> select count(1) from T_IMEI_DAY_1111;

  COUNT(1)
----------
    333575

SQL> select count(1) from EDS.TW_DP_B_TDTERM_IMEI_DAY;

  COUNT(1)
----------
   3731336

SQL> 

脚本的执行计划如下:
SQL> MERGE  INTO EDS.TW_DP_B_TDTERM_IMEI_DAY DM                   
        USING T_IMEI_DAY_1111 TEMP                                                 
                    ON(                                                            
                        DM.DATE_CD      =  TEMP.DATE_CD          AND               
                        DM.CITY_ID      = TEMP.CITY_ID           AND                
                        DM.IMEI          =  TEMP.IMEI AND                          
                        DM.USR_NBR      =  TEMP.USR_NBR                            
                      )                                                            
  WHEN MATCHED THEN  UPDATE SET                                                    
                      DM.GSM_FLUX        =  TEMP.GSM_FLUX             ,          
                      DM.TD_FLUX         =  TEMP.TD_FLUX              ,            
                      DM.GPRS_FLUX       =  TEMP.GPRS_FLUX                         
  WHEN NOT MATCHED THEN INSERT(                                                    
                      DM.DATE_CD                                    ,              
                      DM.CITY_ID                                    ,              
                      DM.IMEI                                       ,             
                      DM.BUSS_CITY_ID                               ,             
                      DM.TYPE_ID                                    ,              
                      DM.USR_NBR                                    ,              
                      DM.GSM_FLUX                                   ,             
                      DM.TD_FLUX                                    ,              
                      DM.GPRS_FLUX                                                 
                      )                                                            
                VALUES(                                                            
                      TEMP.DATE_CD                                  ,              
                      TEMP.CITY_ID                                  ,              
                      TEMP.IMEI                                     ,             
                      TEMP.BUSS_CITY_ID                             ,             
                      TEMP.TYPE_ID                                  ,              
                      TEMP.USR_NBR                                  ,              
                      TEMP.GSM_FLUX                                 ,              
                      TEMP.TD_FLUX                                  ,              
                      TEMP.GPRS_FLUX                                               
                      );    

333575 rows merged.

Execution Plan
----------------------------------------------------------
Plan hash value: 3661285687

--------------------------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT        |                         |   264K|    54M|       |  3576   (2)| 00:01:20 |       |       |
|   1 |  MERGE                 | TW_DP_B_TDTERM_IMEI_DAY |       |       |       |            |          |       |       |
|   2 |   VIEW                 |                         |       |       |       |            |          |       |       |
|*  3 |    HASH JOIN OUTER     |                         |   264K|    44M|    31M|  3576   (2)| 00:01:20 |       |       |
|   4 |     TABLE ACCESS FULL  | T_IMEI_DAY_1111         |   264K|    28M|       |   100   (2)| 00:00:03 |       |       |
|   5 |     PARTITION RANGE ALL|                         |  2128K|   125M|       |   765   (7)| 00:00:17 |     1 |   365 |
|   6 |      TABLE ACCESS FULL | TW_DP_B_TDTERM_IMEI_DAY |  2128K|   125M|       |   765   (7)| 00:00:17 |     1 |   365 |
--------------------------------------------------------------------------------------------------------------------------

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

   3 - access("DM"."USR_NBR"(+)="TEMP"."USR_NBR" AND "DM"."IMEI"(+)="TEMP"."IMEI" AND
              "DM"."CITY_ID"(+)="TEMP"."CITY_ID" AND "DM"."DATE_CD"(+)="TEMP"."DATE_CD")

Note
-----
   - dynamic sampling used for this statement

Statistics
----------------------------------------------------------
       9975  recursive calls
    1212324  db block gets
     111135  consistent gets
       2447  physical reads
  228686840  redo size
        822  bytes sent via SQL*Net to client
       2571  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
     333575  rows processed

SQL>

在优化脚本期间,我添加了USE_MERGE提示,结果执行脚本的时间一下子缩短到几十秒。但是让我很纳闷的是, 无论怎么看,添加USE_MERGE提示的脚本的执行计划怎么比较都比上面没添加提示的脚本的执行计划查(执行计划如下所示)
SQL> MERGE /*+ USE_MERGE(DM TEMP) */ INTO EDS.TW_DP_B_TDTERM_IMEI_DAY DM                   
        USING T_IMEI_DAY_1111 TEMP                                                 
                    ON(                                                            
                        DM.DATE_CD      =  TEMP.DATE_CD          AND               
                        DM.CITY_ID      = TEMP.CITY_ID          AND                
                        DM.IMEI          =  TEMP.IMEI AND                          
                        DM.USR_NBR      =  TEMP.USR_NBR                            
                      )                                                            
  WHEN MATCHED THEN  UPDATE SET                                                    
                      DM.GSM_FLUX        =  TEMP.GSM_FLUX               ,          
                      DM.TD_FLUX         =  TEMP.TD_FLUX              ,            
                      DM.GPRS_FLUX       =  TEMP.GPRS_FLUX                         
  WHEN NOT MATCHED THEN INSERT(                                                    
                      DM.DATE_CD                                    ,              
                      DM.CITY_ID                                    ,              
                      DM.IMEI                                        ,             
                      DM.BUSS_CITY_ID                                ,             
                      DM.TYPE_ID                                    ,              
                      DM.USR_NBR                                    ,              
                      DM.GSM_FLUX                                    ,             
                      DM.TD_FLUX                                    ,              
                      DM.GPRS_FLUX                                                 
                      )                                                            
                VALUES(                                                            
                      TEMP.DATE_CD                                  ,              
                      TEMP.CITY_ID                                  ,              
                      TEMP.IMEI                                      ,             
                      TEMP.BUSS_CITY_ID                              ,             
                      TEMP.TYPE_ID                                  ,              
                      TEMP.USR_NBR                                  ,              
                      TEMP.GSM_FLUX                                 ,              
                      TEMP.TD_FLUX                                  ,              
                      TEMP.GPRS_FLUX                                               
                      )                                                            
  ;     

333575 rows merged.

Execution Plan
----------------------------------------------------------
Plan hash value: 2993229602

---------------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
|   0 | MERGE STATEMENT         |                         |  1688K|   346M|       | 14060   (1)| 00:05:13 |       |       |
|   1 |  MERGE                  | TW_DP_B_TDTERM_IMEI_DAY |       |       |       |            |          |       |       |
|   2 |   VIEW                  |                         |       |       |       |            |          |       |       |
|   3 |    MERGE JOIN OUTER     |                         |  1688K|   283M|       | 14060   (1)| 00:05:13 |       |       |
|   4 |     SORT JOIN           |                         |   264K|    28M|    68M|  2424   (1)| 00:00:54 |       |       |
|   5 |      TABLE ACCESS FULL  | T_IMEI_DAY_1111         |   264K|    28M|       |   100   (2)| 00:00:03 |       |       |
|*  6 |     SORT JOIN           |                         |  2128K|   125M|   586M| 11636   (2)| 00:04:19 |       |       |
|   7 |      PARTITION RANGE ALL|                         |  2128K|   125M|       |   765   (7)| 00:00:17 |     1 |   365 |
|   8 |       TABLE ACCESS FULL | TW_DP_B_TDTERM_IMEI_DAY |  2128K|   125M|       |   765   (7)| 00:00:17 |     1 |   365 |
---------------------------------------------------------------------------------------------------------------------------

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

   6 - access("DM"."USR_NBR"(+)="TEMP"."USR_NBR" AND "DM"."IMEI"(+)="TEMP"."IMEI" AND
              "DM"."CITY_ID"(+)="TEMP"."CITY_ID" AND "DM"."DATE_CD"(+)="TEMP"."DATE_CD")
       filter("DM"."DATE_CD"(+)="TEMP"."DATE_CD" AND "DM"."CITY_ID"(+)="TEMP"."CITY_ID" AND
              "DM"."IMEI"(+)="TEMP"."IMEI" AND "DM"."USR_NBR"(+)="TEMP"."USR_NBR")

Note
-----
   - dynamic sampling used for this statement

Statistics
----------------------------------------------------------
       1884  recursive calls
    1217983  db block gets
      90427  consistent gets
        654  physical reads
  259129380  redo size
        814  bytes sent via SQL*Net to client
       2667  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
         11  sorts (memory)
          0  sorts (disk)
     333575  rows processed

SQL> exit

时间: 2024-08-03 06:22:39

MERGE INTO 性能问题疑问的相关文章

spring-新手关于Spring管理Hibernate下查询性能的疑问

问题描述 新手关于Spring管理Hibernate下查询性能的疑问 我这么两段代码: 1.Query query = Dao.createQuery("from table"); list = query.list(); for(Table item : list){ Query query2 = Dao2.createQuery("select id from table2"); list = query2.list(); } 2.Query query = D

http_load & ab 测试tomcat性能的疑问

问题描述 关于性能测试,有2个疑问一直困惑了好久,哪位牛人给解释下啊测试用tomcat安装后默认的主页面,1.用不同的工具,测试结果不一样,同一工具测试的结果有时也不一样server配置:1核心1G内存,tomcat6maxthreads,acceptCount值为默认值,测试结果如下:maxthreads+acceptCount应该代表了能接受的最大并发访问量,默认为200+100=300按理,应该在300个并发访问的时候,http_load应该不会显示出错才对啊,结果在180个并发时就出现了

ORACLE 博客文章目录(2015-05-27更新)

从接触ORACLE到深入学习,已有好几年了,虽然写的博客不多,质量也参差不齐,但是,它却是成长的历程的点点滴滴的一个见证,见证了我在这条路上的寻寻觅觅,朝圣的心路历程,现在将ORACLE方面的博客整理.归纳分类,方便自己和大家查看.翻阅.  ORACLE数据类型 ORACLE基本数据类型总结 ORACLE VARCHAR2最大长度问题 ORACLE数据库汉字占几个字节问题 ORACLE NUMBER类型Scale为0引发的问题   PL/SQL语法学习   PLSQL 调试触发器 PL/SQL重

Greenplum merge insert 用法与性能 (insert on conflict)

标签 PostgreSQL , Greenplum , merge insert , insert on conflict , 合并插入 , 有则更新 , 无则插入 背景 PostgreSQL insert on conflict语法非常强大,支持合并写入(当违反某唯一约束时,冲突则更新,不冲突则写入),同时支持流式计算. 流计算例子链接: <PostgreSQL 流式统计 - insert on conflict 实现 流式 UV(distinct), min, max, avg, sum,

性能-安卓环境线程调度问题

问题描述 安卓环境线程调度问题 在安卓手机上有两个进程a.b都用SCHED_RR方式创建线程,优先级一样,进程a.b都会对某个pty设备进行读操作,操作逻辑一致,一开始的线程过程函数如下: loop() { while(1) { read() ... 一大块处理代码 } } 功能.性能调好后为了优化代码,考虑a.b两者对该pty设备的操作线程都是上面的形式,可以将while(1)中的一大块代码抽象成一个函数调用,所以过程函数的 实现变成下面这样: handler() { read() ... 一

CYQ.Data 数据框架 性能评测

最近有网友经常关注 CYQ.Data 的性能问题,虽然关注,但没发现谁主动的写过和其它框架的性能评测文章.   个人平常比较忙一些,这么长久以来,一直也没好好的为 CYQ.Data 写一个简单的性能测试.   今天,得为它写了一篇了.   杂七几句: 当很多人问我 CYQ.Data 性能怎样时,我说:比其它ORM的框架性能要好.   当然,我没有给出任何的测试数据来证明,因为我没用过其它框架,所以没法给出数据,所以只能任网友:爱信不信.   说比其它框架要好,当然不是因为卖瓜的赞瓜甜,而是基于以

Mysql存储引擎之TokuDB以及它的数据结构Fractal tree(分形树)

在目前的Mysql数据库中,使用最广泛的是innodb存储引擎.innodb确实是个很不错的存储引擎,就连高性能Mysql里都说了,如果不是有什么很特别的要求,innodb就是最好的选择.当然,这偏文章讲的是TokuDB,不是innodb,相比innodb,TokuDB有着自己的特点. BTree和Fractal tree的比较: 目前无论是SQL Server,还是MySQL的innodb,都是用的B+Tree(SQL Server用的是标准的B-Tree)的索引结构.从理论上来说,这个结构在

SolrLucene优劣势分析

最早lucene2.4以及以前,追溯到2008年前后,lucene刚刚引起大家的关注,到后来Nutch.solr的出现,lucene变得更加热.Nutch.Solr的发展,极大推动了lucene的升级.对于一些接触过搜索,使用过lucene.solr的人来说,一般都会感觉lucene.solr很牛逼.我个人也认为solr.lucene确实非常NB,他涵盖了信息检索的几乎全部基础知识和非常高性能的实现方式.从solr的结构,扩展.维护整体看,发现有非常多的"工程亮点",熟读solr定会增

lucene/solr的缺点

lucene/solr的缺点 solrlucenehadoop&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; 1) http 请求做了cache,8630.html">有时候会出现新数据不可见,cache滞后的问题.-cache优化下也不是问题 2) admin 后台页面,支持中文. 复杂查询语法上,欠友好.-自己稍加扩展也不是问题 3) swap core的时候,单结点多core,并且core对