我有一个包含SELECT语句的PLSQL存储过程,该语句将值插入到表中:
CREATE OR REPLACE PROCEDURE welcome_msg ()
IS
BEGIN
INSERT INTO TABLE1 (
SELECT DIFFERENT FIELDS
FROM TABLE2 T1, TABLE3 T2
WHERE
T1.NAME = T2.NAME
AND T1.REGNO = T2.REGNO
AND T1.TIMESTAMP1 > CURRENT_TIMESTAMP - 1 day
)
END;
此存储过程将在几分钟内运行,但是如果我在外部执行SELECT
SQL查询,则将花费更多时间来执行:
SELECT DIFFERENT FIELDS
FROM TABLE2 T1, TABLE3 T2
WHERE
T1.NAME = T2.NAME
AND T1.REGNO = T2.REGNO
AND T1.TIMESTAMP1 > CURRENT_TIMESTAMP - 1 day
查询执行时间大于存储过程执行时间,因为Oracle PLSQL是编译版本,所以确定查询计划吗?还是我的观察错误?
答案 0 :(得分:0)
正如一些人评论的那样,这里有两个可能的嫌疑人:更改计划和返回行的时间。对于这样一个简单的查询,似乎很可能是通过网络传递行的时间是罪魁祸首。
因此,执行一些测试以查看将完整的数据集从客户端(例如SQL * Plus)与在PL / SQL中获取回来所需的时间是很有用的。有很多方法可以实现这一目标,而机智的开发人员一定会找到合适的方法。我在这里提供了一种使用V $表的方法,可以使人们清楚地了解Oracle的工作。
了解网络缓慢对查询的影响的一种方法是检查会话生成的各种等待事件。
注意:您需要访问V$SESSION_EVENTS
才能使此特定方法起作用。
使用您选择的工具连接到数据库并获取当前会话ID:
SELECT SYS_CONTEXT ('USERENV', 'SID') FROM DUAL;
现在运行非常慢的查询,确保将所有行带回。
如果您使用的是SQL * Plus,则可能要使用SET AUTOTRACE TRACEONLY
才能查看计划和统计信息,但看不到数据飞散。 SQL * Plus仍将拉动整个网络中的行,只是避免显示它们。
慢查询完成后,进入另一个连接并运行此查询:
select wait_class, event, total_waits, time_waited from v$session_event where sid = <SID from first query>;
这是我故意运行大量数据查询后的结果示例:
WAIT_CLASS EVENT TOTAL_WAITS TIME_WAITED
----------- --------------------------------- ----------- -----------
User I/O Disk file operations I/O 8 0
Application enq: KO - fast object checkpoint 1 0
Commit log file sync 2 0
User I/O db file sequential read 147 9
User I/O db file scattered read 491 50
User I/O direct path read 146 6
Network SQL*Net message to client 2072 0
Network SQL*Net more data to client 618 8
Idle SQL*Net message from client 2071 50067
Other events in waitclass Other 1 0
时间以1/100秒为单位。 有趣的是花费在“来自客户端的SQL * Net消息”中的时间...表示等待SQL * Plus说“感谢这些行,请给我更多信息”的时间
列为“用户I / O”的时间与数据库读取有关。 “系统I / O”与数据库写入有关。
在此示例中,很明显,大部分时间都花在了将行发送到SQL * Plus上。
请注意,这些时间并不能解决所有问题:SQL运行的总时间包括等待时间和CPU,因此这组事件等待不显示任何CPU时间。但是,如果我们只对不同等待事件的相对时间感兴趣,那么它就做得很好。
此外,整个会话的等待时间是累积的,因此请确保在运行测试SQL时已连接测试会话,并立即检查V$SESSION_EVENTS
数据,因为可能需要更多的等待时间积累与您的考试无关的东西。