如何在 Zend_Db_Table 之上以一种高性能的方式使用 RDBMS? (如果有的话……)

发布于 2024-10-17 12:37:54 字数 552 浏览 8 评论 0原文

当我从事 Zend Framework 项目时,我的脑海中一直萦绕着这种持续不断的战争——良好的应用程序设计要求数据库查询的数量最小化。每个查询的延迟和 RDBMS 计算时间都很昂贵。 Zend_Db_Table 鼓励您进行大量查询——例如,没有内置方法可以与其他 Zend_Db_Table 进行 JOIN。并且没有办法在给定 Zend_Db_Table 实例的情况下提取基础表的名称,这使得根据 Zend_Db_Table 编写 Zend_Db_Select 查询变得困难。从某种意义上说,Zend_Db_Table 鼓励您实现 RDBMS 已经在 PHP 中提供的功能,这显然不是最理想的。

另一方面,Zend_Db_Table 通过抽象 SQL 查询本身,使表的行为更像本机 PHP 对象。用户不必担心经常引用,并且 SQL 操作被公开为简单的 PHP 方法。

最好是像 Zend_Db_Table 这样的东西,但是它会使用惰性操作(就像微软对 LINQ-to-SQL/实体框架/等所做的那样),以便将看似多个 PHP 语句压缩成一个(或者在至少更少)RDBMS quer(y|ies)。

这样的事存在吗?它是否包含在 Zend 中?

There's this constant war going on in my thoughts when I work on a Zend Framework project -- good application design mandates that the number of database queries be minimized. Each query is expensive in terms of both latency and RDBMS calculation time. And Zend_Db_Table encourages you to make lots of queries -- there's no built in way to JOIN with other Zend_Db_Tables, for example. And there's no way to extract the name of the underlying table given an instance of Zend_Db_Table, which makes writing Zend_Db_Select queries in terms of Zend_Db_Table difficult. In a sense, Zend_Db_Table encourages you to implement features the RDBMS already provides in PHP, which is obviously suboptimal.

On the other hand, Zend_Db_Table makes tables behave a bit more like native PHP objects by abstracting away the SQL queries themselves. The user need not worry about quoting all that often, and SQL operations are exposed as simple PHP methods.

What would be nice would be something like Zend_Db_Table, but which would use lazy operations (as Microsoft does with LINQ-to-SQL/Entity Framework/etc.) in order to condense what seems to be multiple PHP statements into a single (or at least fewer) RDBMS quer(y|ies).

Does such a thing exist? Is it included with Zend or not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

dawn曙光 2024-10-24 12:37:54

我同意你的观点,Zend_Db_Table 有时会充当寻找钉子的锤子。它并不总是用于编写带有联接的自定义高性能查询的最自然的工具。在我看来,Zend_Db_Table 主要对于没有连接的单个表来说是最佳的。但仍然可以使用 Zend_Db 组件的各个方面来执行最佳数据库查询。

正如 @singles 所指出的,所有这些数据库访问可能应该隐藏在模型中(对于 ActiveRecord 类型的方法)或映射器(对于 DataMapper 方法)或实体管理器(如 Doctrine2)中。

例如,您的自定义 BlogPost 模型可以提供自定义 BlogPostDataAccess 的实例,而自定义 BlogPostDataAccess 的实例将提供 Zend_Db_Adapter 的实例。您的所有查询(包括优化的联接)都将驻留在 BlogPost_DataAccess 类中。 DataAccess 类中的 SELECT 查询可以使用类似(伪代码)的内容编写:

$select = $adapter->select()
        ->join()
        ->join()
        // etc.
        ->join()
        ->where()
        ->limit()
        ->order();

明白我的意思吗?

更新

$tableMap 成员变量怎么样?类似的东西:

public static $tableMap = array(
    'posts'        => 'table_posts',
    'users'        => 'table_users',
    'categories'   => 'table_categories',
    // etc
);

然后在您的查询中,您可以使用类似的东西:

$select = $adapter->select();
$select->from(self::$tableMap['users'], array('name', 'email'));

