【问题标题】:RedBean ORM performance [closed]RedBean ORM 性能 [关闭]
【发布时间】:2011-12-07 13:57:45
【问题描述】:

我想知道,Redbean ORM能否用于社交网络应用等性能导向的场景,即使多个用户同时拉取数千条数据,它是否稳定?另外我想知道Redbean是否消耗更多的内存空间?

谁能提供教义-推进-红豆的比较研究?

【问题讨论】:

  • 任何场景中编写纯 SQL 将为您提供更优化的代码。如果您关心性能,那么只需放弃整个 ORM 理念。
  • @tereško 如果可能的话,你能根据你的经验给出orm相对于纯sql的优缺点吗?我也会同时谷歌这个主题。

标签: php orm doctrine propel redbean


【解决方案1】:

我在这里与@tereško 不同 - ORM 可以使数据库查询更易于编写和维护。在我看来,Propel 和 Doctrine 有一些很棒的工作——好好利用它们!网上有很多性能比较,也可以查看NotORM(我没用过,但如果我没记错的话,他们会与 Doctrine 进行一些比较)。

如果您的吞吐量需要您执行原始 SQL,然后在该点进行优化。但就减少错误数量和提高生产力而言,我认为您的储蓄无论如何都会为更好的服务器提供资金。当然,您的里程可能会有所不同。

顺便说一下,我不知道 RedBean,但我有一种温和的观点,即在大多数情况下,Propel 比 Doctrine 更快,因为这些类是预先生成的。当 Propel 是唯一的选择时,我使用了它并坚持使用它,尽管我当然不会反对使用 Doctrine。

2018 年更新

多年后,Propel 2 仍处于 alpha 阶段,需要一些大型重构项目,遗憾的是这些项目都没有完成。尽管维护人员说这个 alpha 版在生产环境中使用得很好,因为它有很好的测试覆盖率,他们现在已经开始使用 Propel 3。不幸的是,在我写这篇文章的时候,它实际上还没有任何版本,尽管存储库已有一年的历史。

虽然我认为 Propel 是一个很棒的项目,但我想知道是否最好暂时使用其他东西。它可能会从灰烬中升起!

【讨论】:

  • 如果使用 orm 从 db 中提取超过 1000 条记录,是否会占用更多空间?很可能我认为 orm 输出将是对象数组的形式。
  • 一般来说,无论您的 ORM 是什么,您都应该警惕在内存中保存大量行。这个数字对于离线进程来说听起来不错,但对于 Web 请求来说却不是。相反,您应该分块进行:例如,从 50 个元素中选择 20 次;这将降低内存使用量。或者,如果它只是您应用程序的一小部分,您可以使用原始数据库调用(通过 ORM 保持数据库独立性)来完成此部分。最后(也是最好的)看看你是否可以把这个东西移到离线进程中。
  • 嗯,不错的火花。因此,您更喜欢以托管方式管理来自数据库的数据访问。并且应该由我们管理。
  • 谷歌“无梨推进”?很多结果,包括我博客上的一个:)。编辑:不要花太多时间在 ORM 系统之间做出决定。选择一个您喜欢的并运行它。在您现在的零用户系统和您未来的 Facebook 大小的系统之间,您可能会重写两到三遍。首先让它工作。
  • 由于我的博客似乎退出了谷歌(grr),我指的文章是here。它适用于 1.5,但在 1.6 上应该可以正常工作。
【解决方案2】:

@tereško 如果可能的话,您能否根据您的经验给出 orm 相对于纯 sql 的优缺点,我也会同时搜索该主题。 – Jaison Justus

嗯 .. 用 600 个字符来解释这一点很难。

我必须澄清一件事:这是关于 PHP 中的 ORM,尽管我很确定它也适用于某些 Ruby ORM,也许还有其他。

简而言之,你应该避免它们,但是如果你必须使用 ORM,那么你会更好地使用 Doctrine 2.x ,这是较小的邪恶。 (实现类似于 DataMapper 而不是 ActiveRecord)。

针对 ORM 的案例

一些开发人员喜欢使用 ORM 的主要原因也是他们最糟糕的一点:在 ORM 中很容易做简单的事情,性能成本非常低。这完全没问题。

1.指数复杂度

问题源于人们对所有事物都使用相同的工具。 如果你只有锤子 (..) 类型的问题。这将导致创建一个technical debt

起初编写新的数据库相关代码很容易。也许,因为你有一个大项目,第一周的管理层(因为稍后会出现其他问题 - 阅读The Mythical Man-Month,如果对细节感兴趣)决定雇用更多人。与一般 SQL 相比,您最终会更喜欢具有 ORM 技能的人。

