【发布时间】:2018-12-14 15:40:16
【问题描述】:
(首先解释了很多,实际问题在帖子末尾相当短)
这是初始情况: 我们正在开发一个软件,它从 sqlite 数据库中查询数据并将它们绘制在不同的图表中(LineChart,BarChart,...) 这个想法是用户可以选择 X 轴和 Y 轴的列以及过滤器的任何组合,软件将创建一个查询,获取数据并绘制它。 现在我们想稍微提高一下查询的性能。为此,我使用软件从随机图中计算的查询并在DB Browser 中对其进行测试,看看需要多长时间。然后我尝试手动更改查询,看看是否可以改进时间。
对于这个测试,我们使用一个带有多个过滤器的大型(用于 sqlite)数据库(1.4Gb 数据库大小,大约 35Mio 行/6 列我们想要从中获取结果的表。
我们有 3 个链接表 EmdTable、ShmooTable 和 ResultTable。
该软件给了我以下查询(从调试复制并删除了字符串转义字符):
SELECT (R0), AVG(R1) FROM
(SELECT (EmdTable."Time [ns]") AS R0, (EmdTable."Upper Sideband [mV]" ) AS R1 FROM EmdTable, ResultTable, ShmooTable
WHERE EmdTable."ResultID"=ResultTable."ID"
AND ResultTable."ShmooID"=ShmooTable."ID"
AND ResultTable."CommandName"="APDU: Get PO"
AND ResultTable."Repetition"="1"
AND ResultTable."StepName"="Command"
AND ShmooTable."Hn [A/m]"="2"
AND EmdTable."Time [ns]" IS NOT NULL
AND EmdTable."Upper Sideband [mV]" IS NOT NULL)
WHERE R0 IS NOT NULL AND R1 IS NOT NULL GROUP BY R0
在 DB 浏览器中,大约需要 62 秒才能获得大约 15.000 个数据点的结果(对于 X 和 Y)
我的想法是立即在子查询中使用过滤条件,而不是将所有内容连接在一起并创建条件。 然后我的手动查询如下所示:
SELECT (R0), AVG(R1) FROM
(
(SELECT (EmdTable."Time [ns]") AS R0, (EmdTable."Upper Sideband [mV]" ) AS R1, (EmdTable."ResultID") AS ID1 FROM EmdTable) AS emdquery INNER JOIN
(
SELECT ID2 FROM
(SELECT ResultTable.ID AS ID2, ShmooID FROM ResultTable WHERE ResultTable."CommandName"="APDU: Get PO" AND ResultTable."Repetition"="1" AND ResultTable."StepName"="Command" ) AS resultquery INNER JOIN
(SELECT ShmooTable.ID FROM ShmooTable WHERE ShmooTable."Hn [A/m]" = "2") AS shmooquery ON resultquery.ShmooID = shmooquery.ID
) AS subquery ON emdquery.ID1 = subquery.ID2
)WHERE R0 IS NOT NULL AND R1 IS NOT NULL GROUP BY R0
现在看:这只需要大约 60 秒...所以并不是我希望的性能改进。
但是,“子查询”本身(上面的大查询中的那个)只需要大约 15 毫秒,并且只返回 3 个值。
如果我现在直接使用这三个值从EmdTable查询我的结果,就像这样:
SELECT EmdTable."Time [ns]", AVG(EmdTable."Upper Sideband [mV]") FROM EmdTable
WHERE (EmdTable.ResultID = 1102 OR EmdTable.ResultID = 4818 OR EmdTable.ResultID = 8510) AND EmdTable."Time [ns]" IS NOT NULL AND EmdTable."Upper Sideband [mV]" IS NOT NULL
GROUP BY EmdTable."Time [ns]"
与前两个查询相同的结果“仅”需要大约 40 秒。改善 20 秒……还不错。
这让我想到了实际的问题:
- 我可以先以编程方式(15 毫秒)查询子查询,然后 再次以编程方式将结果插入主查询, 这应该不会超过 40 秒,对吧?
- 还有其他方法可以直接使用 sql 来执行此操作吗?
【问题讨论】:
-
也许你应该在你的表上建立一些索引。
-
这就是问题所在......我对数据库本身没有任何影响
-
1.4GB 并使用 SQLite?删除 SQLite 并安装 PostgreSQL,伙计。你现在需要大炮。
-
再次:对数据库没有影响。另外:对于这个例子,我搜索了一个极端的数据库,正常使用较小的数据库
-
如果您无法为那些特定的 SQLite 数据库添加索引,您可以将它们复制到您可以控制的版本中,以便创建索引吗?还是将数据复制到性能更好的 DBMS,比如 Postgres?
标签: c# sql performance sqlite subquery