也许添加名为 setTableMap($tableMap)getTableMap()getTable($k) 的方法setTable($k),将初始映射数据存储在配置文件中,然后在引导期间填充静态成员。

I agree with you that Zend_Db_Table sometimes acts as a hammer in search of nail. It's not always the most natural tool for writing customized, performant queries with joins. It seems to me that Zend_Db_Table is optimal primarily for a single table without joins. But it is still possible to do optimal db querying using aspects of the Zend_Db component.

As noted by @singles, all this db access should probably be buried inside a model (for an ActiveRecord type of approach) or in a mapper (for a DataMapper approach) or in an entity manager (like Doctrine2) does.

For exmaple, your custom BlogPost model could be fed an instance of a custom BlogPostDataAccess which would be fed an instance of Zend_Db_Adapter. All your queries - including your optimized joins - would reside within the BlogPost_DataAccess class. The SELECT queries in the DataAccess class could be written using soemthing like (pseudocode):

$select = $adapter->select()
        ->join()
        ->join()
        // etc.
        ->join()
        ->where()
        ->limit()
        ->order();

See what I mean?

Update

How about a $tableMap member variable? Something like:

public static $tableMap = array(
    'posts'        => 'table_posts',
    'users'        => 'table_users',
    'categories'   => 'table_categories',
    // etc
);

Then in your queries, you could use something like:

$select = $adapter->select();
$select->from(self::$tableMap['users'], array('name', 'email'));

Maybe add methods called setTableMap($tableMap), getTableMap(), getTable($k), setTable($k), store the initial mapping data in a config file and then populate the static member during bootstrap.

嘿哥们儿 2024-10-24 12:37:54

有些点需要澄清:

  1. 就像你说的 - Zend_Db_Table 没有实现“自动连接”,换句话说可以称为渴望加载。如果你需要这样的功能,可以看看 PHP-AR
  2. 可以在 中实现预加载你自己的 Zend_Db_Table - 我花了一些时间思考它,并且我很确定它可以完成。但我没有时间这样做:)
  3. 但是从另一面来看 - Zend_Db_Table 是你的应用程序模型的一部分。您应该担心如何获取数据,您对数据本身感兴趣。更进一步 - 如果您使用胖模型,瘦/瘦控制器态度,您可以快速实现方法内部所需的连接,这对于大多数情况来说已经足够了。
    示例: http://pastebin.com/pNwideWf (我链接到粘贴箱,因为代码格式化不在编辑器中不能正常工作)。

不幸的是,使用这种方法,您将无法在连接表中保存数据,并且必须注意列名称:您不能执行 $row->joined_table->field_from_joined_table - 相反,您可以$row->joined_table_field_from_joined_table

总结 - 如果您想要性能,请使用前面提到的胖模型 - 将获取/过滤数据的所有逻辑存储在模型类中,在您的情况下是 Zend_Db_Table

Some points need clarification:

  1. Like you said - Zend_Db_Table doesn't implement "auto join", in another way could be called eager loading. If you need such a functionality, take a look at PHP-AR
  2. It's possible to implement eager loading in Zend_Db_Table on your own - I spent some time thinking about it, and I'm pretty sure, that it can be done. But I don't have time to do it :)
  3. But looking from the other side - Zend_Db_Table is a part of model of your app. You should worry how your data are fetched, you're interested in data itself. Going further - if you use fat model, thin/skinny controller attitude, you can implement join that you need inside method in quick way, which will be sufficient for most of cases.
    Example: http://pastebin.com/pNwideWf (I'm linking to paste bin, because code formating don't work properly for me in editor).

Unfortunately, using that aproach, you won't be able to save data in joined tables, and you must watch out with column names: you can't do $row->joined_table->field_from_joined_table - instead of this you can $row->joined_table_field_from_joined_table.

Summarizing - if you want performance, use fat models as mentioned before - store all logic of fetching/filtering data in model classes, in your case Zend_Db_Table.

匿名。 2024-10-24 12:37:54

看一下 NotORM 数据库层。那可能可以满足您的需要;)

Take a look at NotORM database layer. That might do what you need ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文