57

语境:

  • 我们有一个 PHP/MySQL 应用程序。
  • 某些部分的计算直接在 SQL 中完成。例如:过去 24 小时内创建的所有用户都将通过 SQL 查询返回(NOW() – 1 天)

一位开发人员和我之间正在进行一场辩论,我认为我们应该:

A. 将所有计算/代码/逻辑保存在 PHP 中,并将 MySQL 视为“愚蠢”的信息存储库

他的意见:

B. 根据更容易/更快的情况进行混合和匹配。http://www.onextrapixel.com/2010/06/23/mysql-has-functions-part-5-php-vs-mysql-performance/

我正在研究可维护性的观点。他关注的是速度(正如文章所指出的,MySQL 中的某些操作更快)。


@bob-the-destroyer @tekretic @OMG Ponies @mu 太短了 @Tudor Constantin @tandu @Harley

我同意(而且很明显)高效的 WHERE 子句属于 SQL 级别。但是,例如:

  1. 在 SQL 中使用 NOW() - 1 day 计算 24 周期以选择过去 24 小时内创建的所有用户?
  2. 返回所有用户的大写名字和姓氏?
  3. 连接一个字符串?
  4. (想法,伙计们?)

属于 SQL 域的明确示例:

  1. 特定的 WHERE 选择
  2. 嵌套 SQL 语句
  3. 订购/排序
  4. 选择 DISTINCT 项目
  5. 计数行/项目
4

6 回答 6

49

我会发挥每个系统的优势。

聚合、连接和过滤逻辑显然属于数据层。它更快,不仅因为大多数数据库引擎为此进行了 10 多年的优化,而且您可以最大限度地减少在数据库和 Web 服务器之间转移的数据。

另一方面,我使用的大多数数据库平台在处理单个值方面的功能都很差。诸如日期格式和字符串操作之类的东西在 SQL 中很糟糕,你最好在 PHP 中完成这项工作。

基本上,将每个系统用于其构建的目的。

在可维护性方面,只要清楚地区分发生在哪里,将这些划分为逻辑类型应该不会造成太大问题,当然也不足以抵消好处。在我看来,代码的清晰性和可维护性更多的是关于一致性,而不是把所有逻辑放在一个地方。


回复:具体例子...

  1. 我知道这也不是你所指的,但日期几乎是一个特例。您要确保系统生成的所有日期都是在 Web 服务器或数据库上创建的。如果数据库服务器和网络服务器曾经配置为不同的时区(我已经看到这种情况发生),否则这样做会导致一些潜在的错误。例如,想象一下,您有createdDate一个默认值的列,该列在 DBgetDate()插入时应用。如果您要插入一条记录,则使用PHP 中生成的日期(例如,选择在过去一小时内创建的记录,您可能无法得到您期望的结果。至于您应该在哪一层执行此操作,我倾向于使用数据库因为,如示例中所示,它允许您使用列默认值。date("Y-m-d", time() - 3600)

  2. 对于大多数应用程序,我会在 PHP 中执行此操作。结合名字和姓氏听起来很简单,直到你意识到有时你也需要称呼、头衔和中间名缩写。另外,您几乎肯定会遇到这样的情况:您想要用户的名字、姓氏以及称呼+名字+姓氏的组合。将它们连接到数据库端意味着您最终会移动更多数据,尽管实际上它非常小。

  3. 依靠。如上所述,如果您想单独使用它们,最好在性能方面将它们单独拉出并在需要时连接起来。也就是说,除非您处理的数据集很大,否则可能还有其他因素(如您提到的可维护性)具有更大的影响。

一些经验法则:

  • 生成增量 ID 应该发生在数据库中。
  • 就个人而言,我喜欢数据库应用的默认设置。
  • 选择时,任何减少记录数量的事情都应该由数据库完成。
  • 做一些减少数据集 DB 端大小的事情通常是件好事(比如上面的字符串示例)。
  • 正如你所说;排序、聚合、子查询、连接等应始终在数据库端。
  • 此外,我们还没有讨论过它们,但触发器通常是不好的/必要的。

您在这里面临一些核心权衡,而平衡实际上取决于您的应用程序。

有些事情绝对应该——每次——总是在 SQL 中完成。排除大量 SQL 任务的一些例外情况(如日期的事情)可能非常笨拙,并且可能会让您在逻辑上陷入困境。在您的代码库中搜索对特定列(例如)的引用时,容易错过视图或存储过程中包含的那些。

性能始终是一个考虑因素,但取决于您的应用程序和具体示例,可能不是一个大问题。您对可维护性的担忧可能非常有效,并且我提到的一些性能优势非常轻微,因此请注意过早的优化。

此外,如果其他系统直接访问数据库(例如,用于报告或导入/导出),您将从数据库中的更多逻辑中受益。例如,如果您想直接从另一个数据源导入用户,则可以在 SQL 中实现诸如电子邮件验证功能之类的可重用功能。

简短的回答:这取决于。:)

