0

我对数据库优化/内存管理知之甚少。

我有一个看起来像这样的查询:

SELECT Value
FROM ValueTable
WHERE SomeConstraint > 4

我需要从这个查询中获取结果,以及从这个查询中获得一个额外的 WHERE 子句的结果。这两种方法哪个更好?

1) 将该查询的结果选择到一个变量中。然后有两个额外的查询

SELECT COUNT(DISTINCT(VALUES))
FROM @SavedQuery

SELECT COUNT(DISTINCT(VALUES))
FROM @SavedQuery
WHERE otherConstraintColumn < 30

2)

    SELECT COUNT(DISTINCT(Value))
    FROM ValueTable
    WHERE SomeConstraint > 4

    SELECT COUNT(DISTINCT(Value))
    FROM ValueTable
    WHERE SomeConstraint > 4
    AND otherConstraintColumn < 30

这可能是用 LINQ 编写的,所以这可能是我们存储查询结果的方式。

4

2 回答 2

2

对于您的具体示例,方法#1 更具可扩展性(获取初始结果,未经过滤,并使用 LINQ 在客户端重新过滤它们),但效率较低。请记住,数据库服务器在查询和过滤数据方面通常更好/更快/更有效。

规则 #1 始终是:不要滥用您的数据库。所以,把这个建议放在我说的任何其他事情之前。

当我查看您的示例时,您似乎只查询了数据库 2 次。那不是辱骂。所以,我想说,使用方法#2(两个单独的查询)。但是,让我也限定这个建议:如果你在循环中运行这个块,或者如果这个代码每天运行数百次,我会改变我的建议。2 次重新查询非常轻巧且无关紧要,但在很多情况下它可能会很糟糕。


一般来说,关于优化,如果您使用的是 ASP.NET,它内置了一些非常好的缓存机制。它们比将查询结果存储在 Session 或 Viewstate 中要好。http://msdn.microsoft.com/en-us/library/6hbbsfk6(v=vs.90).aspx

如果您使用的是 winforms 等,只要您的内存不紧张,将结果存储在内存中是值得的。

这是一篇关于其他几种流行方法的 SO 文章:Best way to cache data

于 2013-09-17T15:38:29.873 回答
2

最有效的方法是使用单个查询获取两个计数,例如:

SELECT COUNT(DISTINCT(t.Value)) AS count1
     , COUNT(DISTINCT(CASE WHEN t.otherConstraintColumn<30 THEN t.Value END))) AS count2
  FROM ValueTable t
 WHERE t.SomeConstraint > 4 

与其他两种方法中的任何一种相比,这种方法在数据库服务器上的资源密集度较低(从数据库中提取可能很大的一组值,或者运行两个单独的查询来访问相同的数据。)

在回答您的问题方面,在这两种方法之间,我会选择第二种方法,仅从数据库中提取计数,而不是传输可能需要再次处理的大量行(在客户端) ,或物化结果集的(不必要的)临时存储(在服务器端),并针对它运行其他查询。

您显示的第一个查询将没有足够的数据来满足后续查询,您还需要为otherConstraintColumn<30条件提取一个指标,以便使用它来满足结果。并进一步减少需要在服务器上传输到客户端(或具体化为临时表)的行数:

获得这个结果集会更有效率:

SELECT t.Value
     , MAX(CASE WHEN t.otherConstraintColumn < 30 THEN 1 ELSE 0 END) AS occlt30
  FROM ValueTable t
 WHERE t.SomeConstraint > 4
 GROUP BY t.Value

但是这种方法仍然比通过单个查询获得所需的实际结果集效率低得多。

于 2013-09-17T19:45:50.540 回答