Производительность SQLite.NET Использование SQLiteParameter с оператором LIKE - PullRequest
8 голосов
/ 21 июня 2011

У меня проблема с использованием SQLiteParameters и оператора LIKE в запросе SQLite.Вот фрагмент кода, и я прошу прощения, если мне не хватает кода здесь.Если это так, я могу легко опубликовать больше.

Низкая производительность:

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

Отличная производительность:

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

Другой важный код:

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

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

Первый пример занимает 700 мс, что мой руководитель считает неприемлемым.Второй пример занимает 7 мсек.Почему разница?Есть ли что-то, что я делаю совершенно неправильно, чтобы заработать мне статус новичка?

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 08 июля 2011

Итак, я думаю, что я мог сузить это до проблемы с System.Data.SQLite. Я попробовал следующий код в 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);
}

Функции PoorPerformance и GoodPerformance дали 1 мс с 11 строками. Есть ли что-то другое между тем, что я сделал, и тем, что должно было быть сделано System.Data.SQLite? Надеюсь, что это просто то, что я могу сообщить об ошибке в System.Data.SQLite и, возможно, применить свое собственное исправление.

1 голос
/ 05 июля 2011

Поскольку я не вижу никакой разницы между этими двумя запросами, кроме того факта, что один использует sqliteparameter, а другой - полный SQL-оператор в виде строки - я просто погуглил вашу проблему и наткнулся на , что .

Там это указывает, что в объекте SQLiteCommand есть свойство с именем ParameterCheck , которое может привести к некоторой потере производительности.

Вы можете попытаться переписать свой код для передачи объекта SQLiteCommand и установить для свойства ParameterCheck значение false. Я думаю, вы должны набрать определенную скорость.

По крайней мере, стоит попробовать :)

0 голосов
/ 15 апреля 2012

У меня также были проблемы с производительностью System.Data.SQLite, некоторые из которых мне удалось устранить и исправить, а другие - нет.

Однако недавно я обнаружил эту альтернативную библиотеку C # SQLite: http://code.google.com/p/csharp-sqlite/

Это не дало мне никаких проблем с производительностью, и я фактически заменил System.Data.SQLite на этот в существующем проекте (почти без изменений в синтаксисе - я более или менее буквально заменил DLL и директиву using .. там была пара строк, где я должен был что-то набрать), и это ускорило процесс. Были времена, когда я ожидал порядка секунд с System.Data.SQLite, и теперь выполнения выполняются мгновенно.

...