楼主: 〇〇

[转载] 105-跟专家学习SQL优化-1 原创 老虎刘 老虎刘谈oracle性能优化

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
11#
 楼主| 发表于 2023-7-18 19:21 来自手机 | 只看该作者
idno contno validstate的不同值各有多少

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
12#
发表于 2023-7-18 21:51 | 只看该作者
sql_tigerliu 发表于 2023-7-18 13:58
这种情况, 12.2 以上版本的改写也很简单, 之前的版本稍复杂一点.

我想这么改:
select min(priority)
    from XXXPERSON t
   where (t.idno,t.validstate) in
  (
           select m.idno,'1'
            from LCAPPNT m
            where m.contno = '880037131628'
           union all
           select n.idno,'2'
            from LCINSURED n
           where n.contno = '880037131628'
  )
and t.validstate in ('1','2') ---- 这个条件也可以不加

不知道你说的简单和复杂的改法又是怎样的?

使用道具 举报

回复
论坛徽章:
2
20周年集字徽章-周
日期:2023-08-03 16:37:4519周年集字徽章-19
日期:2024-09-07 21:32:18
13#
发表于 2023-7-18 22:18 | 只看该作者
newkid 发表于 2023-7-18 21:51
我想这么改: select min(priority)    from XXXPERSON t   where (t.idno,t.validstate) in   (           ...

苏老师的改写比较巧妙
12.2+ 把 t.validstate 从子查询里面提出来, 加上or_expand 就可以
  select /*+ or_expand */*
    from XXXPERSON t
   where
      (    t.validstate = '1'  and
        exists
           (select 1
            from LCAPPNT m
            where m.idno  = t.idno
             and m.contno = '880037131628'
            )
       )
      or
      (  t.validstate = '2'  and
          exists
           (select 1
            from LCINSURED n
           where  n.idno  = t.idno
             and n.contno = '880037131628'
            )
      );

12.2- , 这种写法稍复杂, 但是通用性更强一些, 如果主表对两个子查询用的不都是t.validstate 字段, 也适用,这个也是or_expand的查询转换逻辑:
select  min(priority)
from
(
    select priority
    from XXXPERSON t
   where
        exists
           (select 1
            from LCAPPNT m
            where m.idno  = t.idno
             and m.contno = '880037131628'
             and t.validstate = '1'
            )
   union all
   select priority
    from XXXPERSON t
   where exists
           (select 1
            from LCINSURED n
           where  n.idno  = t.idno
             and n.contno = '880037131628'
             and t.validstate = '2'
            )
      and lnnvl( exists
                (select 1
                 from LCAPPNT m
                 where m.idno  = t.idno
                   and m.contno = '880037131628'
                   and t.validstate = '1'
                )
              )
);   

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
14#
 楼主| 发表于 2023-7-19 05:12 来自手机 | 只看该作者
lnnvl的操作其他数据库没有

使用道具 举报

回复
论坛徽章:
2
20周年集字徽章-周
日期:2023-08-03 16:37:4519周年集字徽章-19
日期:2024-09-07 21:32:18
15#
发表于 2023-7-19 07:47 | 只看该作者
〇〇 发表于 2023-7-19 05:12
lnnvl的操作其他数据库没有

其他数据库没有的东西还挺多.  按照这个思路, 再改改总是可以的

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
16#
 楼主| 发表于 2023-7-19 08:10 | 只看该作者
造数据测试了一下,各种写法都差不多
create table xxxperson(idno int , validstate char(1),priority int,idtype int);
create index idx_xxxperson_idno on xxxperson(idno);

create table lcappnt(idno int,idtype int,contno varchar(30));
create index idx_lcappnt_contno on lcappnt(contno);

create table lcinsured(idno int,idtype int,contno varchar(30));
create index idx_lcinsured_contno on lcinsured(contno);

insert into xxxperson select i,i%7,i%3,i%3 from range(1000000)t(i);
insert into lcappnt select i,i%3,i+880037100000 from range(1000000)t(i);
insert into lcinsured select i,i%3,i+880037100000 from range(1000000)t(i);

--liu 1
  select min(priority)
    from XXXPERSON t
   where
  (
        exists
           (select 1
            from LCAPPNT m
            where m.idno  = t.idno
             and m.contno = '880037131628'
             and t.validstate = '1'
            )
      or exists
           (select 1
            from LCINSURED n
           where  n.idno  = t.idno
             and n.contno = '880037131628'
             and t.validstate = '2'
            )
  );  




---newkid
select min(priority)
    from XXXPERSON t
   where (t.idno,t.validstate) in
  (
           select (m.idno,'1')
            from LCAPPNT m
            where m.contno = '880037131628'
           union all
           select (n.idno,'2')
            from LCINSURED n
           where n.contno = '880037131628'
  );


--liu 2
select /*+ or_expand */min(priority)
    from XXXPERSON t
   where
      (    t.validstate = '1'  and
        exists
           (select 1
            from LCAPPNT m
            where m.idno  = t.idno
             and m.contno = '880037131628'
            )
       )
      or
      (  t.validstate = '2'  and
          exists
           (select 1
            from LCINSURED n
           where  n.idno  = t.idno
             and n.contno = '880037131628'
            )
      );


--liu 3
select  min(priority)
from
(
    select priority
    from XXXPERSON t
   where
        exists
           (select 1
            from LCAPPNT m
            where m.idno  = t.idno
             and m.contno = '880037131628'
             and t.validstate = '1'
            )
   union all
   select priority
    from XXXPERSON t
   where exists
           (select 1
            from LCINSURED n
           where  n.idno  = t.idno
             and n.contno = '880037131628'
             and t.validstate = '2'
            )
      and ( exists
                (select 1
                 from LCAPPNT m
                 where m.idno  = t.idno
                   and m.contno = '880037131628'
                   and t.validstate = '1'
                ) is null
             or not
              exists
                (select 1
                 from LCAPPNT m
                 where m.idno  = t.idno
                   and m.contno = '880037131628'
                   and t.validstate = '1'
                )
              )
);   

使用道具 举报

回复
论坛徽章:
2
20周年集字徽章-周
日期:2023-08-03 16:37:4519周年集字徽章-19
日期:2024-09-07 21:32:18
17#
发表于 2023-7-19 08:35 | 只看该作者
〇〇 发表于 2023-7-19 08:10
造数据测试了一下,各种写法都差不多create table xxxperson(idno int , validstate char(1),priority int, ...

卢大师, 我不知道你用的是什么数据库, 我们之前的讨论范围还是局限在oracle数据库. 在oracle数据库中, 这些不同的写法, 执行效率的差别是比较大的. 我没有造数据, 根据表的大小, 通过执行计划基本就能看出好坏.  你说的差不多我不知道是都快还是都慢, 如果是都快, 那么恭喜, 这个数据库的优化器比oracle还强. 如果都慢也正常, 不过100万的数据量, 也慢不到哪里.   **是能比较一下执行计划.

使用道具 举报

回复
论坛徽章:
2
20周年集字徽章-周
日期:2023-08-03 16:37:4519周年集字徽章-19
日期:2024-09-07 21:32:18
18#
发表于 2023-7-19 08:36 | 只看该作者
最x好居然也成了敏感词, 日了鬼了

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
19#
 楼主| 发表于 2023-7-19 08:46 | 只看该作者
本帖最后由 〇〇 于 2023-7-19 08:47 编辑
sql_tigerliu 发表于 2023-7-19 08:35
卢大师, 我不知道你用的是什么数据库, 我们之前的讨论范围还是局限在oracle数据库. 在oracle数据库中, 这些 ...

duckdb数据,1000万也还可以,这个不了解原始数据分布,造的和实际没法比较

insert into xxxperson select i,i%7,i%3,i%3 from range(9000000)t(i);
insert into lcappnt select i,i%3,i+880037100000 from range(9000000)t(i);
insert into lcinsured select i,i%3,i+880037100000 from range(9000000)t(i);

--liu 1
Run Time (s): real 9.256 user 17.113310 sys 6.068439
---newkid
Run Time (s): real 0.122 user 1.279208 sys 0.000000
--liu 2
Run Time (s): real 0.10 1 user 1.138807 sys 0.000000
--liu 3
Run Time (s): real 2.806 user 30.248594 sys 5.**233

使用道具 举报

回复
论坛徽章:
2
20周年集字徽章-周
日期:2023-08-03 16:37:4519周年集字徽章-19
日期:2024-09-07 21:32:18
20#
发表于 2023-7-19 10:02 | 只看该作者
〇〇 发表于 2023-7-19 08:46
duckdb数据,1000万也还可以,这个不了解原始数据分布,造的和实际没法比较insert into xxxperson select i, ...

这个明显能看出区别了.  liu1是原始写法,只能走filter的执行计划,效率不行; 苏老师和liu2(duckdb也能自动做or_expand, 优化器水平还可以) 这两种写法的效率是可以的. liu3的写法, 可能你只加个not exists就行了, 不用再exists了, lnnvl其实就是求反, 只不过增加了null的处理)

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表