楼主: nyfor

[精华] 很少受关注的SQL中一些函数调用秘密

[复制链接]
论坛徽章:
33
劳斯莱斯
日期:2013-08-08 14:01:23三菱
日期:2013-09-28 10:16:06一汽
日期:2013-11-19 17:01:11凯迪拉克
日期:2013-12-07 17:11:282014年新春福章
日期:2014-02-18 16:42:02马上有房
日期:2014-02-18 16:42:02itpub13周年纪念徽章
日期:2014-09-27 14:20:21itpub13周年纪念徽章
日期:2014-10-08 15:13:38懒羊羊
日期:2015-03-04 14:52:112015年新春福章
日期:2015-03-06 11:58:18
31#
发表于 2008-9-9 13:12 | 只看该作者
MARK

使用道具 举报

回复
论坛徽章:
9
六级虎吧徽章
日期:2009-01-03 20:00:34
32#
发表于 2008-9-9 17:40 | 只看该作者
强贴帮顶!学习!

使用道具 举报

回复
论坛徽章:
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
33#
发表于 2008-9-9 21:50 | 只看该作者
原帖由 nyfor 于 2008-9-9 10:40 发表

1000次调用和10次调用当然有性能上的区别, 我说的不太重要的原因是说 不会影响到结果的正确性, 也就是说至少不会让我们的代码出现BUG.


嗯,看出来了,你的目标就是没有蛀牙。接下来你也许就会追求美白了

任何秘技和偏方的存在都说明ORACLE的优化器还有可改善的余地。如果11G能够让我们摈弃SELECT (SELECT f(x) FROM DUAL) ... 这种怪怪的写法,那倒是一种进步。

使用道具 举报

回复
论坛徽章:
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
34#
发表于 2008-9-9 21:54 | 只看该作者
原帖由 dreamroot 于 2008-9-9 10:24 发表
虽然我是菜鸟,但感觉你的研究很无聊和没有必要性。一般很少有人会用dbms_random.value进行随机查询的。而且在dbms_random.value

的确如您所言,where dbms_random.value<dbms_random.value 没有任何实用意义,这纯粹就是为了好玩。其中的乐趣等你多写一些不好玩的代码,就会慢慢体会到了。
这个看似无聊的问题引发了一些有实用意义的探索,其价值参见我#26的结论。
如果你做了几年开发仍然无法体会到这些乐趣和价值,那么恭喜你!你证明了自己适合当领导!

使用道具 举报

回复
35#
发表于 2008-9-9 22:59 | 只看该作者
看得我发晕

使用道具 举报

回复
论坛徽章:
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
36#
发表于 2008-9-10 03:16 | 只看该作者
刚才试了下,NO_MERGE HINT确实起作用了,但它不能防止ORACLE把  filter("N"=1) 改写为 filter("PKG"."INC_N"()=1),因此出来的答案总是不对劲。

任何分析函数也能够和ROWNUM一样起作用:

exec pkg.reset_n;

select * from (select pkg.inc_n n, count(*) over() from t) v where n = 1;

使用道具 举报

回复
论坛徽章:
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
37#
发表于 2008-9-10 03:54 | 只看该作者
能否做几个 9I 下DETERMINISTIC函数的试验?

[ 本帖最后由 newkid 于 2008-9-10 07:34 编辑 ]

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
38#
 楼主| 发表于 2008-9-10 09:02 | 只看该作者
原帖由 newkid 于 2008-9-9 21:50 发表


嗯,看出来了,你的目标就是没有蛀牙。接下来你也许就会追求美白了

任何秘技和偏方的存在都说明ORACLE的优化器还有可改善的余地。如果11G能够让我们摈弃SELECT (SELECT f(x) FROM DUAL) ... 这种怪怪的写法,那倒是一种进步。

嗯, 有道理, 刚开始正常书写SQL, 发现结果错误, 理所当然的是先要求结果的正确性, 但当出现性能问题后, 就会去追求所谓的"美白"了

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
39#
 楼主| 发表于 2008-9-10 09:17 | 只看该作者
原帖由 newkid 于 2008-9-10 03:16 发表
刚才试了下,NO_MERGE HINT确实起作用了,但它不能防止ORACLE把  filter("N"=1) 改写为 filter("PKG"."INC_N"()=1),因此出来的答案总是不对劲。

任何分析函数也能够和ROWNUM一样起作用:

exec pkg.reset_n;

select * from (select pkg.inc_n n, count(*) over() from t) v where n = 1;

奇怪, 我怎么没发现NO_MERGE 起作用了呢, 我不管加不加, 其执行计划的 Access predicates, Filter predicates 没有任何变化, 都是 Filter("SCOTT"."PKG"."INC_N"() = 1)

9i, 10g 环境下我测试出都这样.

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
40#
 楼主| 发表于 2008-9-10 09:24 | 只看该作者
原帖由 newkid 于 2008-9-10 03:54 发表
能否做几个 9I 下DETERMINISTIC函数的试验?

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as scott

SQL>
SQL> create or replace package pkg
  2  is
  3    function get_n return number;
  4    function inc_n return number deterministic;
  5    procedure reset_n;
  6  end;
  7  /

Package created
SQL> create or replace package body pkg
  2  is
  3    g_n number;
  4    function get_n return number
  5    is
  6    begin
  7      return g_n;
  8    end;
  9  
10    function inc_n return number deterministic
11    is
12    begin
13      g_n := g_n + 1;
14      return g_n;
15    end;
16  
17    procedure reset_n
18    is
19    begin
20      g_n := 0;
21    end;
22  begin
23    g_n := 0;
24  end;
25  /

Package body created
SQL> exec pkg.reset_n;

PL/SQL procedure successfully completed
SQL> select pkg.inc_n from t;

     INC_N
----------
         1
         1
         1

SQL>
以下是在9i上:
Connected to Personal Oracle9i Release 9.2.0.1.0
Connected as scott

SQL>
SQL> create or replace package pkg
  2  is
  3    function get_n return number;
  4    function inc_n return number deterministic;
  5    procedure reset_n;
  6  end;
  7  /

Package created
SQL> create or replace package body pkg
  2  is
  3    g_n number;
  4    function get_n return number
  5    is
  6    begin
  7      return g_n;
  8    end;
  9  
10    function inc_n return number deterministic
11    is
12    begin
13      g_n := g_n + 1;
14      return g_n;
15    end;
16  
17    procedure reset_n
18    is
19    begin
20      g_n := 0;
21    end;
22  begin
23    g_n := 0;
24  end;
25  /

Package body created
SQL> exec pkg.reset_n;

PL/SQL procedure successfully completed
SQL> select pkg.inc_n from t;

     INC_N
----------
         1
         2
         3

SQL>
9i下 声明函数为 deterministic 的语法已经支持, 但是似乎该特性尚未实现.

使用道具 举报

回复

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

本版积分规则 发表回复

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