如何在 Zend_Db_Table 之上以一种高性能的方式使用 RDBMS? (如果有的话……)
当我从事 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我同意你的观点,
Zend_Db_Table
有时会充当寻找钉子的锤子。它并不总是用于编写带有联接的自定义高性能查询的最自然的工具。在我看来,Zend_Db_Table
主要对于没有连接的单个表来说是最佳的。但仍然可以使用Zend_Db
组件的各个方面来执行最佳数据库查询。正如 @singles 所指出的,所有这些数据库访问可能应该隐藏在模型中(对于 ActiveRecord 类型的方法)或映射器(对于 DataMapper 方法)或实体管理器(如 Doctrine2)中。
例如,您的自定义
BlogPost
模型可以提供自定义BlogPostDataAccess
的实例,而自定义BlogPostDataAccess
的实例将提供Zend_Db_Adapter
的实例。您的所有查询(包括优化的联接)都将驻留在BlogPost_DataAccess
类中。 DataAccess 类中的SELECT
查询可以使用类似(伪代码)的内容编写:明白我的意思吗?
更新
$tableMap
成员变量怎么样?类似的东西:然后在您的查询中,您可以使用类似的东西:
也许添加名为
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 thatZend_Db_Table
is optimal primarily for a single table without joins. But it is still possible to do optimal db querying using aspects of theZend_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 customBlogPostDataAccess
which would be fed an instance ofZend_Db_Adapter
. All your queries - including your optimized joins - would reside within theBlogPost_DataAccess
class. TheSELECT
queries in the DataAccess class could be written using soemthing like (pseudocode):See what I mean?
Update
How about a
$tableMap
member variable? Something like:Then in your queries, you could use something like:
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.有些点需要澄清:
Zend_Db_Table
没有实现“自动连接”,换句话说可以称为渴望加载。如果你需要这样的功能,可以看看 PHP-AR中实现预加载你自己的 Zend_Db_Table
- 我花了一些时间思考它,并且我很确定它可以完成。但我没有时间这样做:)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:
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-ARZend_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 :)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
.看一下 NotORM 数据库层。那可能可以满足您的需要;)
Take a look at NotORM database layer. That might do what you need ;)