一个 SQL 查询,还是一个循环中的多个?
Posted
技术标签:
【中文标题】一个 SQL 查询,还是一个循环中的多个?【英文标题】:One SQL query, or many in a loop? 【发布时间】:2009-06-03 18:00:35 【问题描述】:我需要从表中提取几行并以两种方式处理它们:
在一个键上聚合 逐行,按相同键排序表格大致如下:
table (
key,
string_data,
numeric_data
)
所以我正在研究我正在编写的函数的两种方法。
第一个会通过一个查询拉取聚合数据,然后在循环内再次查询每组逐行数据(以下是类似 php 的伪代码):
$rows = query(
"SELECT key,SUM(numeric_data)
FROM table
GROUP BY key"
);
foreach ($rows as $row)
<process aggregate data in $row>
$key = $row['key'];
$row_by_row_data = handle_individual_rows($key);
function handle_individual_rows($key)
$rows = query(
"SELECT string_data
FROM table WHERE key=?",
$key
);
<process $rows one row at a time>
return $processed_data;
或者,我可以做一个大查询,让代码完成所有工作:
$rows = query(
"SELECT key, string_data, numeric_data
FROM table"
);
foreach ($rows as $row)
<process rows individually and calculate aggregates as I go>
在此应用程序中,性能不是实际问题;我只是想编写合理且可维护的代码。
我喜欢第一个选项,因为它更模块化——我喜欢第二个选项,因为它看起来结构简单。是一种选择比另一种更好,还是真的只是风格问题?
【问题讨论】:
【参考方案1】:肯定有一个SQL
查询。
这会
为您节省大量往返数据库的次数 允许使用更高效的GROUP BY
方法
由于数据库可以同样出色地执行聚合,因此可维护性也会更好:您将所有结果集逻辑放在一个位置。
这是一个返回每一行并计算SUM
的查询示例:
SELECT string_data, numeric_data, SUM(numeric_data) OVER (PARTITION BY key)
FROM table
请注意,这很可能会使用并行访问来计算不同key
的SUM
,这在PHP
中几乎无法实现。
mysql
中的相同查询:
SELECT key, string_data, numeric_data,
(
SELECT SUM(numeric_data)
FROM table ti
WHERE ti.key = to.key
) AS key_sum
FROM table to
【讨论】:
“允许使用更高效的 GROUP BY 方法” - 怎么样?也许这个例子不清楚,但如果我只使用一个 SQL 查询,我认为我可以不使用 GROUP BY,因为我需要查看每一行 您需要查看每一行并计算汇总。您正在使用 GROUP BY,但您自己的 GROUP BY。用 PHP 编写的 HASH TABLE 几乎不会比用 C 编写的 SQL Server 更高效。 你能告诉我一个查询的例子,它可以让我每一行和计算聚合吗?你在考虑 SELF JOIN 吗? SUM OVER 是专有的 T-SQL 功能吗? 不,它也在 Oracle 和即将推出的 PostgreSQL 8.4 中【参考方案2】:如果性能不是问题,我会选择第二个。似乎更友好一点。
如果性能是一个问题,我的答案是"don't think, profile"。 :)
【讨论】:
【参考方案3】:第二个答案迄今为止更加清晰、明智和可维护。你用更少的代码说同样的话,这通常会更好。
我知道你说性能不是问题,但为什么要获取比你必须更多的数据呢?
【讨论】:
【参考方案4】:我不能从这里的示例中确定,但我想知道是否有机会在 SQL 查询本身中进行聚合和其他处理。在这种情况下,您必须根据您在 SQL 代码与 PHP 代码中表达该处理的相对舒适度来评估“更易于维护”。
您需要对每一行进行的额外处理是否会妨碍您在 SQL 查询本身中表达所有内容?
【讨论】:
这个例子有点过于简单了。我需要查看几列的聚合结果,以及每行中几列的各个值。我想我可以使用 SELF JOIN 在一个查询中完成所有操作,但如果我们谈论的是可读性,不确定这是不是正确的决定。【参考方案5】:我认为您根本不会在很多情况下对循环执行一次查询是更好的选择。事实上,我会说永远不要这样做可能是一个很好的经验法则。
换句话说,到数据库的往返次数越少越好。
根据您的数据和实际表,您也许可以让 SQL 完成聚合工作并通过一个查询选择您需要的所有行。
【讨论】:
“到数据库的往返次数越少越好。”但是,如果性能不是问题,为什么? 因为习惯了这种做法很糟糕。最好学会以“正确的方式”来做这件事,这样当你在做一些关注性能的事情时,你就不必改掉这些坏习惯。 对不起——“为什么”我的意思是“为什么这是一种糟糕的做法”?您只是说一般来说以尊重性能问题的方式进行编码会更好吗?还是除了性能之外还有其他原因,为什么“到数据库的往返次数越少越好”? "..以尊重性能问题的方式?"是的。开始询问同事或浏览网络有关 Web 应用程序性能的信息 - 您几乎都会发现数据库是出现大部分性能问题的地方。 换句话说,当我说“性能不是问题”时,您的回答是“是的”。我怀疑你是对的——那就是你在说什么,对吧?【参考方案6】:一个 sql 查询可能是一个更好的主意。 它避免了你必须重写关系操作
【讨论】:
【参考方案7】:我认为您以某种方式回答了自己的问题,因为您说您有两种不同的处理方式:一种是聚合,一种是逐行。
如果您想保持所有内容的可读性和可维护性,将两者混合在一个查询中听起来不正确,该查询将满足两种不同的需求,因此它的可读性不会很高
即使性能不是问题,在数据库服务器上进行聚合比在代码中进行聚合更快
只有一个查询,处理结果的代码将混合两个处理,同时处理行和计算聚合,因此这段代码迟早会变得混乱和错误
相同的代码可能会随着时间的推移而演变,例如逐行可能会变得复杂,并可能在聚合部分或其他方面产生错误
如果将来您需要拆分这两种处理方式,那么将难以解开当时其他人很久以前编写的代码...
抛开性能方面的考虑,在可维护性和可读性方面,我建议使用两个查询。
但请记住,性能因素目前可能不是问题,但一旦数据库容量增长或其他情况,它可能会及时出现,从长远来看,它绝不是一个可以忽略的因素......
【讨论】:
您是推荐一种方法还是另一种方法,或者您只是想稍微扩展一下优缺点? 对不起,Ben,如果我不够清楚,在我建议使用两个查询的可读性和可维护性方面,我会改写答案。【参考方案8】:即使性能不是问题,你的想法也是。当音乐家练习每一个动作时,都是为了提高音乐家的技能。作为开发人员,您应该开发每个程序以提高您的技能。尽管数据是草率和丑陋的,但迭代循环。 SQL 查询很优雅。你想开发更优雅的代码还是更草率的代码?
【讨论】:
谢谢保罗。共识肯定是站在你这边的,我确实采取了单一查询的方法。想知道您是否可以提供更多关于“尽管数据草率且丑陋的迭代循环”的背景知识。有什么论据?或者,如果我需要争论,我会无能为力吗? ;-)以上是关于一个 SQL 查询,还是一个循环中的多个?的主要内容,如果未能解决你的问题,请参考以下文章
我应该执行多个 sql 查询还是一个大型查询并在服务器上进行处理?
sql多表查询出来的数据在C#中用啥装载比较好,是泛型集合还是集合??还有其他的可以装吗??