使用C#SQLite DataReader和附加数据库迭代结果的性能问题

我在我的C#项目中使用System.Data.SQLiteSQLiteDataReader 。 在使用附加数据库获取查询结果时,我遇到了性能问题。

以下是将文本搜索到两个数据库的查询示例:

 ATTACH "db2.db" as db2; SELECT MainRecord.RecordID, ((LENGTH(MainRecord.Value) - LENGTH(REPLACE(UPPER(MainRecord.Value), UPPER("FirstValueToSearch"), ""))) / 18) AS "FirstResultNumber", ((LENGTH(DB2Record.Value) - LENGTH(REPLACE(UPPER(DB2Record.Value), UPPER("SecondValueToSearch"), ""))) / 19) AS "SecondResultNumber" FROM main.Record MainRecord JOIN db2.Record DB2Record ON DB2Record.RecordID BETWEEN (MainRecord.PositionMin) AND (MainRecord.PositionMax) WHERE FirstResultNumber > 0 AND SecondResultNumber > 0; DETACH db2; 

使用SQLiteStudio或SQLiteAdmin执行此查询时,此工作正常,我在几秒钟内得到结果(记录表可以包含数十万条记录,查询返回36000条记录)。

在我的C#项目中执行此查询时,执行也需要几秒钟,但运行所有结果需要几个小时。

这是我的代码:

 // Attach databases SQLiteDataReader data = null; using (SQLiteCommand command = this.m_connection.CreateCommand()) { command.CommandText = "SELECT..."; data = command.ExecuteReader(); } if (data.HasRows) { while (data.Read()) { // Do nothing, just iterate all results } } data.Close(); // Detach databases 

调用SQLiteDataReaderRead方法一次可能需要10秒以上! 我想这是因为SQLiteDataReader是延迟加载的(因此它在读取结果之前不返回整个行集),我是对的吗?

编辑1:

我不知道这是否与延迟加载有关,就像我最初说的那样,但我想要的只是在查询结束后能够获得所有结果。 不可能吗? 在我看来,这真的很奇怪,只需几个小时就可以在几秒钟内完成查询结果……

编辑2:

我刚刚在我的select查询中添加了一个COUNT(*) ,以便查看是否可以在第一个data.Read()获得结果总数,只是为了确保它只是结果的迭代太长。 我错了:这个新请求在几秒钟内在SQLiteAdmin / SQLiteStudio中执行,但在我的C#项目中执行需要几个小时。 知道为什么同一个查询在我的C#项目中执行的时间要长得多吗?

编辑3:

感谢EXPLAIN QUERY PLAN ,我注意到SQLiteAdmin / SQLiteStudio和我的C#项目之间的同一查询的执行计划略有不同。 在第二种情况下,它在DB2Record上使用AUTOMATIC PARTIAL COVERING INDEX而不是使用主键索引。 有没有办法忽略/禁用自动部分覆盖索引的使用? 我知道它用于加速查询,但在我的情况下,它发生了相反的情况……

谢谢。

除了查找匹配记录外,您似乎还在计算字符串匹配的次数。 此计数的结果也在WHERE子句中使用。

您需要匹配数,但WHERE子句中的匹配数无关紧要 – 您可以尝试将WHERE子句更改为:

 WHERE MainRecord.Value LIKE '%FirstValueToSearch%' AND DB2Record.Value LIKE '%SecondValueToSearch%' 

它可能不会产生任何差异 – 特别是如果Value列上没有索引 – 但值得一试。 文本列上的索引需要很多空间,所以我不会盲目推荐。

如果还没有这样做,请在DB2的RecordID列上放置一个索引。

您可以使用EXPLAIN QUERY PLAN SELECT ...使SQLite吐出它尝试使您的查询执行的function,其输出可能有助于诊断问题。

您确定在System.Data.SQLite ,SQLiteStudio和SQLiteAdmin中使用相同版本的sqlite吗? 你可以有很大的差异。

SQL查询在使用ADO.NET和本机实用程序(如SQLiteAdmin)执行时可能需要不同时间的一个典型原因是CommandText中使用的命令参数(从代码中不清楚是否使用了参数)。 根据ADO.NET提供程序实现,以下相同的CommandText值:

 SELECT * FROM sometable WHERE somefield = ? // assume parameter is '2' 

 SELECT * FROM sometable WHERE somefield='2' 

可能导致完全不同的执行计划和查询性能。

另一个建议:您可以禁用日志(在连接字符串中指定“日志模式=关闭;”)和同步模式(“同步=关闭;”),因为在某些情况下这些选项也可能会影响查询性能。