但是,随着项目的进展,您将开始使用 ORM 来解决日益复杂的问题。您将开始绕过一些限制,最终您可能会遇到即使使用您知道的所有 ORM hack 也无法解决的问题......现在您没有 SQL 专家,因为您没有雇用他们。

此外,大多数流行的 ORM 都实现了ActiveRecord,这意味着您的应用程序的业务逻辑直接与 ORM 耦合。由于这种耦合,添加新功能将花费越来越多的时间。出于同样的原因,为它们编写好的单元测试非常困难。

2。性能

我已经提到,即使是简单的 ORM 使用(使用单个表,没有 JOIN)也会有一些性能成本。这是因为他们使用通配符* 来选择数据。当您只需要文章 ID 和标题列表时,获取内容是没有意义的。

当您需要基于多个条件的数据时,ORM 非常不适合处理多个表。考虑问题:

数据库包含 4 个表:ProjectsPresentationsSlidesBulletpoints

  • 项目有很多演示文稿
  • 演示文稿有很多幻灯片
  • 幻灯片有很多要点

并且您需要从与 ID 为 2、4 和 8 的 Projects 相关的 4 个最新 Presentations 中找到标记为“重要”的 Slides 中的所有 Bulletpoints 的内容。

这是一个用纯 SQL 编写的简单 JOIN,但在我见过的任何 ORM 实现中,这将导致 3 级嵌套循环,每个级别都有查询。


P.S.还有其他原因和副作用,但它们相对较小..暂时不记得任何其他重要问题。

【讨论】:

  • 顺便说一句:关于这个主题的有趣文章Object-Relational Mapping is the Vietnam of Computer Science
  • @JaisonJustus ,顺便说一句,我是“顺便说一句”的首字母缩写词。
  • 我明白你的意思,但我认为这不是不使用 ORM 的理由。正如您所说,您只需要聘请一些 SQL 专家并确保用纯 SQL 编写复杂的查询。 ORM 不会将 SQL 带走。问题是在哪里使用 ORM 以及在哪里使用 SQL,但相信我,如果您的页面变慢,您会发现这一点。仍然 +1 的好答案!
  • @PhillipWhelan ,好吧.. Kohana 的“ORM”更像是一个美化的查询构建器,而不是一个 ORM。当您必须提出一个复杂的请求时,您最终会 1:1 将纯 SQL 转换为 kORM 化的方法调用,从而将其转换回 SQL。您最终只会掩盖您的查询,并在处理过程中失去对生成的 SQL 的控制。
  • ORM 有利于快速开发。当您的查询很复杂时,请使用纯 SQL 写入。我将两者混合。
【解决方案3】:

我觉得Tereško的回答不太对。

首先,它没有解决原始问题。这确实是针对 ORM 的案例,我同意他的回答中描述的问题。这就是我编写 RedBeanPHP 的原因。仅仅因为大多数 ORM 未能让您的生活更轻松并不意味着对象关系映射系统的概念是有缺陷的。大多数 ORM 都试图隐藏 SQL,这就是 JOIN 变得如此复杂的原因;他们需要在面向对象的环境中重新发明类似的东西。这就是 RedBeanPHP 的不同之处,因为它不隐藏 SQL。它创建易于查询的可读、有效的 SQL 表。 RedBeanPHP 使用普通的旧 SQL 进行记录和 bean 检索,而不是虚构的查询语言。简而言之; RedBeanPHP 使用 SQL 而不是反对它。这使它变得不那么复杂。

是的,RedBeanPHP 的性能很好。我怎么能这么肯定?因为与其他 ORM 不同,RedBeanPHP 区分了开发模式和生产模式。在开发周期中,数据库是流动的;您可以添加条目,它们将被动态添加。 RedBeanPHP 创建列、索引、猜测数据类型等。如果您在一段时间后需要更多字节(更高的数据类型),它甚至会扩展列。这使得 RedBeanPHP 非常慢,但仅在开发期间速度不应该成为问题。完成开发后,您可以使用带有单一模式说明符 R::freeze() 的冻结数据库,并且不再进行检查。剩下的是生产服务器上的一个非常简单的数据库层。而且因为做的不多,所以性能很好。

是的,我知道,我是 RedBeanPHP 的作者,所以我有偏见。然而,我觉得我的 ORM 被视为与其他 ORM 相同,这促使我写了这篇文章。如果您想了解更多,请随时咨询RedBeanPHP website,这里是discussion on performance

在我们公司,我们将 RedBeanPHP 用于嵌入式系统以及金融业务系统,因此它似乎可以很好地扩展。

我和 RedBeanPHP 社区一起真诚地努力让 ORM 世界变得更美好;你可以阅读使命宣言here

祝你的项目好运,我希望你找到你正在寻找的技术解决方案。

