0

うまくいけば、誰かが私が現在Oracle DBで抱えている問題に少し光を当てることができます-それは簡単なことだと確信しています!!

サンプルでこれを再現できたので、DB構造は次のとおりです。

CREATE TABLE MyTable(
    ixMyTable NUMBER,
    clobData CLOB
)
/

CREATE OR REPLACE PACKAGE PKGTEST
AS
    PROCEDURE DoSomething(
        cur_OUT OUT SYS_REFCURSOR
        );
END PKGTEST;
/

CREATE OR REPLACE PACKAGE BODY PKGTEST
AS

PROCEDURE DoSomething(
    cur_OUT OUT SYS_REFCURSOR
)
AS
BEGIN
    OPEN cur_OUT FOR 
        SELECT ixMyTable, clobData
        FROM MyTable;
END;

END PKGTEST;
/

GRANT EXECUTE ON PKGTEST TO TEST_ROLE
/

BEGIN
    FOR i IN 1 .. 7000 LOOP
        insert into mytable values (i, TO_CLOB('123456'));
    END LOOP;
END;
/

追加情報:

スキーマの所有者は TEST_SCHEMA です

ユーザーはカール

CARL には TEST_ROLE ロールがあります

上記のようにデータベースをセットアップすると、標準の System.Data.OracleClient.OracleCommand などを使用して PKGTEST.DoSomething を実行し、結果をデータグリッド (DevExpress) にスローする C# テスト アプリがあります。

オープン ソース OTL (幸いなことに、私の部門ではありません) を使用して c++ を介して同じ問題が発生するため、グリッドはここでは無関係であることを確認してください。

さて、問題に....

最初からグリッドにデータが入力されるまでの時間は 35 ~ 40 秒です。

ただし、次のようにすると:

GRANT SELECT ON MyTable TO TEST_ROLE
/

クエリを再度実行すると、5 ~ 6 秒かかります。

これは特権などと関係があるように思えますが、なぜ実際に両方の方法で機能するのかよくわかりません??

手順を次のように変更すると、ポットに何か他のものを投入するだけです

SELECT ixMyTable, TO_CLOB(TO_NCLOB(clobData))
FROM MyTable;

その後、追加の SELECT 権限の有無にかかわらず、時間は 5 ~ 6 秒です。

任意のポインタまたは直接的なソリューションをいただければ幸いです!

編集:

OSはVista x86 Business

Oracle サーバーは 10.2.0.1 です

Oracle クライアントは 10.2.0.3 です

編集:

提案されているように、MS OracleClient から ODP.NET に変更してみましたが、必要に応じて速度が向上します。

残念ながら、影響を受けた C# アプリは、テーブルの表示や SPROCS の実行などに使用される内部アプリにすぎませんでした。

主な成果物は、データベース アクセスにOTL ( http://otl.sourceforge.net/otl3_intro.htm ) を使用する C++ アプリです。これは現時点で変更できるものではないため、不当な GRANT SELECT を意に介さずに、違いの理由を理解したいと思います。

SELECT 権限がないために完全な障害が発生した場合は、おそらくこれを受け入れることができますが、SELECT 権限がないために、CLOB データにアクセスするためのルートが遅くなるようです。

私は3つの答えをマークアップしました-それらに感謝します-しかし、私は本当に理由でできるので、これに賞金を追加します.

PS C++ の最初から OCCI を使いたかったのですが、Oracle は常に最新バージョンより前のバージョンの IDE をサポートしているため、Visual Studio 2008 でうまく動作させることができませんでした。

4

7 に答える 7

7

毎回ディスクから BLOB を読み取っていて、2 回目以降はディスク キャッシュから読み取っていませんか?

私はパフォーマンス テストでこの問題を見てきました。特に、テストの最初の実行がひどい Oracle ではそうです。次に、1 つのマイナーな (そして重要ではないように見える変更) を行うと、パフォーマンスが突然大幅に向上します。しかし、実際には、クエリしているデータがキャッシュに読み込まれ、10 倍または 20 倍のレート (メモリとディスク) でアクセスできるようになっています。

このテストを行う適切な方法は、クエリの実行の間にデータベースをバウンスすることです。DBA がこのテスト用にテスト運用サーバーをバウンスさせない場合は、マシンに Oracle XE のコピーをロードします。

編集:またはそれ以上:毎回テーブルを削除して再作成します。あなたはこれをしているかもしれませんが、それについては言及していません。

于 2009-01-23T18:04:39.350 に答える
1

上記の提案に続いて、別のODBCドライバーまたはクライアントソフトウェアを試すことができますか。TO_CLOB(TO_NCLOB())まっすぐなものではないのに、動作が非常に高速であるという事実は、それが問題が存在する場所であることを示しているようです。

まず、2つのクエリを取得し、SQLDeveloperで実行して、説明プランを取得します。これにより、Oracle側で実行するためのベースラインが得られます。変換を追加しても、実行パスに違いはありません。クエリを交互に実行し、両方の時間を計って、クエリの速度を確認します。違いがなければ、クライアントソフトウェアが問題だと思います。

私の仮定が正しければ、これもGRANT SELECT変化を説明するでしょう。クライアントソフトウェアは、CLOB上である種の高価な変換を実行しています。付与および/または明示的な変換により、クライアントはこれを回避できます。どうしてか分かりません。

于 2009-01-24T13:37:11.760 に答える
1

System.Data.OracleClient の代わりにodp.net http://www.oracle.com/technology/tech/windows/odpnet/index.htmlを試してみます。

于 2009-01-23T19:44:32.423 に答える
0

正直なところ、ここでの問題は、OTL ドライバーと OracleClient が SYS_REFCURSOR からの CLOB を処理する際に問題を抱えていることだと思います。SYS_REFCURSOR は脆弱です。つまり、カーソル自体が任意の型のデータを返すことができます。つまり、ドライバーは継続的にデータベースに戻ってカーソルのメタデータをクエリし (つまり、カーソル内のデータの型を取得する)、CLOB ストリームをロードする必要があります。 、次にデータをロードします。明らかに、クエリを実行しているユーザーがクエリ対象のテーブルにアクセスできる場合、ドライバーはより適切にメタデータを取得して正しいデータを返すことができます。

ストアド プロシージャを変更して強力な ref_cursor を返すことはできますか?

CREATE OR REPLACE PACKAGE PKGTEST
    AS
    TYPE C_DoSomething IS REF CURSOR RETURN MyTable%ROWTYPE;
    PROCEDURE DoSomething(
        cur_OUT OUT c_DoSomething
     );
END PKGTEST;

それもうまくいくように見えるので、ストアドプロシージャを変更して実行できますTO_CLOB()か?

于 2009-01-27T17:45:08.410 に答える