【问题标题】:Pro*C performance differencesPro*C 性能差异
【发布时间】:2012-01-10 16:03:04
【问题描述】:

我在以下场景中运行,这让我很头疼,因为我找不到我所看到的行为的确切解释。我声明了以下内容:

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;

第二次的表现相差很大。

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

【问题讨论】:

    标签: c++ c oracle oracle10g oracle-pro-c


    【解决方案1】:

    对于乍一看无法解释的性能问题:打开包括等待在内的 sql 跟踪。

    ALTER SESSION SET TRACEFILE_IDENTIFIER = "some_unique_identifier";
    dbms_support.start_trace (binds=>true,waits=>true);
    

    运行您的代码,使其提交并优雅地断开连接。不要使用 dbms_support.stop_trace,因为它可能会阻止行源操作的假脱机。 在生成的跟踪文件中,您将找到准确的 sql 文本,因为它被解析,等待影响 sql 和行源操作的事件。行源操作显示了运行 sql 时 sql 计划的准确程度。

    • 检查解析次数
    • 检查是否使用了绑定变量。
    • 检查预期计划的行源操作。

    对于您的问题 - 必须以随机方式一一获取大量行 - 我希望找到

    • 1 个游标声明
    • 1 次解析
    • 打开/获取/关闭游标的循环

    对于这些场景来说,不要解析每个选择是非常重要的。解析可能比执行花费更多时间。

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

    【讨论】:

    • 因为这是由其他人设计的,并且尝试重新设计此解决方案将花费大量时间,而且这不是数据复制操作。不幸的是,这更多地用于 IPC。不要拍我没有想出这个的信使......
    • 尝试按照描述进行跟踪并检查结果。我身边没有射击,我平静地来了;-)
    • 解析过多。另外,如果您返回的不是 1,而是许多 varchar 字段,它会减慢速度。除了我们已经知道使用的字段数量之外。
    • 它经常被忽略,但解析可以使数据库停止。这是扼杀扩展的最大问题之一。它序列化。你能解决它吗?
    • 我认为重新构建我现在正在从事的……………………项目中的一个部分还有很长的路要走。跨度>
    【解决方案2】:

    您是否考虑了缓存的影响?我想不会。

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

    这是因为 where 谓词在两个查询中是相同的,并且结果集中的数据在两个查询中是相同的。通常后续查询相同的查询在您针对索引查询时运行得更快,因为您从不去表获取结果集,它来自缓存它的 SGA。

    尝试为 testvar1_param 使用不同的值,并使用完全不同的 parm 值对每个 from 运行 10 次查询。它们会在时间上非常非常接近。

    你使用的是 tkprof 对吗?

    【讨论】:

    • 我正在考虑缓存的影响。在执行前后使用 gettimeofday() 完成的计时。查询在同一组数据上运行多天,期间数据库重新启动。而 testvar1_param 是随机的。
    • 肯定有其他事情在发生——我不会在 9i 和 11g 下运行你的代码,在一个有 2200 万行和随机参数的表上。 PS:始终打开 sqltrace(和计时),然后通过 tkprof 运行 .trc 文件。墙上的时间是骗人的。你的获取时间不同吗?什么甲骨文版本?
    • 我正在计时个人提取时间,因为个人提取时间在 5 到 100 毫秒之间变化。第二个在 4ms 左右相当一致。 Oracle 版本为 10.2.0.4
    【解决方案3】:

    我的意思是时机(因为它是开发,对吗?)

    ALTER SYSTEM SET TIMED_STATISTICS = TRUE;
    

    这改进了 oracle 在性能跟踪方面为您提供的功能。

    【讨论】:

    • 您可能想要合并两个答案。
    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    • 2015-05-18
    • 2010-10-15
    • 1970-01-01
    • 2011-01-21
    • 2011-08-08
    相关资源
    最近更新 更多