2011-06-21 14 views
8

Tengo un problema al utilizar SQLiteParameters y el operador LIKE en una consulta de SQLite. Aquí hay un fragmento de código, y me disculpo si no tengo suficiente código aquí. Si ese es el caso, puedo publicar más fácilmente.Rendimiento de SQLite.NET utilizando SQLiteParameter con el operador LIKE

degradación de las prestaciones:

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

Gran Rendimiento:

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

Otro código importante:

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

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

El primer ejemplo tiene 700 ms para ejecutar, que mi supervisor considera inaceptable. El segundo ejemplo tarda 7 ms en ejecutarse. ¿Por qué la diferencia? ¿Hay algo que estoy haciendo completamente mal para ganarme estatus de novato?

¡Gracias de antemano!

+1

¿Está ejecutando varias pruebas para eliminar los artefactos de almacenamiento en caché? ¿Ambos devuelven las mismas filas? ¿Estás usando comodines? – Tim

+0

Además, en implementaciones de SQLite donde la función LIKE está anulada, los índices no están disponibles. ¿Qué obtienes con ... donde contactname GLOB @contactname [case sensitive, BTW]? – Tim

+0

Hola Tim. Sí, estoy ejecutando múltiples pruebas. La primera vez es un poco más de 1 segundo y el promedio de más de 15 pruebas es de aproximadamente 700 ms. Sí, devuelven las mismas filas.No, no estoy usando comodines. Sé que parece extraño, pero estoy usando la declaración similar para eliminar la búsqueda sensible a mayúsculas y minúsculas así que usará mi configuración de índice en ContactName COLLATE NOCASE. – Terry

Respuesta

2

lo tanto, yo creo que puede haber reducido a un problema con System.Data.SQLite. Probé el siguiente código en 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); 
} 

Tanto las funciones PoorPerformance y GoodPerformance produjo 1 ms con 11 filas. ¿Hay algo diferente entre lo que hice y lo que debería haber hecho System.Data.SQLite? Espero que esto sea algo que puedo informar como un error con System.Data.SQLite y quizás aplique mi propia solución.

+0

¿Tiene alguna actualización sobre su problema con System.Data.SQLite? – Shrike

+0

@Shrike Mira mi respuesta a continuación ... puede ser útil. – user1032657

1

Como no puedo ver ninguna diferencia entre las dos consultas, pero el hecho de que uno usa sqliteparameter y el otro de una instrucción sql completa como cadena - Acabo de buscar en Google su problema y tropecé con that.

Allí indica que en el objeto SQLiteCommand hay una propiedad llamada ParameterCheck, que puede causar algunas pérdidas de rendimiento.

Puede intentar volver a escribir el código para pasar un objeto SQLiteCommand y establecer la propiedad ParameterCheck en false. Creo que deberías ganar algo de velocidad haciendo esto.

por lo menos es digno de un tiro :)

+0

¡Tenía tanta esperanza de que esto resolvería mi problema! Desafortunadamente, esto usa Devart.Data.SQLite en lugar de System.Data.SQLite. – Terry

0

También he tenido problemas de rendimiento con System.Data.SQLite, algunos de los cuales he podido abordar y mejorar, y otros que no he tenido.

Sin embargo, recientemente he descubierto esta biblioteca de C# SQLite alternativa: http://code.google.com/p/csharp-sqlite/

Se me ha dado ningún problema de rendimiento, y que en realidad reemplazado System.Data.SQLite con éste en un proyecto existente (casi no hay cambios en la sintaxis - De forma más o menos literal, simplemente reemplacé el DLL y la directiva using. Había un par de líneas donde tuve que convertir algo en un encasillado), y aceleró las cosas maravillosamente. Hubo momentos en los que esperaba el orden de segundos con System.Data.SQLite, y ahora las ejecuciones son instantáneas.

Cuestiones relacionadas