我在下面的场景中运行,这让我很头疼,因为我找不到对所看到的行为的确切解释。我有以下声明:
struct test_struct
{
long testv1;
char testv2[51];
long testv3;
};
以及Oracle 10g:中的相应表
CREATE TABLE test_table
(
testv1 NUMBER(10, 0),
testv2 VARCHAR(50),
testv3 NUMBER(4, 0)
);
要访问此表中的数据,我有一个功能:
bool getTestData(long test_var1, struct test_struct *outStruct)
在这里,我看到了我需要解释但无法解释的差异。如果函数的主体看起来像这样:
EXEC SQL BEGIN DECLARE SECTION;
long testvar1_param = test_var1;
struct test_struct *resStruct = outStruct;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT testv1, testv2, testv3
INTO :resStruct
FROM test_table
WHERE testv1 = :testvar1_param;
如果函数体看起来像:,我会得到较慢的性能
EXEC SQL BEGIN DECLARE SECTION;
long testvar1_param = test_var1;
long *testv1_res = &(outStruct->testv1);
char *testv2_res = outStruct->testv2;
long *testv3_res = &(outStruct->testv3);
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT testv1, testv2, testv3
INTO :testv1_res, :testv2_res, :testv3_res
FROM test_table
WHERE testv1 = :testvar1_param;
第二场比赛的表现大不相同。
有人知道是什么可以解释这种行为吗?
对于乍一看无法解释的性能问题:启用包括等待在内的sql跟踪。
ALTER SESSION SET TRACEFILE_IDENTIFIER = "some_unique_identifier";
dbms_support.start_trace (binds=>true,waits=>true);
运行您的代码,使其提交并优雅地断开连接。不要使用dbms_support.stop_trace,因为它可能会阻止行源操作的后台处理。在生成的跟踪文件中,您将在解析时找到确切的sql文本,等待影响sql和行源操作的事件。rowsource操作显示了运行sql时sql计划的确切外观。
- 检查解析数
- 检查是否使用绑定变量
- 请检查行源操作以获得预期的计划
对于你的问题——必须以随机的方式一个接一个地提取很多行——我希望找到
- 1个游标声明
- 1个解析
- 打开/获取/关闭光标的循环
对于这些场景来说,不解析每个选择是非常重要的。解析可能比执行花费更多的时间。
剩下的一个问题是:为什么要一行接一行地获取所有行?这是某种数据复制操作吗?
您是否考虑了缓存的影响?我想不会。
如果运行第一个定时查询,然后运行第二个定时查询(其中testvar1_param值相同),则第二个在明显不同的时间内完成。先运行哪个查询并不重要,第二个版本会更好。
这是因为where谓词在两个查询中都是相同的,结果集中的数据在两个搜索中都是一样的。通常,当您使用索引查询时,后续查询相同的查询运行得更快,因为您从不去表中获取结果集,它来自缓存结果集的SGA。
尝试对testvar1_param使用不同的值,并使用完全不同的parm值从中运行10个查询。他们很快就会非常接近。
你在用tkprof吧?
我所说的时间是指(既然是开发,对吧?)
ALTER SYSTEM SET TIMED_STATISTICS = TRUE;
这提高了oracle在性能跟踪方面的性能。