3

Firebird データベースでの INSERT ステートメントの実行が遅いという問題があります。パフォーマンス値は次のとおりです。

Windows XP を搭載したノートブックに 3800 件のレコードを挿入するには、約 31 秒かかります (1 秒あたり約 120 件の挿入)。Windows 7 32 ビットを搭載した別の PC では、この同じタスクに 80 秒かかります (1 秒あたり ~ 50 回の挿入)。使用する Firebird のバージョンは、2011 年 10 月から 2.5.1 SuperServer です。使用する接続テクノロジは DBExpress です。

これが私のデータベーステーブルの作成方法です:

CREATE TABLE RESULTS
(
    POS         INTEGER,
    FIELD_CODE  VARCHAR(255),
    FIELD_DESC  VARCHAR(255),
    ORD         INTEGER,
    RVALUE      VARCHAR(2048),
    DETAIL      VARCHAR(2048)
);

そしてこれがそれにアクセスするソースコードです。実際と比較すると多少単純化されていますが (呼び出し元のメソッドは含まれていません)、すべての基本的なことが含まれています。Profiler は、この特定のメソッドがボトルネックであることを示しています。1回の呼び出しには約10ミリ秒かかります。したがって、3800 回の呼び出しには約 38 秒かかります。

Field *field = NULL;
int ord = GetFieldOrder(field_code, &field);
if (field == NULL)
{
   return -1;
}

AnsiString sql;
sql.printf("delete from RESULTS where POS = %d and ord = %d", position, ord);
try
{
   Query_SQL->CommandText = sql;
   Query_SQL->ExecSQL();
}
catch (Exception &e)
{
}

if (field->write_field_code)
{
   field_code.printf("'%s'", field->field_code);
}
else
{
   field_code = "NULL";
}
AnsiString field_description;
if (field->write_field_description)
{
   field_description.printf("'%s'", field->field_description);
}
else
{
   field_description = "NULL";
}
sql.printf("insert into RESULTS (POS, FIELD_CODE, FIELD_DESC, ORD, RVALUE) VALUES (%d, %s, %s, %d, '%08X')", position, field_code, field_description, ord, value);

try
{
   Query_Insert->Params->Items[0]->AsInteger = position;
   Query_Insert->Params->Items[1]->AsString = field_code;
   Query_Insert->Params->Items[2]->AsString = field_description;
   Query_Insert->Params->Items[3]->AsInteger = ord;
   Query_Insert->Params->Items[4]->AsString = value;
   Query_Insert->Params->Items[5]->Clear();
   Query_Insert->ExecSQL();
   // Query_SQL->CommandText = sql;
   // Query_SQL->ExecSQL();
}
catch (Exception &e)
{
   return -1;
}
return 0;

コードのコメント部分からわかるように、SQL クエリをパラメータ化して繰り返し実行を高速化しようとしましたが、大きな変更はありませんでした。すべての呼び出しはトランザクション内にあります。

TDBXTransaction *transaction = DataModule->Database->BeginTransaction();

unsigned int i;
unsigned int c = meters.size();
for (i = 0; i < c; i++)
{
            ...
    DataModule->InsertDefaultValues(meters[i]); // <---- here are our INSERTs
            ...
}

DataModule->Database->CommitFreeAndNil(transaction);
transaction = NULL;

データベース ファイルに対する gstat -h コマンドの出力は次のとおりです。

Database "C:\ELMA\EDEX\CAL_RESULTS.FDB"

Database header page information:

Flags           0
Checksum        12345
Generation      33255
Page size       4096
ODS version     11.2
Oldest transaction  33246
Oldest active       33247
Oldest snapshot     33247
Next transaction    33248
Bumped transaction  1
Sequence number     0
Next attachment ID  60
Implementation ID   16
Shadow count        0
Page buffers        0
Next header page    0
Database dialect    1
Creation date       Jul 6, 2013 12:58:03
Attributes      force write

Variable header data:
*END*

firebird.conf の DefaultDbCachePages は 2048 です。

レコードの削除および挿入中、fbserver.exe プロセスは 1 つの CPU コアを完全に使用します。

4

2 に答える 2

0

Windows で「システムの復元」を有効にしましたか? その場合は、無効にしてパフォーマンスが向上するかどうかを確認してください。拡張子が .GDB のデータベース ファイルにも問題があります。その場合は、データベース ファイルの名前を .FDB に変更してみてください。

于 2013-07-11T08:18:22.287 に答える