于 2011-06-23T03:57:26.580 回答
11

我不喜欢重新发明轮子。我也喜欢使用最好的工具来完成需要完成的任务,所以:

  • 当我可以直接从数据库中获取结果集而无需进一步处理时,我会这样做 - 你的情况是一个带有简单WHERE子句的简单查询。想象一下当你有 1000 万用户并且你让他们使用 PHP 时会发生什么,只需要 100 个——你猜对了——你的 Web 服务器很可能崩溃
  • 当您需要一次从 2 个或更多表中获取数据时,MySQL比 PHP好得多
  • 当您需要计算记录时 - 数据库非常擅长
  • 我倾向于支持 FK 约束的应用程序级处理
  • 此外,我倾向于避免存储过程,更喜欢在应用程序级别实现该业务逻辑(当然,除非我们谈论的是巨大的数据集)。

总之,我会说您的同事在所提出的案例中是正确的

于 2011-06-23T03:55:37.013 回答
8

如果您将一半的逻辑放在数据库中,另一半放在 php 中,那么当您进行更改时,需要 6 个月的时间才能弄清楚发生了什么。

尽管如此,你的数据库查询应该有足够的逻辑,以便它们为你的 php 提供它所需要的数据。如果您发现自己在 php 代码中循环了数千条 mysql 记录,那么您做错了什么。但是,在规模的另一端,如果您在 mysql 查询中运行 if / else 语句,那么您也做错了(可能只需要重写您的查询)。

我会避开存储过程。虽然它们在理论上是一个很棒的概念,但您通常可以在 php 中以更快的开发时间完成相同的结果,并且您还可以获得了解所有逻辑在哪里的额外好处。

于 2011-06-23T03:57:27.410 回答
6

随着结果集的增加,MySQL 将更好地扩展。坦率地说,将数据库视为“哑数据”存储库是一种资源浪费......

可维护性往往会受到熟悉程度的影响。如果您不熟悉 PHP,那么它不会是您最初选择的可维护性 - 是吗?

于 2011-06-23T03:50:33.253 回答
4

在 SQL 中获取数据所花费的时间非常耗时,但一旦完成,计算就会更加相同。获取数据后,无论哪种方式都不会花费太多时间,但是在 SQL 中巧妙地执行它可以为大型数据集提供更好的结果。

如果您从 MYSQL 获取数据,然后在 PHP 中对获取的数据进行计算,那么获取所需结果并避免 PHP 处理要好得多,因为它会增加更多时间。

一些基本点:

  1. MYSQL 中的日期格式很强大,大多数格式都在 Mysql 中可用。如果您有非常具体的日期格式,那么您可以使用 PHP。

  2. 字符串操作在 SQL 中很糟糕,最好在 PHP 中完成。如果您不需要进行大的字符串操作,那么您可以在 Mysql SELECTs 中进行操作。

  3. 选择时,任何减少记录数的事情都应该由 SQL 而不是 PHP

  4. 排序数据应始终在 Mysql 中完成

  5. 聚合应该始终在 Mysql 中完成,因为数据库引擎是专门为此设计的。

  6. 子查询和连接应始终在数据库端。它将减少您的大量 PHP 代码。当您需要一次从 2 个或更多表中获取数据时,SQL 比 PHP 好得多

  7. 想统计记录,SQL很棒。

于 2017-09-22T12:12:46.747 回答
1

每个问题的答案如下:

  1. 在 SQL 中使用 NOW() - 1 day 计算 24 周期以选择过去 24 小时内创建的所有用户?

  2. 使用 PHP 创建日期并使用 WHERE 子句查找数据。日期操作在 PHP 中实现起来要快得多。

  3. 返回所有用户的大写名字和姓氏?

  4. 选择数据库中的所有用户,然后使用 PHP 将字符串大写。同样,在 PHP 中实现起来要快得多。

  5. 连接一个字符串?

  6. 同样,PHP 用于字符串操作。

(想法,伙计们?)

使用 PHP 进行所有数据操作,因为它更容易实现。更清楚地说,$variable在 PHP 中操作一个简单的比在 SQL 中写出整个字符串操作更容易。在 PHP 中操作,然后在 SQL 中更新数据库。

属于 SQL 域的明确示例:

特定的 WHERE 选择 - 是的。

嵌套 SQL 语句 - 我会重新评估您的 PHP 数据处理,但如果您必须这样做,可以。

排序/排序 - 排序肯定是 SQL 语句的工作,但您应该只在 SELECT 语句上进行排序。任何其他排序,例如排序和更新数据库,都应该由 PHP 排序,因为再次操作 $vars 比写出 UPDATE SQL 语句更容易。

选择 DISTINCT 项目 - 是。

计数行/项目 - 使用:$Number_Of_Results = count($Results);在 PHP 中。

于 2020-06-26T23:28:53.457 回答