|
|
@ -1,354 +1,284 @@ |
|
|
|
Data Caching |
|
|
|
Data Caching |
|
|
|
============ |
|
|
|
============ |
|
|
|
|
|
|
|
|
|
|
|
Data caching is about storing some PHP variable in cache and retrieving it later from cache. For this purpose, |
|
|
|
Data caching is about storing some PHP variable in cache and retrieving it later from cache. |
|
|
|
the cache component base class [[yii\caching\Cache]] provides two methods that are used most of the time: |
|
|
|
It is also the foundation for more advanced caching features, such as [query caching](#query-caching) |
|
|
|
[[yii\caching\Cache::set()|set()]] and [[yii\caching\Cache::get()|get()]]. Note, only serializable variables and objects could be cached successfully. |
|
|
|
and [content caching](caching-content.md). |
|
|
|
|
|
|
|
|
|
|
|
To store a variable `$value` in cache, we choose a unique `$key` and call [[yii\caching\Cache::set()|set()]] to store it: |
|
|
|
The following code is a typical usage pattern of data caching, where `$cache` refers to |
|
|
|
|
|
|
|
a [cache component](#cache-components): |
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
|
|
|
|
Yii::$app->cache->set($key, $value); |
|
|
|
|
|
|
|
``` |
|
|
|
``` |
|
|
|
|
|
|
|
// try retrieving $data from cache |
|
|
|
|
|
|
|
$data = $cache->get($key); |
|
|
|
|
|
|
|
|
|
|
|
The cached data will remain in the cache forever unless it is removed because of some caching policy |
|
|
|
if ($data === false) { |
|
|
|
(e.g. caching space is full and the oldest data are removed). To change this behavior, we can also supply |
|
|
|
|
|
|
|
an expiration parameter when calling [[yii\caching\Cache::set()|set()]] so that the data will be removed from the cache after |
|
|
|
|
|
|
|
a certain period of time: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
|
|
|
|
// keep the value in cache for at most 45 seconds |
|
|
|
|
|
|
|
Yii::$app->cache->set($key, $value, 45); |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Later when we need to access this variable (in either the same or a different web request), we call [[yii\caching\Cache::get()|get()]] |
|
|
|
// $data is not found in cache, calculate it from scratch |
|
|
|
with the key to retrieve it from cache. If the value returned is `false`, it means the value is not available |
|
|
|
|
|
|
|
in cache and we should regenerate it: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
// store $data in cache so that it can be retrieved next time |
|
|
|
public function getCachedData() |
|
|
|
$cache->set($key, $data); |
|
|
|
{ |
|
|
|
|
|
|
|
$key = /* generate unique key here */; |
|
|
|
|
|
|
|
$value = Yii::$app->cache->get($key); |
|
|
|
|
|
|
|
if ($value === false) { |
|
|
|
|
|
|
|
$value = /* regenerate value because it is not found in cache and then save it in cache for later use */; |
|
|
|
|
|
|
|
Yii::$app->cache->set($key, $value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return $value; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// $data is available here |
|
|
|
``` |
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
This is the common pattern of arbitrary data caching for general use. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When choosing the key for a variable to be cached, make sure the key is unique among all other variables that |
|
|
|
## Cache Components <a name="cache-components"></a> |
|
|
|
may be cached in the application. It is **NOT** required that the key is unique across applications because |
|
|
|
|
|
|
|
the cache component is intelligent enough to differentiate keys for different applications. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some cache storages, such as MemCache, APC, support retrieving multiple cached values in a batch mode, |
|
|
|
Data caching relies on the so-called *cache components* which represent various cache storage, |
|
|
|
which may reduce the overhead involved in retrieving cached data. A method named [[yii\caching\Cache::mget()|mget()]] is provided |
|
|
|
such as memory, files, databases. |
|
|
|
to exploit this feature. In case the underlying cache storage does not support this feature, |
|
|
|
|
|
|
|
[[yii\caching\Cache::mget()|mget()]] will still simulate it. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To remove a cached value from cache, call [[yii\caching\Cache::delete()|delete()]]; and to remove everything from cache, call |
|
|
|
Cache components are usually registered as application components so that they can be globally configurable |
|
|
|
[[yii\caching\Cache::flush()|flush()]]. |
|
|
|
and accessible. The following code shows how to configure the `cache` application component to use |
|
|
|
Be very careful when calling [[yii\caching\Cache::flush()|flush()]] because it also removes cached data that are from |
|
|
|
[memcached](http://memcached.org/) with two cache servers: |
|
|
|
other applications if the cache is shared among different applications. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note, because [[yii\caching\Cache]] implements `ArrayAccess`, a cache component can be used liked an array. The followings |
|
|
|
|
|
|
|
are some examples: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
```php |
|
|
|
$cache = Yii::$app->cache; |
|
|
|
'components' => [ |
|
|
|
$cache['var1'] = $value1; // equivalent to: $cache->set('var1', $value1); |
|
|
|
'cache' => [ |
|
|
|
$value2 = $cache['var2']; // equivalent to: $value2 = $cache->get('var2'); |
|
|
|
'class' => 'yii\caching\MemCache', |
|
|
|
|
|
|
|
'servers' => [ |
|
|
|
|
|
|
|
[ |
|
|
|
|
|
|
|
'host' => 'server1', |
|
|
|
|
|
|
|
'port' => 11211, |
|
|
|
|
|
|
|
'weight' => 100, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
[ |
|
|
|
|
|
|
|
'host' => 'server2', |
|
|
|
|
|
|
|
'port' => 11211, |
|
|
|
|
|
|
|
'weight' => 50, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
], |
|
|
|
``` |
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
### Cache Dependency |
|
|
|
You can then access the above cache component using the expression `Yii::$app->cache`. |
|
|
|
|
|
|
|
|
|
|
|
Besides expiration setting, cached data may also be invalidated according to some dependency changes. For example, if we |
|
|
|
Because all cache components support the same set of APIs, you can swap the underlying cache component |
|
|
|
are caching the content of some file and the file is changed, we should invalidate the cached copy and read the latest |
|
|
|
with a different one by reconfiguring it in the application configuration without modifying the code that uses the cache. |
|
|
|
content from the file instead of the cache. |
|
|
|
For example, you can modify the above configuration to use [[yii\caching\ApcCache|APC cache]]: |
|
|
|
|
|
|
|
|
|
|
|
We represent a dependency as an instance of [[yii\caching\Dependency]] or its child class. We pass the dependency |
|
|
|
|
|
|
|
instance along with the data to be cached when calling [[yii\caching\Cache::set()|set()]]. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
```php |
|
|
|
use yii\caching\FileDependency; |
|
|
|
'components' => [ |
|
|
|
|
|
|
|
'cache' => [ |
|
|
|
// the value will expire in 30 seconds |
|
|
|
'class' => 'yii\caching\ApcCache', |
|
|
|
// it may also be invalidated earlier if the dependent file is changed |
|
|
|
], |
|
|
|
Yii::$app->cache->set($id, $value, 30, new FileDependency(['fileName' => 'example.txt'])); |
|
|
|
], |
|
|
|
``` |
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Now if we retrieve $value from cache by calling `get()`, the dependency will be evaluated and if it is changed, we will |
|
|
|
> Tip: You can register multiple cache application components. The component named `cache` is used |
|
|
|
get a false value, indicating the data needs to be regenerated. |
|
|
|
by default by many cache-dependent classes (e.g. [[yii\web\UrlManager]]). |
|
|
|
|
|
|
|
|
|
|
|
Below is a summary of the available cache dependencies: |
|
|
|
|
|
|
|
|
|
|
|
### Supported Cache Storage <a name="supported-cache-storage"></a> |
|
|
|
- [[yii\caching\FileDependency]]: the dependency is changed if the file's last modification time is changed. |
|
|
|
|
|
|
|
- [[yii\caching\GroupDependency]]: marks a cached data item with a group name. You may invalidate the cached data items |
|
|
|
Yii supports a wide range of cache storage. The following is a summary: |
|
|
|
with the same group name all at once by calling [[yii\caching\GroupDependency::invalidate()]]. |
|
|
|
|
|
|
|
- [[yii\caching\DbDependency]]: the dependency is changed if the query result of the specified SQL statement is changed. |
|
|
|
* [[yii\caching\ApcCache]]: uses PHP [APC](http://php.net/manual/en/book.apc.php) extension. This option can be |
|
|
|
- [[yii\caching\ChainedDependency]]: the dependency is changed if any of the dependencies on the chain is changed. |
|
|
|
considered as the fastest one when dealing with cache for a centralized thick application (e.g. one |
|
|
|
- [[yii\caching\ExpressionDependency]]: the dependency is changed if the result of the specified PHP expression is |
|
|
|
server, no dedicated load balancers, etc.). |
|
|
|
changed. |
|
|
|
* [[yii\caching\DbCache]]: uses a database table to store cached data. To use this cache, you must |
|
|
|
|
|
|
|
create a table as specified in [[yii\caching\DbCache::cacheTable]]. |
|
|
|
### Query Caching |
|
|
|
* [[yii\caching\DummyCache]]: serves as a cache placeholder which does no real caching. |
|
|
|
|
|
|
|
The purpose of this component is to simplify the code that needs to check the availability of cache. |
|
|
|
For caching the result of database queries you can wrap them in calls to [[yii\db\Connection::beginCache()]] |
|
|
|
For example, during development or if the server doesn't have actual cache support, you may configure |
|
|
|
and [[yii\db\Connection::endCache()]]: |
|
|
|
a cache component to use this cache. When an actual cache support is enabled, you can switch to use |
|
|
|
|
|
|
|
the corresponding cache component. In both cases, you may use the same code |
|
|
|
|
|
|
|
`Yii::$app->cache->get($key)` to attempt retrieving data from the cache without worrying that |
|
|
|
|
|
|
|
`Yii::$app->cache` might be `null`. |
|
|
|
|
|
|
|
* [[yii\caching\FileCache]]: uses standard files to store cached data. This is particular suitable |
|
|
|
|
|
|
|
to cache large chunk of data, such as page content. |
|
|
|
|
|
|
|
* [[yii\caching\MemCache]]: uses PHP [memcache](http://php.net/manual/en/book.memcache.php) |
|
|
|
|
|
|
|
and [memcached](http://php.net/manual/en/book.memcached.php) extensions. This option can be considered as |
|
|
|
|
|
|
|
the fastest one when dealing with cache in a distributed applications (e.g. with several servers, load |
|
|
|
|
|
|
|
balancers, etc.) |
|
|
|
|
|
|
|
* [[yii\redis\Cache]]: implements a cache component based on [Redis](http://redis.io/) key-value store |
|
|
|
|
|
|
|
(redis version 2.6.12 or higher is required). |
|
|
|
|
|
|
|
* [[yii\caching\WinCache]]: uses PHP [WinCache](http://iis.net/downloads/microsoft/wincache-extension) |
|
|
|
|
|
|
|
([see also](http://php.net/manual/en/book.wincache.php)) extension. |
|
|
|
|
|
|
|
* [[yii\caching\XCache]]: uses PHP [XCache](http://xcache.lighttpd.net/) extension. |
|
|
|
|
|
|
|
* [[yii\caching\ZendDataCache]]: uses |
|
|
|
|
|
|
|
[Zend Data Cache](http://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm) |
|
|
|
|
|
|
|
as the underlying caching medium. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> Tip: You may use different cache storage in the same application. A common strategy is to use memory-based |
|
|
|
|
|
|
|
cache storage to store data that is small but constantly used (e.g. statistical data), and use file-based |
|
|
|
|
|
|
|
or database-based cache storage to store data that is big and less frequently used (e.g. page content). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Cache APIs <a name="cache-apis"></a> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
All cache components have the same base class [[yii\caching\Cache]] and thus support the following APIs: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* [[yii\caching\Cache::get()|get()]]: retrieves a data item from cache with a specified key. A false |
|
|
|
|
|
|
|
value will be returned if the data item is not found in the cache or is expired/invalidated. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::set()|set()]]: stores a data item identified by a key in cache. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::add()|add()]]: stores a data item identified by a key in cache if the key is not found in the cache. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::mget()|mget()]]: retrieves multiple data items from cache with the specified keys. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::mset()|mset()]]: stores multiple data items in cache. Each item is identified by a key. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::madd()|madd()]]: stores multiple data items in cache. Each item is identified by a key. |
|
|
|
|
|
|
|
If a key already exists in the cache, the data item will be skipped. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::exists()|exists()]]: returns a value indicating whether the specified key is found in the cache. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::delete()|delete()]]: removes a data item identified by a key from the cache. |
|
|
|
|
|
|
|
* [[yii\caching\Cache::flush()|flush()]]: removes all data items from the cache. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some cache storage, such as MemCache, APC, support retrieving multiple cached values in a batch mode, |
|
|
|
|
|
|
|
which may reduce the overhead involved in retrieving cached data. The APIs [[yii\caching\Cache::mget()|mget()]] |
|
|
|
|
|
|
|
and [[yii\caching\Cache::madd()|madd()]] are provided to exploit this feature. In case the underlying cache storage |
|
|
|
|
|
|
|
does not support this feature, it will be simulated. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Because [[yii\caching\Cache]] implements `ArrayAccess`, a cache component can be used liked an array. The followings |
|
|
|
|
|
|
|
are some examples: |
|
|
|
|
|
|
|
|
|
|
|
```php |
|
|
|
```php |
|
|
|
$connection->beginCache(60); // cache all query results for 60 seconds. |
|
|
|
$cache['var1'] = $value1; // equivalent to: $cache->set('var1', $value1); |
|
|
|
// your db query code here... |
|
|
|
$value2 = $cache['var2']; // equivalent to: $value2 = $cache->get('var2'); |
|
|
|
$connection->endCache(); |
|
|
|
|
|
|
|
``` |
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Data Caching |
|
|
|
### Cache Keys <a name="cache-keys"></a> |
|
|
|
============ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Data caching is about storing some PHP variable in cache and retrieving it |
|
|
|
Each data item stored in cache is uniquely identified by a key. When you store a data item in cache, |
|
|
|
later from cache. For this purpose, the cache component base class [CCache] |
|
|
|
you have to specify a key for it. Later when you retrieve the data item from cache, you should provide |
|
|
|
provides two methods that are used most of the time: [set()|CCache::set] |
|
|
|
the corresponding key. |
|
|
|
and [get()|CCache::get]. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To store a variable `$value` in cache, we choose a unique ID and call |
|
|
|
|
|
|
|
[set()|CCache::set] to store it: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
[php] |
|
|
|
|
|
|
|
Yii::app()->cache->set($id, $value); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The cached data will remain in the cache forever unless it is removed |
|
|
|
|
|
|
|
because of some caching policy (e.g. caching space is full and the oldest |
|
|
|
|
|
|
|
data are removed). To change this behavior, we can also supply an |
|
|
|
|
|
|
|
expiration parameter when calling [set()|CCache::set] so that the data will |
|
|
|
|
|
|
|
be removed from the cache after, at most, that period of time: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
[php] |
|
|
|
|
|
|
|
// keep the value in cache for at most 30 seconds |
|
|
|
|
|
|
|
Yii::app()->cache->set($id, $value, 30); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Later when we need to access this variable (in either the same or a |
|
|
|
|
|
|
|
different Web request), we call [get()|CCache::get] with the ID to retrieve |
|
|
|
|
|
|
|
it from cache. If the returned value is false, it means the value is not |
|
|
|
|
|
|
|
available in cache and we have to regenerate it. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
[php] |
|
|
|
|
|
|
|
$value=Yii::app()->cache->get($id); |
|
|
|
|
|
|
|
if($value===false) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// regenerate $value because it is not found in cache |
|
|
|
|
|
|
|
// and save it in cache for later use: |
|
|
|
|
|
|
|
// Yii::app()->cache->set($id,$value); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When choosing the ID for a variable to be cached, make sure the ID is |
|
|
|
|
|
|
|
unique among all other variables that may be cached in the application. It |
|
|
|
|
|
|
|
is NOT required that the ID is unique across applications because the cache |
|
|
|
|
|
|
|
component is intelligent enough to differentiate IDs for different |
|
|
|
|
|
|
|
applications. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some cache storages, such as MemCache, APC, support retrieving |
|
|
|
|
|
|
|
multiple cached values in a batch mode, which may reduce the overhead involved |
|
|
|
|
|
|
|
in retrieving cached data. A method named |
|
|
|
|
|
|
|
[mget()|CCache::mget] is provided to achieve this feature. In case the underlying |
|
|
|
|
|
|
|
cache storage does not support this feature, [mget()|CCache::mget] will still |
|
|
|
|
|
|
|
simulate it. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
To remove a cached value from cache, call [delete()|CCache::delete]; and |
|
|
|
|
|
|
|
to remove everything from cache, call [flush()|CCache::flush]. Be very |
|
|
|
|
|
|
|
careful when calling [flush()|CCache::flush] because it also removes cached |
|
|
|
|
|
|
|
data that are from other applications. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> Tip: Because [CCache] implements `ArrayAccess`, a cache component can be |
|
|
|
|
|
|
|
> used liked an array. The followings are some examples: |
|
|
|
|
|
|
|
> ~~~ |
|
|
|
|
|
|
|
> [php] |
|
|
|
|
|
|
|
> $cache=Yii::app()->cache; |
|
|
|
|
|
|
|
> $cache['var1']=$value1; // equivalent to: $cache->set('var1',$value1); |
|
|
|
|
|
|
|
> $value2=$cache['var2']; // equivalent to: $value2=$cache->get('var2'); |
|
|
|
|
|
|
|
> ~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Cache Dependency |
|
|
|
|
|
|
|
---------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Besides expiration setting, cached data may also be invalidated according |
|
|
|
|
|
|
|
to some dependency changes. For example, if we are caching the content of |
|
|
|
|
|
|
|
some file and the file is changed, we should invalidate the cached copy and |
|
|
|
|
|
|
|
read the latest content from the file instead of the cache. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We represent a dependency as an instance of [CCacheDependency] or its |
|
|
|
|
|
|
|
child class. We pass the dependency instance along with the data to be |
|
|
|
|
|
|
|
cached when calling [set()|CCache::set]. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
[php] |
|
|
|
|
|
|
|
// the value will expire in 30 seconds |
|
|
|
|
|
|
|
// it may also be invalidated earlier if the dependent file is changed |
|
|
|
|
|
|
|
Yii::app()->cache->set($id, $value, 30, new CFileCacheDependency('FileName')); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Now if we retrieve `$value` from cache by calling [get()|CCache::get], the |
|
|
|
|
|
|
|
dependency will be evaluated and if it is changed, we will get a false |
|
|
|
|
|
|
|
value, indicating the data needs to be regenerated. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Below is a summary of the available cache dependencies: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- [CFileCacheDependency]: the dependency is changed if the file's last |
|
|
|
|
|
|
|
modification time is changed. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- [CDirectoryCacheDependency]: the dependency is changed if any of the |
|
|
|
You may use a string or an arbitrary value as a cache key. When a key is not a string, it will be automatically |
|
|
|
files under the directory and its subdirectories is changed. |
|
|
|
serialized into a string. |
|
|
|
|
|
|
|
|
|
|
|
- [CDbCacheDependency]: the dependency is changed if the query result |
|
|
|
A common strategy of defining a cache key is to include all determining factors in terms of an array. |
|
|
|
of the specified SQL statement is changed. |
|
|
|
For example, [[yii\db\Schema]] uses the following key to cache schema information about a database table: |
|
|
|
|
|
|
|
|
|
|
|
- [CGlobalStateCacheDependency]: the dependency is changed if the value |
|
|
|
```php |
|
|
|
of the specified global state is changed. A global state is a variable that |
|
|
|
[ |
|
|
|
is persistent across multiple requests and multiple sessions in an |
|
|
|
__CLASS__, // schema class name |
|
|
|
application. It is defined via [CApplication::setGlobalState()]. |
|
|
|
$this->db->dsn, // DB connection data source name |
|
|
|
|
|
|
|
$this->db->username, // DB connection login user |
|
|
|
- [CChainedCacheDependency]: the dependency is changed if any of the |
|
|
|
$name, // table name |
|
|
|
dependencies on the chain is changed. |
|
|
|
]; |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
- [CExpressionDependency]: the dependency is changed if the result of |
|
|
|
As you can see, the key includes all necessary information needed to uniquely specify a database table. |
|
|
|
the specified PHP expression is changed. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When the same cache storage is used by different applications, you should specify a unique cache key prefix |
|
|
|
|
|
|
|
for each application to avoid conflicts of cache keys. This can be done by configuring the [[yii\caching\Cache::keyPrefix]] |
|
|
|
|
|
|
|
property. For example, in the application configuration you can write the following code: |
|
|
|
|
|
|
|
|
|
|
|
Query Caching |
|
|
|
```php |
|
|
|
------------- |
|
|
|
'components' => [ |
|
|
|
|
|
|
|
'cache' => [ |
|
|
|
|
|
|
|
'class' => 'yii\caching\ApcCache', |
|
|
|
|
|
|
|
'keyPrefix' => 'myapp', // a unique cache key prefix |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Since version 1.1.7, Yii has added support for query caching. |
|
|
|
To ensure interoperability, only alphanumeric characters should be used. |
|
|
|
Built on top of data caching, query caching stores the result of a DB query |
|
|
|
|
|
|
|
in cache and may thus save the DB query execution time if the same query is requested |
|
|
|
|
|
|
|
in future, as the result can be directly served from the cache. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
> Info: Some DBMS (e.g. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)) |
|
|
|
|
|
|
|
> also support query caching on the DB server side. Compared with the server-side |
|
|
|
|
|
|
|
> query caching, the same feature we support here offers more flexibility and |
|
|
|
|
|
|
|
> may be potentially more efficient. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Cache Expiration <a name="cache-expiration"></a> |
|
|
|
|
|
|
|
|
|
|
|
### Enabling Query Caching |
|
|
|
A data item stored in a cache will remain there forever unless it is removed because of some caching policy |
|
|
|
|
|
|
|
enforcement (e.g. caching space is full and the oldest data are removed). To change this behavior, you can provide |
|
|
|
|
|
|
|
an expiration parameter when calling [[yii\caching\Cache::set()|set()]] to store a data item. The parameter |
|
|
|
|
|
|
|
indicates for how many seconds the data item can remain valid in the cache. When you call |
|
|
|
|
|
|
|
[[yii\caching\Cache::get()|get()]] to retrieve the data item, if it has passed the expiration time, the method |
|
|
|
|
|
|
|
will return false, indicating the data item is not found in the cache. For example, |
|
|
|
|
|
|
|
|
|
|
|
To enable query caching, make sure [CDbConnection::queryCacheID] refers to the ID of a valid |
|
|
|
```php |
|
|
|
cache application component (it defaults to `cache`). |
|
|
|
// keep the data in cache for at most 45 seconds |
|
|
|
|
|
|
|
$cache->set($key, $data, 45); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sleep(50); |
|
|
|
|
|
|
|
|
|
|
|
### Using Query Caching with DAO |
|
|
|
$data = $cache->get($key); |
|
|
|
|
|
|
|
if ($data === false) { |
|
|
|
|
|
|
|
// $data is expired or is not found in the cache |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
To use query caching, we call the [CDbConnection::cache()] method when we perform DB queries. |
|
|
|
|
|
|
|
The following is an example: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
### Cache Dependencies <a name="cache-dependencies"></a> |
|
|
|
[php] |
|
|
|
|
|
|
|
$sql = 'SELECT * FROM tbl_post LIMIT 20'; |
|
|
|
|
|
|
|
$dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); |
|
|
|
|
|
|
|
$rows = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll(); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When running the above statements, Yii will first check if the cache contains a valid |
|
|
|
Besides expiration setting, cached data item may also be invalidated by changes of the so-called *cache dependencies*. |
|
|
|
result for the SQL statement to be executed. This is done by checking the following three conditions: |
|
|
|
For example, [[yii\caching\FileDependency]] represents the dependency of a file's modification time. |
|
|
|
|
|
|
|
When this dependency changes, it means the corresponding file is modified. As a result, any outdated |
|
|
|
|
|
|
|
file content found in the cache should be invalidated and the [[yii\caching\Cache::get()|get()]] call |
|
|
|
|
|
|
|
should return false. |
|
|
|
|
|
|
|
|
|
|
|
- if the cache contains an entry indexed by the SQL statement. |
|
|
|
Cache dependencies are represented as objects of [[yii\caching\Dependency]] descendant classes. When you call |
|
|
|
- if the entry is not expired (less than 1000 seconds since it was first saved in the cache). |
|
|
|
[[yii\caching\Cache::set()|set()]] to store a data item in the cache, you can pass along an associated cache |
|
|
|
- if the dependency has not changed (the maximum `update_time` value is the same as when |
|
|
|
dependency object. For example, |
|
|
|
the query result was saved in the cache). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If all of the above conditions are satisfied, the cached result will be returned directly from the cache. |
|
|
|
```php |
|
|
|
Otherwise, the SQL statement will be sent to the DB server for execution, and the corresponding |
|
|
|
// Create a dependency on the modification time of file example.txt. |
|
|
|
result will be saved in the cache and returned. |
|
|
|
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The data will expire in 30 seconds. |
|
|
|
|
|
|
|
// It may also be invalidated earlier if example.txt is modified. |
|
|
|
|
|
|
|
$cache->set($key, $data, 30, $dependency); |
|
|
|
|
|
|
|
|
|
|
|
### Using Query Caching with ActiveRecord |
|
|
|
// The cache will check if the data has expired. |
|
|
|
|
|
|
|
// It will also check if the associated dependency was changed. |
|
|
|
|
|
|
|
// It will return false if any of these conditions is met. |
|
|
|
|
|
|
|
$data = $cache->get($key); |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
Query caching can also be used with [Active Record](/doc/guide/database.ar). |
|
|
|
Below is a summary of the available cache dependencies: |
|
|
|
To do so, we call a similar [CActiveRecord::cache()] method like the following: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
- [[yii\caching\ChainedDependency]]: the dependency is changed if any of the dependencies on the chain is changed. |
|
|
|
[php] |
|
|
|
- [[yii\caching\DbDependency]]: the dependency is changed if the query result of the specified SQL statement is changed. |
|
|
|
$dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); |
|
|
|
- [[yii\caching\ExpressionDependency]]: the dependency is changed if the result of the specified PHP expression is changed. |
|
|
|
$posts = Post::model()->cache(1000, $dependency)->findAll(); |
|
|
|
- [[yii\caching\FileDependency]]: the dependency is changed if the file's last modification time is changed. |
|
|
|
// relational AR query |
|
|
|
- [[yii\caching\GroupDependency]]: marks a cached data item with a group name. You may invalidate the cached data items |
|
|
|
$posts = Post::model()->cache(1000, $dependency)->with('author')->findAll(); |
|
|
|
with the same group name all at once by calling [[yii\caching\GroupDependency::invalidate()]]. |
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The `cache()` method here is essentially a shortcut to [CDbConnection::cache()]. |
|
|
|
|
|
|
|
Internally, when executing the SQL statement generated by ActiveRecord, Yii will |
|
|
|
|
|
|
|
attempt to use query caching as we described in the last subsection. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Query Caching <a name="query-caching"></a> |
|
|
|
|
|
|
|
|
|
|
|
### Caching Multiple Queries |
|
|
|
Query caching is a special caching feature built on top of data caching. It is provided to cache the result |
|
|
|
|
|
|
|
of database queries. |
|
|
|
|
|
|
|
|
|
|
|
By default, each time we call the `cache()` method (of either [CDbConnection] or [CActiveRecord]), |
|
|
|
Query caching requires a [[yii\db\Connection|DB connection]] and a valid `cache` application component. |
|
|
|
it will mark the next SQL query to be cached. Any other SQL queries will NOT be cached |
|
|
|
The basic usage of query caching is as follows, assuming `$db` is a [[yii\db\Connection]] instance: |
|
|
|
unless we call `cache()` again. For example, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
```php |
|
|
|
[php] |
|
|
|
$duration = 60; // cache query results for 60 seconds. |
|
|
|
$sql = 'SELECT * FROM tbl_post LIMIT 20'; |
|
|
|
$dependency = ...; // optional dependency |
|
|
|
$dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$rows = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll(); |
|
|
|
$db->beginCache($duration, $dependency); |
|
|
|
// query caching will NOT be used |
|
|
|
|
|
|
|
$rows = Yii::app()->db->createCommand($sql)->queryAll(); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
By supplying an extra `$queryCount` parameter to the `cache()` method, we can enforce |
|
|
|
// ...performs DB queries here... |
|
|
|
multiple queries to use query caching. In the following example, when we call `cache()`, |
|
|
|
|
|
|
|
we specify that query caching should be used for the next 2 queries: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
$db->endCache(); |
|
|
|
[php] |
|
|
|
``` |
|
|
|
// ... |
|
|
|
|
|
|
|
$rows = Yii::app()->db->cache(1000, $dependency, 2)->createCommand($sql)->queryAll(); |
|
|
|
|
|
|
|
// query caching WILL be used |
|
|
|
|
|
|
|
$rows = Yii::app()->db->createCommand($sql)->queryAll(); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
As we know, when performing a relational AR query, it is possible several SQL queries will |
|
|
|
As you can see, any SQL queries in between the `beginCache()` and `endCache()` calls will be cached. |
|
|
|
be executed (by checking the [log messages](/doc/guide/topics.logging)). |
|
|
|
If the result of the same query is found valid in the cache, the query will be skipped and the result |
|
|
|
For example, if the relationship between `Post` and `Comment` is `HAS_MANY`, |
|
|
|
will be served from the cache instead. |
|
|
|
then the following code will actually execute two DB queries: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- it first selects the posts limited by 20; |
|
|
|
Query caching can be used for [DAO](db-dao.md) as well as [ActiveRecord](db-active-record.md). |
|
|
|
- it then selects the comments for the previously selected posts. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
> Info: Some DBMS (e.g. [MySQL](http://dev.mysql.com/doc/refman/5.1/en/query-cache.html)) |
|
|
|
[php] |
|
|
|
also support query caching on the DB server side. You may choose to use either query caching mechanism. |
|
|
|
$posts = Post::model()->with('comments')->findAll(array( |
|
|
|
The query caching described above has the advantage that you may specify flexible cache dependencies |
|
|
|
'limit'=>20, |
|
|
|
and are potentially more efficient. |
|
|
|
)); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If we use query caching as follows, only the first DB query will be cached: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
### Configurations <a name="query-caching-configs"></a> |
|
|
|
[php] |
|
|
|
|
|
|
|
$posts = Post::model()->cache(1000, $dependency)->with('comments')->findAll(array( |
|
|
|
|
|
|
|
'limit'=>20, |
|
|
|
|
|
|
|
)); |
|
|
|
|
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In order to cache both DB queries, we need supply the extra parameter indicating how |
|
|
|
Query caching has two two configurable options through [[yii\db\Connection]]: |
|
|
|
many DB queries we want to cache next: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~~~ |
|
|
|
* [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: this represents the number of seconds |
|
|
|
[php] |
|
|
|
that a query result can remain valid in the cache. The duration will be overwritten if you call |
|
|
|
$posts = Post::model()->cache(1000, $dependency, 2)->with('comments')->findAll(array( |
|
|
|
[[yii\db\Connection::beginCache()]] with an explicit duration parameter. |
|
|
|
'limit'=>20, |
|
|
|
* [[yii\db\Connection::queryCache|queryCache]]: this represents the ID of the cache application component. |
|
|
|
)); |
|
|
|
It defaults to `'cache'`. Query caching is enabled only when there is a valid cache application component. |
|
|
|
~~~ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Limitations |
|
|
|
### Limitations <a name="query-caching-limitations"></a> |
|
|
|
|
|
|
|
|
|
|
|
Query caching does not work with query results that contain resource handles. For example, |
|
|
|
Query caching does not work with query results that contain resource handles. For example, |
|
|
|
when using the `BLOB` column type in some DBMS, the query result will return a resource |
|
|
|
when using the `BLOB` column type in some DBMS, the query result will return a resource |
|
|
@ -358,7 +288,3 @@ Some caching storage has size limitation. For example, memcache limits the maxim |
|
|
|
of each entry to be 1MB. Therefore, if the size of a query result exceeds this limit, |
|
|
|
of each entry to be 1MB. Therefore, if the size of a query result exceeds this limit, |
|
|
|
the caching will fail. |
|
|
|
the caching will fail. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Note, by definition, cache is a volatile storage medium. It does not ensure the existence of the cached |
|
|
|
|
|
|
|
data even if it does not expire. Therefore, do not use cache as a persistent storage (e.g. do not use cache |
|
|
|
|
|
|
|
to store session data or other valuable information). |
|
|
|
|
|
|
|