-- 效率就是效率!--

luoyoumou 2010-12-09 03:02:44
-- 看到人家写的一个存储过程,只看两行,就看不下去啦......
CREATE OR REPLACE PROCEDURE "MUSIC"."LOGIN_STAT"
is
v_sum number(18);
v_shu number(18);
v_begintime date;
v_current date;
str_sql varchar2(2000);
begin
str_sql:='alter session set nls_date_format = ''yyyy-mm-dd''';
execute immediate str_sql;
select to_char(sysdate,'yyyy')||'-'||to_char(sysdate,'mm')||'-'||'01' into v_begintime from dual;
select to_char(sysdate-1,'yyyy-mm-dd') into v_current from dual;
...

end;
/

-- 测试:
----------------------------1 : 验证是否相等:------------------------------------
ALTER SESSION SET NLS_DATE_FORMAT='yyyy-mm-dd';

DECLARE
v_begintime_a date;
v_current_a date;

v_begintime_b date;
v_current_b date;
BEGIN
SELECT trunc(sysdate,'MM') INTO v_begintime_a FROM DUAL;
SELECT trunc(sysdate-1) INTO v_current_a FROM DUAL;

select to_char(sysdate,'yyyy')||'-'||to_char(sysdate,'mm')||'-'||'01' into v_begintime_b from dual;
select to_char(sysdate-1,'yyyy-mm-dd') into v_current_b from dual;

IF v_begintime_a <> v_begintime_b THEN
dbms_output.put_line('v_begintime_a <> v_begintime_b');
dbms_output.put_line('v_begintime_a: '||to_char(v_begintime_a,'YYYY-MM-DD HH24:MI:SS')||' v_begintime_b: '||to_char(v_begintime_b,'YYYY-MM-DD HH24:MI:SS'));
ELSE
dbms_output.put_line('v_begintime_a = v_begintime_b');
dbms_output.put_line('v_begintime_a: '||to_char(v_begintime_a,'YYYY-MM-DD HH24:MI:SS')||' v_begintime_b: '||to_char(v_begintime_b,'YYYY-MM-DD HH24:MI:SS'));
END IF;

IF v_current_a <> v_current_b THEN
dbms_output.put_line('v_current_a <> v_current_b');
dbms_output.put_line('v_current_a: '||to_char(v_current_a,'YYYY-MM-DD HH24:MI:SS')||' v_current_b: '||to_char(v_current_b,'YYYY-MM-DD HH24:MI:SS'));
ELSE
dbms_output.put_line('v_current_a = v_current_b');
dbms_output.put_line('v_current_a: '||to_char(v_current_a,'YYYY-MM-DD HH24:MI:SS')||' v_current_b: '||to_char(v_current_b,'YYYY-MM-DD HH24:MI:SS'));
END IF;

END;
/

----------------------------2 : 效率检测:------------------------------------

-- 方法一:
DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;

BEGIN
v_begin_loop_time := sysdate;
FOR i IN 1..1000000 LOOP
select to_char(sysdate,'yyyy')||'-'||to_char(sysdate,'mm')||'-'||'01' into v_begintime from dual;
select to_char(sysdate-1,'yyyy-mm-dd') into v_current from dual;
END LOOP;
v_end_loop_time := sysdate;

dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;
/

v_begin_loop_time: 2010-12-09 09:51:56 v_end_loop_time: 2010-12-09 09:52:34

PL/SQL 过程已成功完成。

-- 执行一百万次循环赋值,执行时间:38秒

----------------------------------
-- 方法二:

DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;

BEGIN
v_begin_loop_time := sysdate;
FOR i IN 1..1000000 LOOP
select to_char(sysdate,'yyyy')||'-'||to_char(sysdate,'mm')||'-'||'01', to_char(sysdate-1,'yyyy-mm-dd') into v_begintime, v_current from dual;
END LOOP;
v_end_loop_time := sysdate;

dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;
/


v_begin_loop_time: 2010-12-09 09:53:31 v_end_loop_time: 2010-12-09 09:53:52


-- 执行一百万次循环,执行时间:21秒

