CakePHP 3 - 由完整 SQL 语句键入的缓存查询
CakePHP 3 - Cache query keyed by full SQL statement
使用 我尝试将缓存添加到一个特别慢的查询中。
此查询具有固定的选定字段和限制,但三个组件可能因不同的用户而异:table 本身的 where
语句,加入的 [=36] 上的 on
过滤器=] 和 on
过滤第二个加入的 table.
所以我过滤主要 table 和两个连接的数据。
为了缓存工作,我需要将过滤条件合并到缓存键中。 为此目的,我如何提取所有查找过滤器(包括连接)?
如果我使用 $q->clause('where')
,就像在链接的建议中一样,我只会在主 table 上获得过滤器,而不是连接。 $q->clause('join')
为空。
$query = $this->Regions->find('veryComplicatedFinder')
->cache(function (\Cake\ORM\Query $q)
{
debug($q->clause('where'));
return 'test123';
}, 'queries');
我想我可能只使用整个 SQL 语句。但是,$q->sql()
结果类似于:
'SELECT ... FROM regions Regions INNER JOIN chains Chains ON
(Chains.id in (:c0,:c1,:c2) AND Chains.id = (Regions.chain_id)) LEFT
JOIN stores Stores ON (Stores.type in (:c388) AND Stores.type in
(:c389) AND Regions.id = (Stores.region_id)) LEFT JOIN sales Sales ON
Stores.id = (Sales.store_id) WHERE (Regions.shape &&
ST_MakeEnvelope(51.5,5,52,5.5,4326)) GROUP BY Regions.id LIMIT 2000'
好像没有包含绑定参数。
包含的连接是延迟构建的
如果 join
子句为空,那么您可能使用了包含,即 contain()
、*joinWith()
、matching()
、and/or notMatching()
方法。
包含连接只会在查询被编译时添加到查询对象的 join
子句中,直到那时它们都存在于预加载器中,它们的查询构建器回调尚未被评估。因此,虽然您可以这样获得它们:
// contain()
$contain = $query->getEagerLoader()->getContain();
// *joinWith()/matching()/notMatching()
$matching = $query->getEagerLoader()->getMatching();
条件尚未在任何地方应用。
获取绑定
也就是说,如果您想评估整个查询,那么您可以通过值绑定器访问绑定值,如下所示:
$sql = $query->sql();
$bindings = $query->getValueBinder()->bindings();
在查找器中构建缓存键
您可能要考虑的一种方法是将缓存键的责任部分转移到查找器中,即在您手边拥有所有必需信息的查找器中构建缓存键,并将它们设置在查询对象上 evaluate/use在其他地方。
它可能看起来像这样:
public function findVeryComplicatedFinder(\Cake\ORM\Query $query)
{
$cacheKey = '';
if ($abc) {
$cacheKey .= 'abc';
$query->leftJoinWith('Abc', function () {
// ...
});
}
if ($xyz) {
$cacheKey .= 'xyz';
$query->innerJoinWith('Xyz', function () {
// ...
});
}
// ...
$query->applyOptions([
'veryComplicatedFinderCacheKey' => $cacheKey
]);
return $query;
}
在您的主查询对象的 cache()
回调中,您可以读取该选项并使用它来构建最终的缓存键,大致如下:
$query = $this->Regions
->find('veryComplicatedFinder')
->cache(
function (\Cake\ORM\Query $query) {
$options = $query->getOptions();
$cacheKey =
'mainQueryCachKeyBasedOnWhateverYouRequire' .
$options['veryComplicatedFinderCacheKey'];
return $cacheKey;
},
'queries'
);
使用
此查询具有固定的选定字段和限制,但三个组件可能因不同的用户而异:table 本身的 where
语句,加入的 [=36] 上的 on
过滤器=] 和 on
过滤第二个加入的 table.
所以我过滤主要 table 和两个连接的数据。
为了缓存工作,我需要将过滤条件合并到缓存键中。 为此目的,我如何提取所有查找过滤器(包括连接)?
如果我使用 $q->clause('where')
,就像在链接的建议中一样,我只会在主 table 上获得过滤器,而不是连接。 $q->clause('join')
为空。
$query = $this->Regions->find('veryComplicatedFinder')
->cache(function (\Cake\ORM\Query $q)
{
debug($q->clause('where'));
return 'test123';
}, 'queries');
我想我可能只使用整个 SQL 语句。但是,$q->sql()
结果类似于:
'SELECT ... FROM regions Regions INNER JOIN chains Chains ON (Chains.id in (:c0,:c1,:c2) AND Chains.id = (Regions.chain_id)) LEFT JOIN stores Stores ON (Stores.type in (:c388) AND Stores.type in (:c389) AND Regions.id = (Stores.region_id)) LEFT JOIN sales Sales ON Stores.id = (Sales.store_id) WHERE (Regions.shape && ST_MakeEnvelope(51.5,5,52,5.5,4326)) GROUP BY Regions.id LIMIT 2000'
好像没有包含绑定参数。
包含的连接是延迟构建的
如果 join
子句为空,那么您可能使用了包含,即 contain()
、*joinWith()
、matching()
、and/or notMatching()
方法。
包含连接只会在查询被编译时添加到查询对象的 join
子句中,直到那时它们都存在于预加载器中,它们的查询构建器回调尚未被评估。因此,虽然您可以这样获得它们:
// contain()
$contain = $query->getEagerLoader()->getContain();
// *joinWith()/matching()/notMatching()
$matching = $query->getEagerLoader()->getMatching();
条件尚未在任何地方应用。
获取绑定
也就是说,如果您想评估整个查询,那么您可以通过值绑定器访问绑定值,如下所示:
$sql = $query->sql();
$bindings = $query->getValueBinder()->bindings();
在查找器中构建缓存键
您可能要考虑的一种方法是将缓存键的责任部分转移到查找器中,即在您手边拥有所有必需信息的查找器中构建缓存键,并将它们设置在查询对象上 evaluate/use在其他地方。
它可能看起来像这样:
public function findVeryComplicatedFinder(\Cake\ORM\Query $query)
{
$cacheKey = '';
if ($abc) {
$cacheKey .= 'abc';
$query->leftJoinWith('Abc', function () {
// ...
});
}
if ($xyz) {
$cacheKey .= 'xyz';
$query->innerJoinWith('Xyz', function () {
// ...
});
}
// ...
$query->applyOptions([
'veryComplicatedFinderCacheKey' => $cacheKey
]);
return $query;
}
在您的主查询对象的 cache()
回调中,您可以读取该选项并使用它来构建最终的缓存键,大致如下:
$query = $this->Regions
->find('veryComplicatedFinder')
->cache(
function (\Cake\ORM\Query $query) {
$options = $query->getOptions();
$cacheKey =
'mainQueryCachKeyBasedOnWhateverYouRequire' .
$options['veryComplicatedFinderCacheKey'];
return $cacheKey;
},
'queries'
);