在MySQL和PHP中进行计算

时间:2011-06-23 03:41:53

标签: php mysql performance maintainability

背景:

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

一位开发者与我之间正在进行辩论,我认为我们应该这样做:

一个。保留PHP中的所有计算/代码/逻辑,并将MySQL视为“哑”信息库

他的意见:

B中。根据什么更轻松/更快地进行混合搭配。 http://www.onextrapixel.com/2010/06/23/mysql-has-functions-part-5-php-vs-mysql-performance/

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


@鲍勃最破坏者 @tekretic @OMG小马 @mu太短了 @Tudor Constantin @tandu @Harley

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

  1. 使用NOW()计算24个句点 - 在SQL中选择1天以选择过去24小时内创建的所有用户?
  2. 返回所有用户的大写名字和姓氏?
  3. 连接字符串?
  4. (想法,伙计?)
  5. 清除属于SQL域的示例:

    1. 具体WHERE选择
    2. 嵌套SQL语句
    3. 订购/排序
    4. 选择DISTINCT项目
    5. 计算行/项目

6 个答案:

答案 0 :(得分:41)

我发挥每个系统的优势。

聚合,加入和过滤逻辑显然属于数据层。它的速度更快,不仅因为大多数数据库引擎都有10年以上的优化时间,而且还可以最大限度地减少数据库和Web服务器之间的数据转移。

另一方面,我使用的大多数数据库平台在处理单个值时都具有非常差的功能。事情就像日期格式化和字符串操作只是在SQL中吮吸,你最好用PHP做这项工作。

基本上,使用每个系统来构建它。

就可维护性而言,只要在明确的地方之间进行划分,将这些划分为逻辑类型不应该造成太多问题,当然也不足以超出好处。在我看来,代码清晰度和可维护性更多地是关于一致性,而不是将所有逻辑放在一个地方。


回复:具体的例子......

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

  2. 对于大多数应用程序,我会在PHP中执行此操作。结合名字和姓氏听起来很简单,直到你意识到你有时也需要称呼,标题和中间姓名首字母。此外,你几乎肯定会在你想要用户名字,姓氏和联合致敬+名字+姓氏的情况下结束。将它们连接在一起DB端意味着你最终会移动更多的数据,尽管它确实很小。

  3. 取决于。如上所述,如果您想要单独使用它们,那么最好将性能分别拉出来并在需要时连接。也就是说,除非您处理的数据集很大,否则可能还有其他因素(例如,如您所说,可维护性)更具影响力。

  4. 一些经验法则:

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

    您在这里面临一些核心权衡取舍,余额实际上取决于您的申请。

    有些事情肯定 - 每次 - 总是在SQL中完成。排除许多任务的一些异常(比如日期事物),SQL可能非常笨重,可以让你在逻辑上不受限制。在代码库中搜索特定列的引用时(例如) 很容易错过视图或存储过程中包含的那些。

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

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

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

答案 1 :(得分:8)

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

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

总之,我会说你的同事在提交的案件中是正确的

答案 2 :(得分:7)

如果你把一半的逻辑放在数据库中,而另一半放在php中,那么当你进行改变时,你需要花费两倍的时间才能弄清楚发生了什么。

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

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

答案 3 :(得分:6)

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

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

答案 4 :(得分:3)

在SQL中获取数据所花费的时间非常耗时,但一旦完成计算的时间相同。在获取数据之后,无论采用哪种方式,在SQL中巧妙地执行此操作都可以为大型数据集提供更好的结果。

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

一些基本要点:

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

  2. 字符串操作只是吮吸SQL,最好在PHP中完成这项工作。如果你没有需要进行大的字符串操作,那么你可以在Mysql SELECTs中进行。

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

  4. 订购数据应始终在Mysql

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

  7. 子查询和联接应始终为DB端。它会减少你的大量PHP代码。当您需要同时从两个或多个表中获取数据时,SQL要比PHP好得多

  8. 想要记录记录,SQL很棒。

答案 5 :(得分:1)

每个问题的答案如下:

  1. 使用NOW()-用SQL中的1天计算24个期间来选择过去24小时内创建的所有用户吗?

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

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

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

  5. 连接字符串?

  6. 再次使用PHP进行字符串操作。

(想法,伙计?)

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

清除属于SQL域的示例:

特定的WHERE选择-是。

嵌套的SQL语句-我将重新评估PHP数据处理,但如果需要,可以。

排序/排序-排序确实是SQL语句的工作,但您仅应在SELECT语句上进行排序。任何其他排序(例如,对数据库进行排序和更新)都应该由PHP进行排序,因为同样,操作$ vars比写出UPDATE SQL语句要容易得多。

选择DISTINCT项目-是。

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