暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

8个小时的SQL优化到1秒钟

沃趣技术 2019-03-01
415



优化方法

AWR中此sql执行8个多小时。

DataGrip生成的sql,无法在软件中更改sql文本,要想改变执行计划用hint就不行了。

下面我们具体看下sql与执行计划,sql样子很熟悉,with as,都是数据字典表,并且在from后,很敏感想到view merge,查询每个子句都很快,那么执行计划也不用看了,直接在后加/*+materialize*/将其固化不做view merge操作,尝试一下。

文本如下:

with O1 as ( select object_id,
                object_type,
                object_name
         from sys.all_objects
         where owner = :1 
           --  and last_ddl_time >= :since
           --  and object_name in ( :[*major_object_names] )
           and object_type in ('TYPE''TYPE BODY''PACKAGE''PACKAGE BODY',
                               'PROCEDURE''FUNCTION',
                               'MATERIALIZED VIEW''VIEW''TRIGGER') ),
 O2 as ( select object_id as referenced_id,
                owner as referenced_schema_name,
                object_type as referenced_type,
                object_name as referenced_name
         from sys.all_objects ), -- don't use #CAT here
 DE as ( select type as object_type,
                name as object_name,
                referenced_owner as referenced_schema_name,
                referenced_type,
                referenced_name
         from sys.all_dependencies
         where owner = :2 
            and not (owner = referenced_owner and name = referenced_name and type = referenced_type || ' BODY')
            and not (referenced_owner = 'SYS' and referenced_type = 'PACKAGE' and referenced_name = 'STANDARD')
            and type not in ('SYNONYM','UNDEFINED','JAVA CLASS','JAVA DATA')
            and referenced_type not like 'JAVA%' )
select /* object_id, referenced_id */O1.object_id, O2.referenced_id /* object_id, referenced_id */
from O1 natural join DE natural join O2


将SQL中的绑定变量代入具体值,再次查询。

with O1 as ( select /*+ materialize */object_id,
                object_type,
                object_name
         from sys.all_objects
         where owner = 'SYS'
           --  and last_ddl_time >= :since
           --  and object_name in ( :[*major_object_names] )
           and object_type in ('TYPE''TYPE BODY''PACKAGE''PACKAGE BODY',
                               'PROCEDURE''FUNCTION',
                               'MATERIALIZED VIEW''VIEW''TRIGGER') ),
 O2 as ( select /*+ materialize */ object_id as referenced_id,
                owner as referenced_schema_name,
                object_type as referenced_type,
                object_name as referenced_name
         from sys.all_objects ), -- don't use #CAT here
 DE as ( select /*+ materialize */ type as object_type,
                name as object_name,
                referenced_owner as referenced_schema_name,
                referenced_type,
                referenced_name
         from sys.all_dependencies
         where owner = 'SYS' 
            and not (owner = referenced_owner and name = referenced_name and type = referenced_type || ' BODY')
            and not (referenced_owner = 'SYS' and referenced_type = 'PACKAGE' and referenced_name = 'STANDARD')
            and type not in ('SYNONYM','UNDEFINED','JAVA CLASS','JAVA DATA')
            and referenced_type not like 'JAVA%' )
select /* object_id, referenced_id */O1.object_id, O2.referenced_id /* object_id, referenced_id */
from O1 natural join DE natural join O2;


1秒钟执行完。

执行计划如下:

此处略去好多行… …

那么在不改变sql的情况下,怎么将不同sql id好的执行计划绑定到目标sql中呢?想到了coe_load_sql_profile.sql    

下面我们就将这个/*+materialize */ hint的执行计划绑定到老的SQL中。

SQL>@coe_load_sql_profile.sql

Parameter 1:
ORIGINAL_SQL_ID (required)

Enter value for 11kn67w4a4ch53

Parameter 2:
MODIFIED_SQL_ID (required)

Enter value for 299hfmmfxdmu95


 PLAN_HASH_VALUE          AVG_ET_SECS
-------------------- --------------------
      2037728849                1.148

Parameter 3:
PLAN_HASH_VALUE (required)

Enter value for 32037728849

Values passed to coe_load_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ORIGINAL_SQL_ID: "1kn67w4a4ch53"
MODIFIED_SQL_ID: "99hfmmfxdmu95"
PLAN_HASH_VALUE: "2037728849"
… …此处省略一直到结尾


| 效率对比

SELECT SQL_ID,
   CHILD_NUMBER,
   PLAN_HASH_VALUE,
   SORTS,
   DISK_READS,
   DIRECT_WRITES,
   BUFFER_GETS,
   ROUND(ELAPSED_TIME / 1000 / 10002) ELAPSED_S,
   ROUND(CPU_TIME / 1000 / 10002) CPU_S,
   EXECUTIONS
FROM V$SQL
WHERE SQL_ID = '1kn67w4a4ch53';



| 另一种方法

除了使用/*+materialize */,到这里其实还有一种方式优化这条sql 大家不妨想一想。

… …

下面给出答案。

with O1 as ( select object_id,
                object_type,
                object_name
         from sys.all_objects
         where owner = 'SYS'
           and object_type in ('TYPE''TYPE BODY''PACKAGE''PACKAGE BODY',
                               'PROCEDURE''FUNCTION',
                               'MATERIALIZED VIEW''VIEW''TRIGGER') ),
 O2 as ( select object_id as referenced_id,
                owner as referenced_schema_name,
                object_type as referenced_type,
                object_name as referenced_name
         from sys.all_objects ), 
 DE as ( select type as object_type,
                name as object_name,
                referenced_owner as referenced_schema_name,
                referenced_type,
                referenced_name
         from sys.all_dependencies
         where owner = 'SYS' 
            and not (owner = referenced_owner and name = referenced_name and type = referenced_type || ' BODY')
            and not (referenced_owner = 'SYS' and referenced_type = 'PACKAGE' and referenced_name = 'STANDARD')
            and type not in ('SYNONYM','UNDEFINED','JAVA CLASS','JAVA DATA')
            and referenced_type not like 'JAVA%' )
select /*+NO_MERGE(O1) NO_MERGE(O2) NO_MERGE(DE) */ O1.object_id, O2.referenced_id 
from O1 natural join DE natural join O2;


No_merge的执行计划中有7个view,发生了view merge的执行计划中有4个view

如果发生了视图合并,那么视图/子查询就会被拆开,并且执行计划中视图/子查询部分就没有VIEW关键字。 正好3个子查询,说明坏的执行计划发生了view merge了。


感谢姚崇童鞋的供稿!


- END -



点击查看招聘信息


相关链接

当心!使用mysqldump备份可能会让你欲哭无泪

sysbench花式踩坑之三:自增值导致的锁等待

沃趣微讲堂 | Oracle集群技术(六):集群应用资源层

如果将relay_log_recovery设置为0会发生什么?(下)

谈谈代码——如何避免写出糟糕if...else语句

为何Binlog中同一个事务的event时间点会乱序?

Oracle中的并行系列(二):你设置的并行真的生效了吗?

Oracle集群技术 | 集群的自启动系列(一)

深入浅出Kubernetes网络:容器网络初探

SQL优化之统计信息和索引

数据恢复新姿势——通过ibd和frm文件恢复数据

MySQL主从复制错误——列类型转换错误


更多干货,欢迎来撩~

文章转载自沃趣技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论