我对数据库优化/内存管理知之甚少。
我有一个如下所示的查询:
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编写的,因此可能就是我们存储查询结果的方式。
答案 0 :(得分: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
答案 1 :(得分: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
但是这种方法的效率仍然低于仅通过单个查询获得所需的实际结果集。