Deleting items from database is very slow... #99
-
I don't know if this question belongs here, so please be patient with me. For the clean-up I use this routine (mStateDB is a wxSQLite3Database*): sql.Format("select timestamp from log_db order by timestamp;");
wxSQLite3ResultSet rs = mStateDB->ExecuteQuery(sql);
mStateDB->Begin(); // Defer execution
while ( rs.NextRow() )
{
wxDateTime ts_dt = rs.GetDate(wxT("timestamp"));
wxString ts_str = rs.GetString(wxT("timestamp"));
if ( ts_dt.IsValid() && date_time.IsLaterThan(ts_dt) )
{
sql.Format("delete from log_db where timestamp = %Q;", (const char*)ts_str.mb_str(wxConvUTF8));
mStateDB->ExecuteUpdate(sql);
}
}
mStateDB->Commit(); // Now execute commands It happens that unexpectedly for a database, for just a few thousand deletions this operation is rather slow and takes many seconds, up to half a minute. So I wonder where this slow-down comes from and suspect my code... ;-) Maybe I didn't understand the API, but ->Begin() and ->End() does first collect and than executes DB commands at once, right? Do you have any hints for me? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
Questions, if they are not related directly to the wxSQLite3 wrapper, but to SQLite itself (like about query optimization or performance of certain SQL commands), are usually better asked on the SQLite user forum.
SQLite can handle databases which have many GBs in size, so 10-15 MB should not impose a problem.
Theoretically your code could be to blame, but I doubt it. Are you sure that your application causes the slow-down? For example, SQLite will usually create a rollback journal file for a large transaction. If this triggers your antivirus software, this may explain the problem. Without knowing the database schema it is very difficult to analyze performance issues. There are many reasons that could cause slow-downs like update of index tables, disk I/O, etc. If the code you present is really the SQL code that gets executed, it looks rather inefficient. For example, you retrieve with the outer If you must delete records individually for some reason, I would strongly recommend to use a prepared statement, because this would eliminate the overhead of reparsing the delete command over and over again. Prepared statements can be reused with new values for the bound parameters.
Not exactly. Using a transaction persists all database changes only, when the final commit is executed. That is, you usually have considerably less disk I/O. A minor detail: the |
Beta Was this translation helpful? Give feedback.
-
Finally, for others that also stumble across this one: I improved the situation a lot by doing: mStateDB->Begin(); // Defer execution
sql.Format("select timestamp from log_db order by timestamp;");
wxSQLite3ResultSet rs = mStateDB->ExecuteQuery(sql);
wxSQLite3Statement stmt = mStateDB->PrepareStatement("delete from log_db where timestamp = ?;");
while ( rs.NextRow() )
{
wxDateTime ts_dt = rs.GetDate (wxT("timestamp"));
wxCharBuffer ts_c = rs.GetString(wxT("timestamp")).ToUTF8();
if ( ts_dt.IsValid() && date_time.IsLaterThan(ts_dt) )
{
stmt.Bind(1, ts_c.data());
stmt.ExecuteUpdate();
stmt.Reset();
}
}
mStateDB->Commit(); // Now execute commands Its maybe not perfect (still struggling with date and Thanks again for you help! :-) |
Beta Was this translation helpful? Give feedback.
-
Using prepared statements and bind variables is almost always faster than constructing an SQL string with parameter values. Regarding the where-condition, something like DELETE FROM log_db WHERE timestamp < :date_time; should work (where you bind the user-selected timestamp to the parameter |
Beta Was this translation helpful? Give feedback.
Questions, if they are not related directly to the wxSQLite3 wrapper, but to SQLite itself (like about query optimization or performance of certain SQL commands), are usually better asked on the SQLite user forum.
SQLite can handle databases which have many GBs in size, so 10-15 MB should not impose a problem.