----------------------------------
-- 方法三:

DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;

BEGIN
v_begin_loop_time := sysdate;
FOR i IN 1..1000000 LOOP
select trunc(sysdate,'MM'), trunc(sysdate-1) into v_begintime, v_current from dual;
END LOOP;
v_end_loop_time := sysdate;

dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;
/

v_begin_loop_time: 2010-12-09 09:56:57 v_end_loop_time: 2010-12-09 09:57:13

PL/SQL 过程已成功完成。

-- 执行一百万次循环,执行时间:16秒

----------------------------------
-- 方法三:

DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;

BEGIN
v_begin_loop_time := sysdate;
FOR i IN 1..1000000 LOOP
select trunc(sysdate,'MM'), trunc(sysdate-1) into v_begintime, v_current from dual;
v_begintime := trunc(sysdate,'MM');
v_current := trunc(sysdate-1);
END LOOP;
v_end_loop_time := sysdate;

dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;
/

v_begin_loop_time: 2010-12-09 10:05:36 v_end_loop_time: 2010-12-09 10:05:58

PL/SQL 过程已成功完成。

-- 执行一百万次循环,执行时间:22秒

----------------------------------
-- 方法四:

DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;
v_sql VARCHAR2(500);
BEGIN
v_begin_loop_time := sysdate;
v_sql := 'select trunc(sysdate,''MM''), trunc(sysdate-1) from dual';
FOR i IN 1..1000000 LOOP
EXECUTE IMMEDIATE v_sql INTO v_begintime, v_current;
END LOOP;
v_end_loop_time := sysdate;
dbms_output.put_line('v_begintime: '||to_char(v_begintime,'YYYY-MM-DD HH24:MI:SS')||' v_current: '||to_char(v_current,'YYYY-MM-DD HH24:MI:SS'));
dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;
/
...全文
422 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
zh_666 2010-12-23
  • 打赏
  • 举报
回复
我也测试了一下 方法三 在我的机子上要快点
碧水幽幽泉 2010-12-22
  • 打赏
  • 举报
回复
不错的实验,如果LZ能把帖再格式化成SQL下就更好了!
liuyi8903 2010-12-10
  • 打赏
  • 举报
回复
目的是什么?
luoyoumou 2010-12-09
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 lxyzxq2008 的回复:]
SQL code

--为虾米我的第三种执行了这么长时间呢?
SQL> DECLARE
2 v_begintime date;
3 v_current date;
4
5 v_begin_loop_time date;
6 v_end_loop_time date;
7
8 BEGIN
9 v_begin……
[/Quote]


-- 不同的机器,其性能也不一样,只是在同样的测试环境:用各种方法的执行时间去比较就行啦!
lxyzxq2008 2010-12-09
  • 打赏
  • 举报
回复

--为虾米我的第三种执行了这么长时间呢?
SQL> DECLARE
2 v_begintime date;
3 v_current date;
4
5 v_begin_loop_time date;
6 v_end_loop_time date;
7
8 BEGIN
9 v_begin_loop_time := sysdate;
10 FOR i IN 1..1000000 LOOP
11 select trunc(sysdate,'MM'), trunc(sysdate-1) into v_begintime, v_current from dual;
12 END LOOP;
13 v_end_loop_time := sysdate;
14
15 dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS'
)||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));
16
17 END;
18 /
v_begin_loop_time: 2010-12-09 18:17:22 v_end_loop_time: 2010-12-09 18:18:09

PL/SQLプロシージャが正常に完了しました。
iqlife 2010-12-09
  • 打赏
  • 举报
回复
测试下,,,,下个月。。。
  • 打赏
  • 举报
回复
方法一和方法二.....
icyjhl 2010-12-09
  • 打赏
  • 举报
回复
我测了下,第四种要更快,这是为啥呢?
gelyon 2010-12-09
  • 打赏
  • 举报
回复
--个人理解:
总的来说To_Char()比较耗时间,因为对日期型进行了格式转换成字符型
Trunc()由于也是格式转换,但是没有进行类型转换,转换格式后仍然是日期型的

