楼主: 暗纹河豚毒

[SQL] 分组求max,min速度很快,但是求max-min速度很慢

[复制链接]
论坛徽章:
30
生肖徽章:猴
日期:2015-03-20 10:13:49ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:31优秀写手
日期:2015-03-07 06:00:14沸羊羊
日期:2015-03-13 13:26:07美羊羊
日期:2015-04-06 20:32:13天蝎座
日期:2015-07-20 12:34:47射手座
日期:2015-09-18 12:38:55乌索普
日期:2016-08-03 07:04:28奥运会纪念徽章:手球
日期:2016-09-26 07:19:26山治
日期:2016-10-19 05:48:10
51#
发表于 2013-9-10 11:00 | 只看该作者
C:\Documents and Settings\10c001>sqlplus mes/MES@XXMES

SQL*Plus: Release 11.2.0.1.0 Production on 星期二 9月 10 08:16:51 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Release 11.2.0.1.0 - 64bit Production

SQL> @c:\plset

Session altered.

SQL> SELECT b.b,  max(b.ID) , /*test*/ min(b.ID) min_used FROM big b, (SELECT DISTINCT E.A FROM E WHERE E.A LIKE '1%') M
  2    WHERE b.A>=3 AND b.A<=4 AND b.b= M.A GROUP BY b.b;

         B  MAX(B.ID)   MIN_USED
---------- ---------- ----------
         1     999863         59
        11     999989         11
        12     999961        157
        10     999988         10

SQL> @c:\pln test
old   6: where upper(sql_text) like '%&1%'
new   6: where upper(sql_text) like '%test%'

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------

SQL_ID  9kq9byyj13ysw, child number 0
-------------------------------------
SELECT b.b,  max(b.ID) , /*test*/ min(b.ID) min_used FROM big b,
(SELECT DISTINCT E.A FROM E WHERE E.A LIKE '1%') M   WHERE b.A>=3 AND
b.A<=4 AND b.b= M.A GROUP BY b.b

Plan hash value: 69571800

-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |      1 |        |      4 |00:00:00.97 |    1147 |       |    |             |
|   1 |  HASH GROUP BY        |          |      1 |     13 |      4 |00:00:00.97 |    1147 |   718K|   718K| 1191K (0)|
|*  2 |   HASH JOIN           |          |      1 |    128K|  39410 |00:00:00.93 |    1147 |  1301K|  1301K|  940K (0)|
|   3 |    VIEW               | VW_GBF_5 |      1 |     13 |      4 |00:00:00.01 |      12 |       |    |             |
|   4 |     HASH GROUP BY     |          |      1 |     13 |      4 |00:00:00.01 |      12 |  1302K|  1302K|  715K (0)|
|*  5 |      TABLE ACCESS FULL| E        |      1 |    500 |   3077 |00:00:00.01 |      12 |       |    |             |
|*  6 |    TABLE ACCESS FULL  | BIG      |      1 |    285K|    285K|00:00:00.26 |    1135 |       |    |             |
-----------------------------------------------------------------------------------------------------------------------

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

   2 - access("B"."B"="ITEM_1")
   5 - filter(TO_CHAR("E"."A") LIKE '1%')
   6 - filter(("B"."A">=3 AND "B"."A"<=4))


27 rows selected.

SQL> SELECT b.b, /*test2*/ max(b.ID) - min(b.ID) min_used FROM big b, (SELECT DISTINCT E.A FROM E WHERE E.A LIKE '1%') M
  2    WHERE b.A>=3 AND b.A<=4 AND b.b= M.A GROUP BY b.b;

         B   MIN_USED
---------- ----------
         1     999804
        11     999978
        12     999804
        10     999978

SQL> @c:\pln test2
old   6: where upper(sql_text) like '%&1%'
new   6: where upper(sql_text) like '%test2%'

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------

SQL_ID  8w619bv23hwy3, child number 0
-------------------------------------
SELECT b.b, /*test2*/ max(b.ID) - min(b.ID) min_used FROM big b,
(SELECT DISTINCT E.A FROM E WHERE E.A LIKE '1%') M   WHERE b.A>=3 AND
b.A<=4 AND b.b= M.A GROUP BY b.b

