DataTable读取器加载速度很慢
我需要根据关键字获取一些数据,该查询被测试为100%准确,但问题是reader
的加载速度很慢。我试图用一个不包含inner join
的查询替换这个查询,并且加载非常快。所以我想知道,因为我只选择一列作为结果,为什么DataTable.Load()需要这么多时间?加载整个结果的是SQLite
的ExecuteReader
而不仅仅是一列吗?DataTable读取器加载速度很慢
在使用DataTable之前,执行每个reader.Read()
的平均时间为7秒。
这是我的代码:
_database.Connect();
var selectCommand = new SQLiteCommand(
@"SELECT A.ID AS MY_ID FROM MD
INNER JOIN TMD ON MD.ID = TMD.ID_MD
INNER JOIN TR ON TR.ID = TMD.ID_TR
INNER JOIN P ON P.ID = TR.ID_P
INNER JOIN DP ON DP.ID_P = P.ID
INNER JOIN CD ON CD.ID = DP.ID_CD
WHERE CD.DESC = @desc"
);
selectCommand.Parameters.AddWithValue("@desc", value);
using (DbDataReader reader = _database.ExecuteQuery(selectCommand))
{
DataTable data = new DataTable("MyData");
data.Load(reader);
}
_database.Disconnect();
The SQLite Query Planner提供了关于SQLite查询优化的一些提示。
可能适用于你的问题的一些项目:
1)由于SQLite的执行你可以尝试重新排列多个联接:
当前实现的SQLite只使用循环连接。也就是说, 说,联接被实现为嵌套循环。 嵌套循环在链接中的默认顺序是FROM子句中最左边的表格至 形成外部循环,最右边的表格形成内部循环。
所以,根据JOIN的构造方式,可能会有性能差异。
的SQLite试图自动优化这一点,但据我了解的文档有成功不能保证(由我亮点):
然而,SQLite的将鸟巢,如果在做不同的顺序循环所以 将帮助它选择更好的指数。 [...] 加入重新排序是自动的,通常运行良好,程序员 不必考虑它,特别是如果ANALYZE已被用于收集有关可用索引的统计信息 。 但是偶尔需要 程序员的一些提示。
2)另外,请注意,内部连接在内部转换为WHERE子句,因此任何在表现技巧在文档的部分可能适用,太:
的ON和内部联接的USING子句在上述段落1.0中的WHERE子句分析 之前被转换为WHERE子句的附加项。因此,对于SQLite,没有 计算优势,可以使用较早的SQL89连接语法而不是较旧的SQL89逗号连接语法。他们最终都在内部连接上完成了相同的事情,完成了 。
3)你可能会考虑在你的语句来选择多个列,如果上面有任何索引:
这是没有必要为索引的每列出现在WHERE 为了使用该索引,使用子句术语。但是不能是 使用的索引列中的间隔。
所有连接都建立在主键上,我认为这解决了索引的问题,但我真的想要考虑1 + 2是否可以成为我的案例的救星。 – iCantSeeSharp 2012-07-10 14:31:00
我在我的sql命令之前使用了'ANALYZE',查询执行得非常快。所以,考虑到你为这个特定问题提供了正确的方向,你会得到答案。谢谢! – iCantSeeSharp 2012-07-10 14:53:03
我认为出现这种情况的SQLite由于性质和大量的联接。
尝试重构数据库方案,如使数据非规范化以加快访问速度。
“SQLite的性质”是否意味着预期结果与当前返回的不同? – iCantSeeSharp 2012-07-10 13:56:21
@Souvlaki:我的意思是说,SQLite不支持这么多的连接的良好加载,也可能有一个大文件会降低最终的持久性。 – abatishchev 2012-07-10 13:58:55
尽管Navicat的查询速度相当快? – iCantSeeSharp 2012-07-10 14:03:33
这听起来像你的查询是简单的。有没有不同的方式来访问你的表,这样你就不必做很多连接了? – Tejs 2012-07-10 13:53:34
我知道这会伤人..不幸的是,我们需要根据其中一个字段连接2个表格。鉴于当前的数据库架构,这些连接是它们之间的唯一连接。 – iCantSeeSharp 2012-07-10 13:55:25
什么是_database,为什么它有像Connect和Disconnect这样的方法?不要重新发明轮子。您还应该为连接使用'using-statement',以确保它尽快“关闭”。这是像ASP.NET这样的多线程环境吗? – 2012-07-10 13:55:55