至于一条SQL能转换的,用两条,当然要耗多一点时间的
gelyon 2010-12-09
  • 打赏
  • 举报
回复


-- 测试:
----------------------------1 : 验证是否相等:------------------------------------

PL/SQL block, executed in 0.015 sec.
v_begintime_a = v_begintime_b
v_begintime_a: 2010-12-01 00:00:00 v_begintime_b: 2010-12-01 00:00:00
v_current_a = v_current_b
v_current_a: 2010-12-08 00:00:00 v_current_b: 2010-12-08 00:00:00
Total execution time 0.031 sec.

----------------------------2 : 效率检测:------------------------------------

-- 方法一:

PL/SQL block, executed in 01:3.391 (63.391 sec.)
v_begin_loop_time: 2010-12-09 15:14:39 v_end_loop_time: 2010-12-09 15:15:43
Total execution time 01:3.407 (63.407 sec.)


-- 方法二:

PL/SQL block, executed in 36.266 sec.
v_begin_loop_time: 2010-12-09 15:13:28 v_end_loop_time: 2010-12-09 15:14:05
Total execution time 36.281 sec.

-- 方法三:

PL/SQL block, executed in 27.094 sec.
v_begin_loop_time: 2010-12-09 15:12:13 v_end_loop_time: 2010-12-09 15:12:40
Total execution time 27.125 sec.


-- 方法四:

PL/SQL block, executed in 36.859 sec.
v_begin_loop_time: 2010-12-09 15:10:55 v_end_loop_time: 2010-12-09 15:11:31
Total execution time 36.907 sec.

----------------------------------
-- 方法五:

PL/SQL block, executed in 28.376 sec.
v_begintime: 2010-12-01 00:00:00 v_current: 2010-12-08 00:00:00
v_begin_loop_time: 2010-12-09 15:09:43 v_end_loop_time: 2010-12-09 15:10:11
Total execution time 28.391 sec.


--结论:
方法三最优!方法一最差!
minitoy 2010-12-09
  • 打赏
  • 举报
回复
哦,已经alter session了..
minitoy 2010-12-09
  • 打赏
  • 举报
回复
程序有问题啊.方法一和方法二怎么把把varchar2放date变量里?
Diza1986 2010-12-09
  • 打赏
  • 举报
回复
罗师傅
心中的彩虹 2010-12-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wkc168 的回复:]
引用 2 楼 luoyoumou 的回复:
-- 我是希望各位去测试,效率:需要用事实说话!


罗哥已经测试完毕

SQL code

---最优
--已用时间: 00: 00: 21.62 ---第三种
DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_e……
[/Quote]
to_char 费时原因: 我的理解 首先把日期类型的转为字符(多在这步) 在修改成后面的格式 所以费时
多在前面一步 转类型

trunc 对类型不变 只是取后面对应格式的值 所以花费时间少

所以总结 能用trunc则尽量
心中的彩虹 2010-12-09
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 luoyoumou 的回复:]
-- 我是希望各位去测试,效率:需要用事实说话!
[/Quote]

罗哥已经测试完毕

---最优
--已用时间: 00: 00: 21.62 ---第三种
DECLARE
v_begintime date;
v_current date;

v_begin_loop_time date;
v_end_loop_time date;

BEGIN
v_begin_loop_time := sysdate;
FOR i IN 1..1000000 LOOP
select trunc(sysdate,'MM'), trunc(sysdate-1) into v_begintime, v_current from dual;
END LOOP;
v_end_loop_time := sysdate;

dbms_output.put_line('v_begin_loop_time: '||to_char(v_begin_loop_time,'YYYY-MM-DD HH24:MI:SS')||' v_end_loop_time: '||to_char(v_end_loop_time,'YYYY-MM-DD HH24:MI:SS'));

END;


luoyoumou 2010-12-09
  • 打赏
  • 举报
回复
-- 我是希望各位去测试,效率:需要用事实说话!
gelyon 2010-12-09
  • 打赏
  • 举报
回复
罗哥,你是在分享吗?

3,490

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