我在SQLite查询中使用SQLiteParameters和LIKE运算符时遇到问题。这是一段代码,如果我这里没有足够的代码,我会道歉。如果是这种情况,我可以轻松发布更多内容。
表现不佳:
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毫秒才能执行。为什么不同?为了赢得新手身份,有什么我做错了吗?
提前致谢!
答案 0 :(得分:2)
所以,我想我可能已经将它缩小到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 ms,共11行。我做了什么以及System.Data.SQLite应该做些什么之间有什么不同?希望这只是我可以报告为System.Data.SQLite的一个错误,并且可能应用我自己的修复。
答案 1 :(得分:1)
因为我看不出两个查询之间有什么区别,但事实上,一个使用sqliteparameter而另一个使用完整的sql语句作为字符串 - 我只是用Google搜索你的问题并偶然发现that。
它表明在SQLiteCommand对象上有一个名为ParameterCheck的属性,这会导致一些性能损失。
您可以尝试重写代码以传递SQLiteCommand对象并将ParameterCheck属性设置为false。我认为你应该加快速度。
至少值得一试:)
答案 2 :(得分:0)
我也遇到过System.Data.SQLite的性能问题,其中一些我能够解决和改进,还有一些我没有。
但是,最近我发现了另一个C#SQLite库:http://code.google.com/p/csharp-sqlite/
它给了我没有性能问题,我实际上在现有项目中用这一个替换了System.Data.SQLite(语法几乎没有变化 - 我或多或少地字面上只是替换了DLL和using指令..那里有几行,我不得不强调一些东西),它加快了事情的发展。有时我用System.Data.SQLite等待秒数,现在执行是即时的。