膨大な数の SQL クエリを含む Qt(C++) プロジェクトに取り組んでいます。基本的に、これは~ 1000回update()
呼び出される関数です。私のシステムでは、すべての呼び出しに約 25 ~ 30 ミリ秒かかるため、合計実行時間は 30 秒と膨大になります。このルーチンを最適化して時間の消費を減らすことができると思いますが、最適化の方法がわかりません。ここに関数があります-
void mediaProp::update(){
static QSqlQuery q1, q2, q3;
static bool firstCall = true;
static QString stable;
QString table = this->type+"s";
if(firstCall){
stable = table;
q1.prepare("SELECT id FROM titles WHERE lower(title)= lower(:a) AND type = :b COLLATE NOCASE");
q2.prepare("INSERT INTO " + table + "(pic_id, score) VALUES (0, 0)");
q3.prepare("INSERT INTO titles (id, type, title) VALUES (:a, :b, :c)");
firstCall = false;
}
else if(stable != table){
stable = table;
q2.prepare("INSERT INTO " + table + "(pic_id, score) VALUES (0, 0)");
}
q1.bindValue(":a", this->title);
q1.bindValue(":b", dbEnums(this->type));
q1.exec();
q1.last();
int size = q1.at() + 1;
if( size > 0){
q1.first();
this->id = q1.value("id").toInt();
}
else if( !this->title.trimmed().isEmpty() ){
q2.exec();
this->id = q2.lastInsertId().toUInt();
q3.bindValue(":a", this->id);
q3.bindValue(":b", dbEnums(this->type));
q3.bindValue(":c", this->title);
q3.exec();
}
else{
this->id = 0;
}
}
どんな提案や助けも本当に素晴らしいでしょう! ありがとう :)
編集- Yohan Danvinが示唆したように、関数に変更を加え、上記を更新しました。
EDIT2 - Yohan Danvinのコンセプトはスマートで、プリペアド ステートメントを静的変数として使用するとルーチンが最適化されると確信していました。しかし、それは私たちが期待したようには機能しませんでした。時間がかからない代わりに、ルーチン全体に時間がかかりました。準備されたステートメントが事態を悪化させるのは奇妙でした! しかし、その後、多くの掘り下げを行った後、その理由がわかりました-
THE PROCEDURE TOOK 25 MILLISECONDS IN AVERAGE
AFTER USING Yohan's STATIC PREPARED STATEMENT MAPPING PROCEDURE- IT TOOK 27ms IN AVG
記録のために、メモリではなくファイルをデータベースとして使用していました。INSERT クエリが実行されるたびに、QSqlQuery は一時的なダンプ ファイルを作成し、それをメイン データベース ファイルに追加していました。メモリとは対照的にファイルへのアクセスは非常に時間がかかるため、挿入速度は 25 ミリ秒と遅くなりました。Yohan のコンセプトを使用したときは、関数のオーバーヘッドなどでもう少し時間がかかったと思います。間違っていたら教えてください。最後に、私はhttp://www.sqlite.org/pragma.htmlに出会い、いくつかのプラグマパラメーターを変更しました-
QSqlQuery("PRAGMA journal_mode = OFF");
QSqlQuery("PRAGMA synchronous = OFF");
そして、それは魅力のように機能しました!実行速度は、ルーチン コールあたり 25 ミリ秒から 3 ルーチン コールあたり 1 ミリ秒に減少しました。それは大きなギャップです!基本的に を設定すると、 pragma journal_mode = OFF
SQLITE に個別の一時ダンプ ファイルを作成しないように指示しPRAGMA synchronous = OFF
、すべてのクエリが実行された後に変更をデータベースに適用します。場合によっては、一時的なインメモリ データベースを使用します。私が間違っている点を指摘した場合はお知らせください。
ルーチンが145 倍高速になったことを嬉しく思います。