如果我使用多个子查询并将其结果用作主查询的条件,是否可以提高查询的性能?

时间:2018-12-14 15:40:17

标签: c# sql performance sqlite subquery

(首先进行很多解释,在帖子末尾实际问题很短)

这是初始情况: 我们正在开发一种软​​件,该软件可查询sqlite数据库中的数据并将其绘制在不同的图形中(LineChart,BarChart等) 这个想法是,用户可以选择X轴和Y轴的列以及过滤器的任意组合,并且软件将创建查询,获取数据并对其进行绘图。 现在我们要稍微提高查询性能。为此,我进行了查询,该软件从随机图计算得出并在DB Browser中对其进行测试,并查看需要花费多长时间。然后,我尝试手动更改查询,看看是否可以改善时间。

对于此测试,我们使用具有多个过滤器的大型(用于sqlite)数据库(数据库大小为1.4Gb,大约35Mio行/ 6列,我们希望从中获取结果。

我们有3个链接表EmdTableShmooTableResultTable。 该软件为我提供了以下查询(从调试中复制并删除了字符串转义符):

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秒...还不错。

这使我想到了实际的问题:

  1. 我可以先以编程方式(15ms)查询子查询,然后 再次以编程方式将结果插入主查询中, 哪个时间不应该超过40秒,对吧?
  2. 还有另一种直接使用sql直接执行此操作的方法吗?

1 个答案:

答案 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]"