在具有不同SQLite提供程序的同一程序上执行的相同查询具有大不相同的执行时间

时间:2015-08-28 17:07:12

标签: c# sqlite

因此,我将C#应用程序从框架(3.5)(Visual Studio 2008)迁移到框架(4.5.1)(Visual Studio 2013)。我们正在使用SQLite数据库并将实体框架升级到6.1.3和SQLite引用的最终(1.0.98)。 在一些预测的问题得到解决而另一些问题未得到预测之后,我陷入了困境。 我在代码端执行了一个查询,在两个框架之间执行时间不同,不幸的是,新的查询结果最差。 在旧的(3.5)执行时间约为2-3秒,在新的执行时间约为2分钟。我保证DB是相同的,并且始终具有相同的数据量。

还有另外一件事......如果我直接在SQLite上执行查询,那么它在框架4.5.1上的执行时间就差不多(差不多2分钟)。如何在SQLite上花费更多时间而不是旧应用程序?

我创建了两个虚拟项目(每个框架一个),以确保它在迁移过程中没有丢失,但结果仍然相同。

这绝对是旧框架的一部分。我的理论是,在旧应用程序上发送了一些数据库参数,这使得查询更有效,但我无法找到哪一个。

使用以下commad运行查询:

SQLiteCommand.Execute(query,SQLiteExecuteType.NonQuery," MyConnectionString",new object [] {});

(两个应用程序相同)

这是 SQLITE DATABASE(v3.5.85.2505)的EXPLAIN QUERY PLAN输出:

selectid    order   from    detail
1   0   0   SCAN TABLE SI_REFERENCES USING INDEX IDX_SI_REFERENCES_FKEY
1   0   0   USE TEMP B-TREE FOR GROUP BY
0   0   0   SCAN TABLE SI_INVOICE
0   1   1   SEARCH TABLE HEADER USING INTEGER PRIMARY KEY (rowid=?)
0   2   2   SEARCH TABLE CUSTOMER USING INDEX IDX_CUSTOMER_HEADERID (HEADERID=?)
0   3   3   SEARCH TABLE SI_LINE USING INDEX IDX_SI_LINE_3 (FKEY=?)
0   4   4   SEARCH SUBQUERY 1 AS T1 USING AUTOMATIC COVERING INDEX (HEADERID=? AND FKEY=?)
0   0   0   USE TEMP B-TREE FOR GROUP BY
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 2
0   0   0   EXECUTE CORRELATED SCALAR SUBQUERY 3

这是来自 NEW PROGRAM(4.5.1)SQLITE(1.0.98)的EXPLAIN QUERY PLAN输出:

selectid    order   from    detail
1 0 0 SCAN TABLE SI_REFERENCES USING INDEX IDX_SI_REFERENCES_FKEY
1 0 0 USE TEMP B-TREE FOR GROUP BY
0 0 0 SCAN TABLE SI_INVOICE
0 1 1 SEARCH TABLE HEADER USING INTEGER PRIMARY KEY (rowid=?)
0 2 2 SEARCH TABLE CUSTOMER USING INDEX IDX_CUSTOMER_HEADERID (HEADERID=?)
0 3 3 SEARCH TABLE SI_LINE USING INDEX IDX_SI_LINE_3 (FKEY=?)
0 4 4 SEARCH SUBQUERY 1 AS T1 USING AUTOMATIC COVERING INDEX (HEADERID=? AND FKE
Y=?)
0 0 0 USE TEMP B-TREE FOR GROUP BY
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 2
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 3

这是 OLD PROGRAM(3.5)SQLITE(1.0.88)的EXPLAIN QUERY PLAN输出:

selectid    order   from    detail
1 0 0 SCAN TABLE SI_REFERENCES (~1000000 rows)
1 0 0 USE TEMP B-TREE FOR GROUP BY
0 0 0 SCAN TABLE SI_INVOICE (~250000 rows)
0 1 1 SEARCH TABLE HEADER USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
0 2 2 SEARCH TABLE CUSTOMER USING INDEX IDX_CUSTOMER_1 (CUSTOMERID=?) (~2 rows)

0 3 3 SEARCH TABLE SI_LINE USING INDEX IDX_SI_LINE_3 (FKEY=?) (~2 rows)
0 4 4 SEARCH SUBQUERY 1 AS T1 USING AUTOMATIC COVERING INDEX (HEADERID=? AND FKE
Y=?) (~3 rows)
0 0 0 USE TEMP B-TREE FOR GROUP BY
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 2
0 0 0 EXECUTE CORRELATED SCALAR SUBQUERY 3

希望有人可以提供帮助!

最好的问候

1 个答案:

答案 0 :(得分:1)

查询规划器尝试执行查询的方式存在一些差异。 在新版本中,它使用索引来读取SI_REFERENCES表而不是扫描它(因为这将从GROUP BY处理中逐步删除),并且它使用不同的索引来查找{{{1}中的行。 1}}表。

SQLite文档有一个checklist for fixing query planner problems 在几乎所有情况下,运行ANALYZE应该有所帮助(并且在旧版本中也很有用)。 只作为最后的手段,您可以尝试通过添加INDEXED BY子句(CUSTOMER... FROM SI_REFERENCES NOT INDEXED GROUP BY ...)来强制它执行旧版本的查询。