(首先进行很多解释,在帖子末尾实际问题很短)
这是初始情况: 我们正在开发一种软件,该软件可查询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
在数据库浏览器中,这大约需要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秒...还不错。
这使我想到了实际的问题:
答案 0 :(得分:0)
问题1的答案当然是肯定的,特别是如果您可以使用LINQ to SQL之类的东西,那将很容易。 LINQ将方法Contains
转换为SQL运算符IN
。
在SQL中,您可以将子查询与IN
一起使用吗?
SELECT EmdTable."Time [ns]", AVG(EmdTable."Upper Sideband [mV]") FROM EmdTable
WHERE EmdTable.ResultID IN (
SELECT ResultTable."ID"
FROM ResultTable, ShmooTable
WHERE 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
GROUP BY EmdTable."Time [ns]"