1

私は次のシナリオで実行していますが、私が見ている動作の正確な説明が見つからないため、かなりの頭痛の種になります。私は次のように宣言しています:

struct test_struct
{
    long testv1;
    char testv2[51];
    long testv3;
};

およびOracle10gの対応するテーブル:

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;

2番目のパフォーマンスは、大幅に異なります。

誰かがこの振る舞いを説明できるものを知っていますか?

4

3 に答える 3

1

キャッシングの影響を考慮していますか?私はそうではないと思います。

最初のクエリをtimedで実行し、次に2番目のクエリをtimedで実行すると、testvar1_paramの値は同じになり、2番目のクエリは著しく異なる時間で完了します。どのクエリが最初に実行されるかは関係ありません。2番目のバージョンの方がうまくいきます。

これは、where述語が両方のクエリで同じであり、結果セットのデータが両方のクエリで同じであるためです。通常、後続のクエリの同一のクエリは、インデックス付きクエリに対して実行するときにはるかに高速に実行されます。これは、結果セットを取得するためにテーブルに移動することがないためです。結果セットは、キャッシュされているSGAから取得されます。

testvar1_paramに異なる値を使用してみて、完全に異なるparm値でそれぞれから10個のクエリを実行してください。彼らは時間的に非常に近いでしょう。

tkprofを使っていますよね?

于 2012-01-10T17:50:49.440 に答える
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プランがどのように表示されたかを示します。

  • 解析の数を確認してください
  • バインド変数が使用されているかどうかを確認します。
  • 予想される計画のrowsource操作を確認してください。

あなたの問題のために-ランダムな方法で1つずつたくさんの行をフェッチする必要があります-私は見つけることを期待しています

  • 1カーソル宣言
  • 1解析
  • カーソルを開く/フェッチする/閉じるループ

これらのシナリオでは、すべての選択を解析しないことが非常に重要です。解析は実行よりも時間がかかる場合があります。

残っている1つの質問は、なぜすべての行を1つずつ取得するのかということです。これはある種のデータコピー操作ですか?

于 2012-01-11T07:56:54.227 に答える
0

タイミングとは(開発だからですよね?)

ALTER SYSTEM SET TIMED_STATISTICS = TRUE;

これにより、オラクルがパフォーマンスのトレースで提供するものが改善されます。

于 2012-01-10T18:47:19.050 に答える