一个 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

请注意,这很可能会使用并行访问来计算不同keySUM,这在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 查询还是一个大型查询并在服务器上进行处理?

Postgresql 是 1 个查询还是多个?

sql多表查询出来的数据在C#中用啥装载比较好,是泛型集合还是集合??还有其他的可以装吗??

SQL Server 查询分析器中的GO 是成对使用还是单独使用?

SQL - 组合多个类似查询

PHP:多个 SQL 查询与一个怪物