【讨论】:

  • RedBeanPHP 缺少对表前缀的支持,这是一个丑陋的特征,但仍然被广泛使用。它也感觉不完全集成,因为可链接查询不直接返回 ORM 对象列表。您需要为此显式调用 R::convertToBeans。
  • @PhillipWhelan - 我认为 RedBean 会欢迎功能请求。您在错误跟踪器上提出了它? :)
  • @halfer 这个问题已经出现在邮件列表中,并且出于性能原因以及能够支持 RedBeanPHP 3 中的一些新功能而被决定反对。虽然理论上我可以同意这是现实生活工作的真实性质并不总是允许这样做。
  • 我还要补充一点,性能问题可能不是 ORM 代码,而是底层数据库大小和查询复杂性。特别是对于后者,RB 迟早会停止,而您将留下手动制作的 SQL 查询——这些查询的好坏与您编写的查询一样好或坏。这不是针对 RB 的情况,而是因为它的灵活性......
  • 我刚刚放弃了doctrine2,因为它无法执行复杂的查询并开始尝试redbeanphp。到目前为止,我喜欢 redbean 的地方是您不必偏离 SQL 查询。我不喜欢的是它通常缺乏表前缀支持和命名 - 我更喜欢写表名 order_detail 或 OrderDetail 而不是 orderdetail,但也许这只是我。
【解决方案4】:

我会选择“马为课程”的情况,它利用了两个世界的混合和匹配。我已经使用 RedBean 构建了一些大型应用程序,因此我的评论将仅关注 RedBean 而不是其他 ORM。

RedBean ORM 速度慢吗?

嗯,这取决于你如何使用它。在某些情况下,它比传统查询更快,因为 RedBean 将结果缓存几秒钟。重用查询将更快地产生结果。使用R::debug(true);查看日志它总是显示

"SELECT * FROM `table` -- keep-cache"

场景 1:获取所有 (*)

在 RedBean 中查询

$result = R::findOne('table', ' id = ?', array($id));

这表示为

$result= mysql_query("Select * from TABLE where id =".$id);

您可能会争辩说,如果表有多个列,为什么要查询 (*)

场景 2:单列

获取单个列

R::getCol( 'SELECT first_name FROM accounts' );

就像我提到的“Horses for Courses”,开发者不应该仅仅依赖FindOne, FindAll, FindFirst, FindLast,还要仔细起草他们真正需要的东西。

场景 3:缓存

当您不需要缓存时,您可以在应用程序级别禁用,这不是理想的情况

R::$writer->setUseCache(true);

RedBean 建议,如果您不想在应用程序级别禁用缓存,则应使用带有 no-cache 参数的传统查询,例如 $result = R::exec("SELECT SQL_NO_CACHE * FROM TABLE");

通过完全丢弃查询缓存,完美解决了从表中获取实时数据的问题。

场景 4:快速发展

使用 ORM 使您的应用程序开发速度非常快,开发人员使用 ORM 进行编码的速度比编写 SQL 快 2-3 倍。

场景 5:复杂查询和关系

RedBean 提供了一种非常好的实现复杂查询和one-to-manymany-to-many 关系的方法

用于复杂查询的普通 SQL

$books = R::getAll( 'SELECT 
    book.title AS title, 
    author.name AS author, 
    GROUP_CONCAT(category.name) AS categories FROM book
    JOIN author ON author.id = book.author_id
    LEFT JOIN book_category ON book_category.book_id = book.id
    LEFT JOIN category ON book_category.category_id = category.id 
    GROUP BY book.id
    ' );
    foreach( $books as $book ) {
        echo $book['title'];
        echo $book['author'];
        echo $book['categories'];
    }

OR RedBean 处理多对多关系的方式

list($vase, $lamp) = R::dispense('product', 2);

$tag = R::dispense( 'tag' );
$tag->name = 'Art Deco';

//creates product_tag table!
$vase->sharedTagList[] = $tag;
$lamp->sharedTagList[] = $tag;
R::storeAll( [$vase, $lamp] );

性能问题

像 ORM 之类的参数通常很慢,消耗更多内存并且往往会使应用程序变慢。我认为他们不是在谈论 RedBean。

我们已经使用 MySQL 和 Postgres 对其进行了测试,相信我的性能从来都不是瓶颈。

不可否认,ORM 增加的开销很小,而且往往会使您的应用程序变慢(只是一点点)。使用 ORM 主要是在开发人员时间和稍慢的运行时性能之间进行权衡。我的策略是首先使用 ORM 构建端到端的应用程序,然后基于测试用例,调整速度关键模块以使用直接数据访问。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 2012-05-28
    • 2023-03-06
    • 2011-06-07
    • 2014-04-11
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多