2

我是 PHP 新手,也是 Propel 新手。

正如我所读到的,Propel 有一个实例池来重用查询。

例如

    <?php
// first call
$author1 = AuthorQuery::create()->getByFooField('foo');
$foo = $author1->getId();
// SELECT query
...
// second call
$author2 = AuthorQuery::create()->getByFooField('Foo');
// Skips the SQL query and returns the existing $author1 object
$foo = $author2->getId();

事情是

这个物体存活了多少时间?这是因为我必须解析一个 excel,并构建一些对象以将它们保存在数据库中。

所以,也许在我读了 100 行的 excel 中,我读了 25 次 'foo',所以,如果我能避免 24 次查询,每次查询数据库以获得 PK 将是一件坏事。

看起来Instance Propel解决了这个问题,但我不知道多少次。

这取决于时间、使用的内存或执行查询的范围之类的东西?(我的意思是,可能在执行第一个查询的方法之后,实例池被清除了,所以,除非第二个查询在同一个方法中,否则它将再次查询数据库。或者当对象还活着时,我不知道不知道)

我搜索了一下,但没有找到任何东西,我的直觉告诉我这取决于使用的内存,但是,没有官方的。

或者也许有更好的方法来做到这一点。

4

1 回答 1

3

只需在我上面的评论之后添加一个答案。

基本上,实例池是按主键组织的对象集合。它不是查询缓存,而是特定实例之一。几乎在您请求特定记录的任何时候,它都会被添加到该类的实例池中。当你再次通过它的主键请求该记录时,Propel 将返回缓存的对象而不是访问数据库。任何时候你发出一个->find()Propel都会命中数据库,不管实例池是什么。

在您生成的基类中,您可以通过查找方法并查看其使用方式来查看此findPk行为。getInstanceFromPool()addInstanceToPool()

例如:

$entity1 = EntityQuery::create()->findPk(13); // WILL hit database
$entity2 = EntityQuery::create()->findPk(13); // WILL NOT hit database

// This WILL hit DB, even if there is only 1 record & it is in the instance pool
$entity3 = EntityQuery::create()->findOneByName("Record Thirteen");
// This will also hit the DB EVERY TIME, regardless of the instance pool
// even though it is the same query
$entity4 = EntityQuery::create()->findOneByName("Record Thirteen");

// This will always hit the database, even if the instance is in the pool
$entity5 = EntityQuery::create()->findByUniqueField("Unique Value");

希望这可以帮助。同样,这不是猜测,我已经进入代码并仔细检查了这一点。您可以查看生成的基类和propel/runtime/lib/query/ModelCriteria.php(特别是find()方法)以了解它是如何工作的。

于 2013-04-05T20:22:39.000 回答