将值计算从 SQL 移到 PHP 层会更好吗?

Posted

技术标签:

【中文标题】将值计算从 SQL 移到 PHP 层会更好吗?【英文标题】:Is it better to move values computation to PHP layer out of SQL? 【发布时间】:2012-08-23 02:01:47 【问题描述】:

此方法用于在 User 和 TargetUser 之间选择操作数,例如只是在两个用户之间。这个方法的结果值依赖于GetTotalOfPossibleActions()的动态返回值(每个用户都有自己的编号)。

问题:将值计算移到 SQL 之外的 php 层会更好吗?

public function GetAction() 

    // ...

    $MaxActionCount = $this->GetTotalOfPossibleActions();

    return registry::getInstance()->get('DB')->select(
        'SELECT
            `Action`
            , `HA`.`Id` AS `ActionId`
            , IF(`Count` IS NULL
                , IF('.$MaxActionCount.' % 2
                    , IF(`HA`.`Id` = 1
                        , CEIL('.$MaxActionCount.' / 2)
                        , FLOOR('.$MaxActionCount.' / 2))
                    , '.$MaxActionCount.' / 2)
                , GREATEST(IF('.$MaxActionCount.' % 2
                    , IF(`HA`.`Id` = 1
                        , CEIL('.$MaxActionCount.' / 2) -  CONVERT(`H`.`Count`, SIGNED)
                        , FLOOR('.$MaxActionCount.' / 2) - CONVERT(`H`.`Count`, SIGNED))
                    , '.$MaxActionCount.' / 2 - `H`.`Count`), 0)
            ) AS `CountLeft`
        FROM `Help` AS `H`
        RIGHT JOIN `HelpAction`  AS `HA`
        ON `H`.`ActionId` = `HA`.`Id`
        AND `UserId` = '.$this->UserId.'
        AND `TargetUserId` = '.$this->TargetUserId.'
        AND `CreatedDate` = CURDATE()'));


【问题讨论】:

您只是将变量猛烈撞击到 SQL 中的方式非常令人担忧。您至少应该使用占位符来避免 SQL 注入错误或更糟。 SQL 注入在这里是不可能的,因为 $MaxActionCount 是内部值。 @Roman 这甚至不是重点。如果您不使用参数化查询,则数据库引擎无法重用您的查询。每次使用它访问数据库时都必须完全解析它。将其转换为存储过程并将值作为参数发送。与将一些简单的数学运算从这里转移到那里相比,这将节省更多时间。 @Tomalak,这正是我今天早上想的,将其转换为 SP。 “参数化查询”是什么意思? 数据来自哪里并不重要。它必须在放入您的 SQL 语句之前正确转义。当你做出这样的假设时,你最终会给自己带来非常严重的麻烦。 【参考方案1】:

没有硬性和快速的答案,但以下是我应用的一般指南。

PHP 服务器可以负载平衡和倍增。因此,如果您的 CPU 周期不足,您可以相对轻松地添加另一个 PHP 服务器。反之,mysql服务器也不能轻易成倍增加。您可以添加复制服务器并在从属服务器上运行复杂的“选择”,但是复制会增加一点压力,并且在主服务器上的更新与从服务器上可用之间总是存在延迟。 (永远不要相信说它是毫秒的数据库管理员;当服务器处于压力之下/有备份等时它会变慢。)

所以 +1 给 PHP。

但是,SQL 的构建和设计目的是对数据进行计算。这就是它的工作。它的效率要高得多(假设您正确设计了表、查询和索引)。

所以 +1 到 mySQL。

如果你在MySQL上做计算,你也不需要把整个数据表转给PHP来处理和处理。这样可以节省两者之间的网络流量。

所以 +1 到 mySQL。

但是,如果您难以正确查询,或者 MySQL 正在耗尽所有内存,不停地创建临时表并交换到硬盘,那么通过分解PHP中的计算。 MySQL EXPLAIN 和缓慢的查询日志有时令人沮丧。

所以 +1 给 PHP。

所以... 2 全部。如果您在一台服务器上同时拥有两者,并且查询没有给您带来问题,那么让 MySQL 来完成它的工作。如果您遇到查询问题,请退回到 PHP。如果您在多台服务器上,请尽可能多地使用 MySQL,而不会遇到瓶颈。如果 MySQL 是一个瓶颈并且无法复制,请退回到 PHP。然后检查网络流量。

然后记得在负载增加时重新评估...

【讨论】:

PHP 服务器在 AWS Auto Scaling 下,DB 是 Master / Slave + Slave Replica。我现在把它移到 SP,让我们看看......

以上是关于将值计算从 SQL 移到 PHP 层会更好吗?的主要内容,如果未能解决你的问题,请参考以下文章

PHP/SQL - 如果 foreach() 中的 ID 相同,则将值相加

无法将值从组件传递到模板

我可以通过查询将值传递给 SQL 触发器吗?

SQL 动态地将值拆分为新列

我可以通过查询将值传递给SQL触发器吗?

将值列表从 Python 传递到 SQL 查询的 IN 子句