Plan hash value: 2033372611

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |      1 |        |      4 |00:00:54.02 |    1147 |       |       |          |
|   1 |  HASH GROUP BY      |      |      1 |     13 |      4 |00:00:54.02 |    1147 |   718K|   718K| 3978K (0)|
|*  2 |   HASH JOIN         |      |      1 |   4926K|     30M|00:00:25.76 |    1147 |  1301K|  1301K| 1156K (0)|
|*  3 |    TABLE ACCESS FULL| E    |      1 |    500 |   3077 |00:00:00.01 |      12 |       |       |          |
|*  4 |    TABLE ACCESS FULL| BIG  |      1 |    285K|    285K|00:00:00.26 |    1135 |       |       |          |
-----------------------------------------------------------------------------------------------------------------

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

   2 - access("B"."B"="E"."A")
   3 - filter(TO_CHAR("E"."A") LIKE '1%')
   4 - filter(("B"."A">=3 AND "B"."A"<=4))


25 rows selected.
从test2看,哈希关联行数达285K*3077次,结果为30M行,比TEST的39410多得多,这正是慢的原因,最根本的原因还是关联前两个数据源的数量不同,TEST是将E表的3077行DISTINCT后只剩4行,而TEST2

仍是3077行,也就是说TEST2比TEST在关联时多做多285K*3073次比较。如将TEST2不进行视图合并,则与TEST一样了。
SQL> SELECT b.b, /*test3*/ max(b.ID) - min(b.ID) min_used FROM big b, (SELECT /*+no_merge*/ DISTINCT E.A FROM E WHERE E.A LIKE '1%') M
  2    WHERE b.A>=3 AND b.A<=4 AND b.b= M.A GROUP BY b.b;

         B   MIN_USED
---------- ----------
         1     999804
        11     999978
        12     999804
        10     999978

SQL> @c:\pln test3
old   6: where upper(sql_text) like '%&1%'
new   6: where upper(sql_text) like '%test3%'

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

------------------------

SQL_ID  5rwvaxyv2cps0, child number 0
-------------------------------------
SELECT b.b, /*test3*/ max(b.ID) - min(b.ID) min_used FROM big b,
(SELECT /*+no_merge*/ DISTINCT E.A FROM E WHERE E.A LIKE '1%') M
WHERE b.A>=3 AND b.A<=4 AND b.b= M.A GROUP BY b.b

Plan hash value: 781819126

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |      1 |        |      4 |00:00:01.00 |    1147 |       |       |          |
|   1 |  HASH GROUP BY        |      |      1 |     13 |      4 |00:00:01.00 |    1147 |   718K|   718K| 1186K (0)|
|*  2 |   HASH JOIN           |      |      1 |    128K|  39410 |00:00:00.96 |    1147 |  1301K|  1301K|  820K (0)|
|   3 |    VIEW               |      |      1 |     13 |      4 |00:00:00.01 |      12 |       |       |          |
|   4 |     HASH UNIQUE       |      |      1 |     13 |      4 |00:00:00.01 |      12 |  1302K|  1302K|  695K (0)|
|*  5 |      TABLE ACCESS FULL| E    |      1 |    500 |   3077 |00:00:00.01 |      12 |       |       |          |
|*  6 |    TABLE ACCESS FULL  | BIG  |      1 |    285K|    285K|00:00:00.26 |    1135 |       |       |          |
-------------------------------------------------------------------------------------------------------------------

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

   2 - access("B"."B"="M"."A")
   5 - filter(TO_CHAR("E"."A") LIKE '1%')
   6 - filter(("B"."A">=3 AND "B"."A"<=4))


27 rows selected.

使用道具 举报

回复
论坛徽章:
30
生肖徽章:猴
日期:2015-03-20 10:13:49ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:31优秀写手
日期:2015-03-07 06:00:14沸羊羊
日期:2015-03-13 13:26:07美羊羊
日期:2015-04-06 20:32:13天蝎座
日期:2015-07-20 12:34:47射手座
日期:2015-09-18 12:38:55乌索普
日期:2016-08-03 07:04:28奥运会纪念徽章:手球
日期:2016-09-26 07:19:26山治
日期:2016-10-19 05:48:10
52#
发表于 2013-9-10 11:06 | 只看该作者
关键是视图内的DISTINCT后有多少行的问题,
一)如果视图内没有相同值,而走视图不合并,则会多了一步DISTINCT操作,如果记录很多,则DISTINCT要多花时间,走视图合并则较快。
二)如果视图内有相同值,DISTINCT后记录行少,走视图不合并,因源表行很少,所以就快。
所以这个CBO是无法做最优选择的,因它无法在执行前计算源表到底有多少行记录。

