Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLite.NET Performance Using SQLiteParameter with LIKE operator

I am having an issue using SQLiteParameters and the LIKE operator in a SQLite query. Here is a snippet of code, and I apologize if I don't have enough code here. If that is the case, I can easily post more.

Poor Performance:

using (OdysseyDataContext entities = new OdysseyDataContext())
{
    var results = entities.SearchResults.SqlQuery(
        "SELECT * FROM SearchResults WHERE ContactName LIKE @ContactName",
        new SQLiteParameter("@ContactName", "test")
    );
}

Great Performance:

using (OdysseyDataContext entities = new OdysseyDataContext())
{
    var results = entities.SearchResults.SqlQuery(
        string.Format(
            "SELECT * FROM SearchResults WHERE ContactName LIKE '{0}'",
            "test"
        )
    );
}

Other important code:

public class OdysseyDataContext : DbContext
{
    public DbSet<SearchResult> SearchResults { get; set; }
}

public class SearchResult
{
    [Key]
    public Guid Id { get; set; }
    public string ContactName { get; set; }
}

The first example takes 700 ms to execute, which my supervisor finds unacceptable. The second example takes 7 ms to execute. Why the difference? Is there something I am doing completely wrong to earn me newbie status?

Thanks in advance!

like image 752
Terry Avatar asked Jun 21 '11 15:06

Terry


2 Answers

So, I think I may have narrowed it down to an issue with System.Data.SQLite. I tried the following code in C++:

#include "sqlite3.h"
#include <stdio.h>

void xProfile(void* pArg, const char* query, sqlite3_uint64 pTimeTaken)
{
    printf("%s\n", query);
    printf("%I64d ms\n", pTimeTaken / 1000000);
}

void PoorPerformance();
void GoodPerformance();

int main()
{
    printf("Poor Performance:\n");
    PoorPerformance();

    printf("Good Performance:\n");
    GoodPerformance();

    return 0;
}

void PoorPerformance()
{
    int rc;
    int rowCount = 0;

    sqlite3 *db;
    if (sqlite3_open("<<File Here>>", &db))
    {
        printf("Could not open the database.");
        return;
    }

    sqlite3_profile(db, &xProfile, NULL);

    sqlite3_stmt *statement;
    if (!sqlite3_prepare_v2(db, "SELECT * FROM SearchResults WHERE ContactName LIKE @ContactName;", -1, &statement, 0))
    {
        int result = 0;
        int parameterIndex = sqlite3_bind_parameter_index(statement, "@ContactName");
        sqlite3_bind_text(statement, 1, "test", -1, NULL);
        while (result != SQLITE_DONE)
        {
            result = sqlite3_step(statement);

            if (result == SQLITE_ROW)
            {
                rowCount++;
            }
        }

        sqlite3_finalize(statement);
    }

    printf("%d rows\n", rowCount);

    sqlite3_close(db);
}

void GoodPerformance()
{
    int rc;
    int rowCount = 0;

    sqlite3 *db;
    if (sqlite3_open("<<File Here>>", &db))
    {
        printf("Could not open the database.");
        return;
    }

    sqlite3_profile(db, &xProfile, NULL);

    sqlite3_stmt *statement;
    if (!sqlite3_prepare_v2(db, "SELECT * FROM SearchResults WHERE ContactName LIKE 'test';", -1, &statement, 0))
    {
        int result = 0;

        while (result != SQLITE_DONE)
        {
            result = sqlite3_step(statement);

            if (result == SQLITE_ROW)
            {
                rowCount++;
            }
        }

        sqlite3_finalize(statement);
    }

    printf("%d rows\n", rowCount);

    sqlite3_close(db);
}

Both the PoorPerformance and GoodPerformance functions yielded 1 ms with 11 rows. Is there something different between what I did and what should have been done by System.Data.SQLite? Hopefully this is just something I can report as a bug with System.Data.SQLite and perhaps apply my own fix.

like image 53
Terry Avatar answered Nov 13 '22 12:11

Terry


Since I cannot see any difference between the two queries, but the fact, that one uses sqliteparameter and the other one a complete sql-statement as string - I just googled your problem and stumbled upon that.

There it indicates that on the SQLiteCommand object there is a property called ParameterCheck, which can cause some performance loss.

You could try to rewrite your code to pass a SQLiteCommand object and set the ParameterCheck property to false. I think you should gain some speed doing this.

At least it's worth a shot :)

like image 25
Gambrinus Avatar answered Nov 13 '22 12:11

Gambrinus