2012-01-10 65 views
1

我在下面的场景中运行,这让我颇为头疼,因为我无法找到我所看到的行为的确切解释。我有以下声明:Pro * C性能差异

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; 

在第二个表现是由显著边缘不同。

有谁知道什么可以解释这种行为?

回答

1

对于第一眼看不到的性能问题:打开包括等待的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解析
  • 打开一个循环/获取/关闭光标

这些场景对于不分析每个选择非常重要。解析可能需要比执行更多的时间。

剩下的一个问题是:为什么要逐一获取所有行?这是某种数据复制操作吗?

+0

由于这是由其他人构建的,并试图重新构建此解决方案将花费大量时间,这不是数据复制操作。不幸的是,这更多地用于IPC。不要拍摄信使我没有拿出这个... – Karlson 2012-01-11 15:01:26

+0

尝试使描述的痕迹和检查结果。没有拍摄从我身边,我来平安;-) – 2012-01-11 15:21:17

+0

@卡尔森你发现了什么? – 2012-01-13 06:29:09

1

你是否考虑了缓存的影响?我不假设。

如果您运行第一个查询timed,然后运行第二个查询timed,其中testvar1_param值相同,第二个查询完成时间明显不同。首先运行哪个查询并不重要,第二个版本会更好。

这是因为where谓词在两个查询中都是相同的,并且结果集中的数据在两个查询中都是相同的。通常,随后的查询相同的查询在针对索引查询时运行速度会快得多,因为您从不去获取结果集,而是从SGA缓存它。

尝试对testvar1_param使用不同的值,并使用完全不同的parm值运行10个查询。他们将会非常接近时间。

您正在使用tkprof吗?

+0

我正在考虑缓存的影响。在执行前后使用gettimeofday()完成的时间。查询是在多天内对相同的一组数据运行的,其间数据库重新启动。而testvar1_param是随机的。 – Karlson 2012-01-10 17:55:49

+0

必须有其他的事情发生 - 我不会在9i和11g的桌面上运行你的代码,这些代码有2200万行和随机参数。 PS:总是打开sqltrace(和计时),然后通过tkprof运行.trc文件。长城时间在欺骗。你的读取时间不同?什么oracle版本? – 2012-01-10 18:43:38

+0

我个人提取时间取决于个人提取5至100毫秒。第二个在4ms左右相当一致。 Oracle版本是10.2.0.4 – Karlson 2012-01-10 19:46:20

0

通过时间我的意思(因为它是发展的,对不对?)

ALTER SYSTEM SET TIMED_STATISTICS = TRUE; 

这提高了Oracle为您提供了跟踪性能。

+0

您可能想要合并这两个答案。 – Karlson 2012-01-11 15:36:02