使用道具 举报

回复
论坛徽章:
30
生肖徽章:猴
日期:2015-03-20 10:13:49ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:31优秀写手
日期:2015-03-07 06:00:14沸羊羊
日期:2015-03-13 13:26:07美羊羊
日期:2015-04-06 20:32:13天蝎座
日期:2015-07-20 12:34:47射手座
日期:2015-09-18 12:38:55乌索普
日期:2016-08-03 07:04:28奥运会纪念徽章:手球
日期:2016-09-26 07:19:26山治
日期:2016-10-19 05:48:10
53#
发表于 2013-9-10 11:30 | 只看该作者
〇〇 发表于 2013-9-10 10:53
lz把你的distinct改为group by 试试看
我的改了以后减法和不做减法计划相同了

看来是GROUP BY能禁止视图合并,而DISTINCT则不能。

使用道具 举报

回复
论坛徽章:
0
54#
 楼主| 发表于 2013-9-10 12:38 | 只看该作者
阿吉2009 发表于 2013-9-10 09:10
没有使用HINT?

没有用HINT

使用道具 举报

回复
论坛徽章:
0
55#
 楼主| 发表于 2013-9-10 12:46 | 只看该作者
〇〇 发表于 2013-9-10 10:53
lz把你的distinct改为group by 试试看
我的改了以后减法和不做减法计划相同了


是的,改过之后计划相同了
多谢大大

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
56#
发表于 2013-9-10 12:48 | 只看该作者
阿吉2009 发表于 2013-9-10 11:30
看来是GROUP BY能禁止视图合并,而DISTINCT则不能。

都能视图合并,complex view merge,限制比较多而已

使用道具 举报

回复
论坛徽章:
484
ITPUB北京香山2007年会纪念徽章
日期:2007-01-24 14:35:02ITPUB北京九华山庄2008年会纪念徽章
日期:2008-01-21 16:50:24ITPUB北京2009年会纪念徽章
日期:2009-02-09 11:42:452010新春纪念徽章
日期:2010-03-01 11:04:552010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-04 13:35:54ITPUB9周年纪念徽章
日期:2010-10-08 09:28:512011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:54
57#
发表于 2013-9-10 15:04 | 只看该作者
distinct的效率要比group by慢一些,据说在9i上也如是

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
58#
发表于 2013-9-10 15:05 | 只看该作者
lastwinner 发表于 2013-9-10 15:04
distinct的效率要比group by慢一些,据说在9i上也如是

一样的啊

http://asktom.oracle.com/pls/ask ... N_ID:32961403234212

使用道具 举报

回复
论坛徽章:
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
59#
发表于 2013-9-10 16:49 | 只看该作者
--目前最快
select /*+ gather_plan_statistics */b.b,
        max(b.id) - /*很慢*/
        min(b.id) min_used
   from big b
where b.a>=3
    and b.a<=4
and exists(select  1
           from e m
         where m.a like '1%'  and b.b= m.a)
group by b.b;

使用道具 举报

回复
论坛徽章:
30
生肖徽章:猴
日期:2015-03-20 10:13:49ITPUB 11周年纪念徽章
日期:2012-10-23 16:55:31优秀写手
日期:2015-03-07 06:00:14沸羊羊
日期:2015-03-13 13:26:07美羊羊
日期:2015-04-06 20:32:13天蝎座
日期:2015-07-20 12:34:47射手座
日期:2015-09-18 12:38:55乌索普
日期:2016-08-03 07:04:28奥运会纪念徽章:手球
日期:2016-09-26 07:19:26山治
日期:2016-10-19 05:48:10
60#
发表于 2013-9-10 18:21 | 只看该作者
〇〇 发表于 2013-9-10 16:49
--目前最快
select /*+ gather_plan_statistics */b.b,
        max(b.id) - /*很慢*/

为何说这样是最快的?我觉得跟视图不合并差不多一样快。你这句走的是HJ SEMI,但驱动表E有3077条记录,而视图不合并尽管走的是HJ,比HJ SEMI慢,但他的驱动表只有4条啊,全比较4条与半比较3077条哪个更快呢?往极端想,如果E有5W记录,DISTINCT后也是4条,那么走视图不合并要快些,如E表只有4条且都不相同,那么你这句就快些了。

使用道具 举报

回复

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

本版积分规则 发表回复

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