HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Optimizing SQLite SELECT Performance

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
selectsqliteoptimizingperformance

Problem

I need to read Databases which contain 44-50 Tables, with around 5 Million entries in Total (~ 100k entries per Table).

The Data consists of Positional Tracking Data in Sports (Players,Refs and the Ball) and Match-Events (Shots, Plays,Tackles,...):
Match-Events are negligible regarding performance.

Table: PlayerXYZ or Ball
-------------------------------------------
|id (int Primary Key)| x | y | z | timekey | 
--------------------------------------------


Right now, it takes 86 seconds to read the Database and assign the content to a DataTable Dictionary.
That's a "Speed" of 57000 entries per second.

```
private async void ProcessLoadMatch()
{
var window = Application.Current.MainWindow as MetroWindow;
var controller = await window.ShowProgressAsync("Please wait...", "Process message", false, new MetroDialogSettings());

controller.SetTitle("Loading Match-Data...");
await Task.Run(() => HandleLoadMatch(controller));
await controller.CloseAsync();

}

static bool HandleLoadMatch(ProgressDialogController ProgCtrl)
{
string DataBasePath = @"W:\data\sqlite";
string DataBaseName = "db";
string dbpath = @DataBasePath + @"\" + @DataBaseName + ".sqlite";

SQLiteConnection con = new SQLiteConnection("Data Source=" + dbpath + ";Version=3;");
con.Open();

DataTable tables = con.GetSchema("Tables");
double currentTable = 0;
double Percentage = 0;
foreach (DataRow row in tables.Rows)
{
currentTable++;
Percentage = (100 / tables.Rows.Count) * currentTable;
string tablename = (string)row[2];
ProgCtrl.SetMessage("Loading Data\nCurrent Table ("+currentTable+" of "+tables.Rows.Count+"): " + tablename + " ...");
ProgCtrl.SetProgress(Percentage / 100);

string CmdString = "SELECT * FROM " + tablename;
SQLiteCommand cmd = new SQLiteCommand(CmdString, con);
SQLiteDataAdapter sda = new SQLiteDataAdapter(cmd);
DataTable MatchDt = new DataTable();

Solution

Improving the performance depends on where exactly the bottleneck is - with a database it's typically either IO or CPU. A simple way to see if IO is the main problem is to load the entire database into memory and then selecting from it. However once you have loaded the database into memory you might just want to consider loading your data on demand when you need to display it rather than pulling it into a DataTable.

Once you have the database in-memory you could also try a Parallel.ForEach to load the data from all tables in parallel. Of course you can try this without loading the data into in-memory. I'm not sure how well this works with a physical file but it's worth a shot.

A few additional remarks:

-
Nitpick: It's a database and not a data base hence your variable names should read Database and not DataBase.

-
The general C# naming convention for method parameters and local variables is camelCase - Percentage and ProgCtl both violate this.

-
Don't abbreviate variable and parameter names needlessly, e.g. ProgCtl could be easily progressController - much more readable.

-
For more complex string formatting I'd prefer string.Format over concatenating manually:

ProgCtrl.SetMessage(string.Format("Loading Data\nCurrent Table ({0} of {1}): {2} ...", 
                                   currentTable, tables.Rows.Count, tablename));


Makes the structure of the resulting string much clearer.

-
SQLiteConnection, SQLiteDataAdapter and SQLiteCommand are all IDisposable and should be wrapped into using statements to make sure they get cleaned up properly.

-
DatabasePath and DatabaseName should be const.

-
Use Path.Combine to combine paths:

string dbpath = Path.Combine(DataBasePath, DataBaseName + ".sqlite");

Code Snippets

ProgCtrl.SetMessage(string.Format("Loading Data\nCurrent Table ({0} of {1}): {2} ...", 
                                   currentTable, tables.Rows.Count, tablename));
string dbpath = Path.Combine(DataBasePath, DataBaseName + ".sqlite");

Context

StackExchange Code Review Q#115840, answer score: 3

Revisions (0)

No revisions yet.