0

基本的にテストデータベース用に大量のデータを生成するC#アプリがあります。Oracle.DataAccessバージョン4.112.3.0を使用しています

30回の挿入ごとに奇妙な理由で、OracleCommand.ExecuteNonQuery()ステートメントが秒間渡されます。場合によっては15秒話します!

DSNを介して汎用ODBC接続を使用する場合、この問題は発生しませんでした。Oracleクライアントがインストールされていないシステムでもこのアプリケーションを動作させたいので、DSNの使用に戻ることはできません。

どんな助けでも大歓迎です

接続クラスのコード、接続のオープンと挿入の実行を処理します-SQLServerとOracleの両方で機能するようにセットアップします

public Connection(string username,
            string password,
            string serverAddress,
            String servicename,
            string qual)
        {
            uid = username;
            pwd = password;
            server = serverAddress;
            oraServiceName = servicename;
            qualifier = qual;
            string oradb = "Data Source=(DESCRIPTION="
                             + "(ADDRESS=(PROTOCOL=TCP)(HOST=" + serverAddress + ")(PORT=1521))"
                             + "(CONNECT_DATA=(SERVICE_NAME="+servicename+")));"
                             + "User Id=" + username + ";Password=" + password + ";";
                oraConn = new OracleConnection(oradb);
                oraCom = new OracleCommand("",oraConn);
                oraCom.CommandType = System.Data.CommandType.Text;


        } 
public void doInsert(string s)
        {

            try
            {
                sqlCom.CommandText = s;
                sqlCom.Connection = sqlConn;
                sqlCom.ExecuteNonQuery();
            }
            catch (NullReferenceException e)
            {
                try
                {
                    oraCom.CommandText = s;
                   // oraCom.Connection = oraConn;

                    oraCom.ExecuteNonQuery();

                }
                catch (NullReferenceException e2)
                {
                    throw e2;
                }
            }

        }

実際に挿入を行うコード

public void generateData()
    {
        try
        {
            indivID = GenerateId();
            conn.openConn();
            conn.doInsert(tData.insertIndividual());
            //number of calls
            for (long x = 0; x < numCalls; x++)
            {
                countCalls++;
                callidkey = GenerateId();

                //start segments
                for (long y = 0; y < numSegments; y++)
                {
                    if (countSegs != numSegments)
                    {
                        countSegs++;
                    }
                    else
                    {
                        countSegs = 0;
                    }
                    INTX_ID = GenerateId();
                    conn.doInsert(this.tData.insertINTXSEGMENT());
                    //start parts and recordings
                    for (long n = 0; n < numParts; n++)
                    {

                       // INTX_PART_ID = GenerateId();
                        conn.doInsert(tData.insertINTXPART());
                        if (countParts != numParts)
                        {
                            countParts++;
                        }
                        else
                        {
                            countParts = 0;
                        }
                        if (genRec)
                        {

                            recData.recordingid = GenerateId();
                            conn.doInsert(recData.insertRecData());
                            conn.doInsert(recData.insertRecPart());
                            if (countRecs != numParts)
                            {
                                countRecs++;
                            }
                            else
                            {
                                countRecs = 0;
                            }
                        }
                    }
                }
            }
        }
        catch (Exception)
        {}
        }
    }
4

1 に答える 1

1

私はプログラマーではなく、ただのデータベース管理者です。覚えておくべきことがいくつかあります。

  1. 可能な場合は開いている接続を再利用します - 接続管理には時間がかかります。
  2. できれば一括収集で、挿入にバインド変数を使用してください。

これら 2 つの単純なルールを実装した場合、次に確認することは、データベースのオンライン redolog ファイルのサイズです。デフォルトは 512KB です。それらがいっぱいになると、次の REDO ファイルに空きができるまでアプリがフリーズします。やり直しはラウンドロビン方式で使用されます。データベースがアーカイブログモードの場合、それらがいっぱいになるとアーカイブにコピーされます。これにより、多くの挿入を行うときに速度が低下する可能性があります。

データベースのログモードを確認します。

select log_mode from v$database;

REDO サイズとグループ数を確認します。

select group#, bytes, first_time from v$log;

やり直しは非常に高速なストレージにある必要があります。シーケンシャルioのみを行っています。REDO が通常の負荷に比べて小さい場合は、そのサイズを増やします。(通常、15 分ごとに約 1 回のログ切り替えを目指しています) 常にそれ以上のログ切り替えがある場合は、サイズを増やします。通常、1 時間に約 4 つのスイッチがあり、自分の負荷だけですぐにいっぱいになる場合は、ログ グループを追加します。

于 2012-05-10T15:02:41.013 に答える