2013-07-06 92 views
3

我在Firebird數據庫上執行INSERT語句的速度很慢。性能值如下:Firebird插入很慢

在帶有Windows XP的筆記本上插入3800條記錄大約需要31秒(每秒約120次插入)。在Windows 7 32位的另一臺PC上,同樣的任務需要80秒(每秒約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表明這種特殊的方法是瓶頸。一次通話需要約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* 

DefaultDbCachePages在firebird.conf 2048

在刪除和插入記錄,fbserver.exe進程充分利用一個CPU內核。

+0

你能更新你的問題包括:如果您使用的是經典,superclassic或超級服務器,數據庫上'gstat -h'的輸出和服務器使用的頁面緩衝區大小(在firebird.conf中設置'DefaultDbCachePages')? –

+0

謝謝你的建議。我更新了我的問題。 – truthseeker

+0

看起來很正常,除了您使用方言1的事實以外,它自2000年以來一直傾向於使用方言3;這不應該導致任何性能問題。 –

回答

0

慢方法的原因不是插入而是在它們之前調用的刪除。這個簡單的SQL命令加快了我的方法幾次。

CREATE INDEX INDEX_RESULTS ON RESULTS (POS, ORD); 

我也會做另一個優化 - 而不是刪除+插入我會用初始插入,然後只更新。同樣在這種情況下,爲索引定義用於解決特定記錄的列是非常重要的。有時索引可以通過幾個命令來加快速度。我做了以下測試:

10000更新,而不指數 - 300秒

10000更新索引 - 1.6秒

0

你有沒有在Windows系統恢復活動?如果是這樣,請嘗試取消激活並查看性能是否更好。數據庫文件也有.GDB擴展名。嘗試將數據庫文件重命名爲.FDB(如果是這種情況)。

+0

禁用「系統還原」服務 - 無效。 數據庫文件擴展名 - 已經使用fdb。 – truthseeker