フォロワー 5

データキャッシング

データキャッシングとは、いくつかのPHP変数をキャッシュに保存し、後でキャッシュから取得することです。 また、クエリキャッシングページキャッシングなど、より高度なキャッシング機能の基盤にもなります。

次のコードは、データキャッシングの典型的な使用パターンです。ここで、`$cache`はキャッシュコンポーネントを参照しています。

// try retrieving $data from cache
$data = $cache->get($key);

if ($data === false) {
    // $data is not found in cache, calculate it from scratch
    $data = $this->calculateSomething();

    // store $data in cache so that it can be retrieved next time
    $cache->set($key, $data);
}

// $data is available here

バージョン2.0.11以降、キャッシュコンポーネントは、データの取得、計算、および格納のコードを簡素化するgetOrSet()メソッドを提供しています。次のコードは、前の例とまったく同じ動作をします。

$data = $cache->getOrSet($key, function () {
    return $this->calculateSomething();
});

キャッシュに `$key` に関連付けられたデータがある場合、キャッシュされた値が返されます。 それ以外の場合、渡された無名関数が実行され、キャッシュされて返される値が計算されます。

無名関数が外部スコープからのデータを必要とする場合は、`use`ステートメントを使用して渡すことができます。 例えば

$user_id = 42;
$data = $cache->getOrSet($key, function () use ($user_id) {
    return $this->calculateSomething($user_id);
});

**注意:** getOrSet()メソッドは、期間と依存関係もサポートしています。 詳細については、キャッシュの有効期限キャッシュの依存関係を参照してください。

キャッシュコンポーネント

データキャッシングは、メモリ、ファイル、データベースなど、さまざまなキャッシュストレージを表す、いわゆる *キャッシュコンポーネント* に依存しています。

キャッシュコンポーネントは、通常、アプリケーションコンポーネントとして登録されるため、グローバルに設定およびアクセスできます。 次のコードは、2つのキャッシュサーバーでmemcachedを使用するように`cache`アプリケーションコンポーネントを設定する方法を示しています。

'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'server1',
                'port' => 11211,
                'weight' => 100,
            ],
            [
                'host' => 'server2',
                'port' => 11211,
                'weight' => 50,
            ],
        ],
    ],
],

上記の設定後、`Yii::$app->cache`という式を使用して、上記のキャッシュコンポーネントにアクセスできます。

キャッシュコンポーネントが指定されていない場合、Yiiはデフォルトでyii\caching\FileCacheを使用します。

すべてのキャッシュコンポーネントは同じAPIセットをサポートしているため、キャッシュを使用するコードを変更することなく、アプリケーション設定で再設定することで、基盤となるキャッシュコンポーネントを別のコンポーネントと交換できます。 たとえば、上記の設定を変更して、APCキャッシュを使用するようにできます。

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
    ],
],

ヒント: 複数のキャッシュアプリケーションコンポーネントを登録できます。 cache という名前のコンポーネントは、多くのキャッシュ依存クラス(例:yii\web\UrlManager)でデフォルトで使用されます。

サポートされているキャッシュストレージ

Yiiは幅広いキャッシュストレージをサポートしています。以下は概要です。

  • yii\caching\ApcCache: PHPのAPC拡張機能を使用します。このオプションは、集中型の厚いアプリケーション(例:1台のサーバー、専用のロードバランサーなしなど)のキャッシュを扱う場合、最速の選択肢と考えることができます。
  • yii\caching\DbCache: データベーステーブルを使用してキャッシュデータを保存します。このキャッシュを使用するには、yii\caching\DbCache::$cacheTableで指定されているテーブルを作成する必要があります。
  • yii\caching\ArrayCache: 値を配列に格納することにより、現在のリクエストのキャッシュのみを提供します。ArrayCacheのパフォーマンスを向上させるには、yii\caching\ArrayCache::$serializerfalseに設定して、格納されたデータのシリアル化を無効にすることができます。
  • yii\caching\DummyCache: 実際のキャッシュを行わないキャッシュプレースホルダーとして機能します。このコンポーネントの目的は、キャッシュの可用性をチェックする必要があるコードを簡素化することです。たとえば、開発中やサーバーが実際のキャッシュをサポートしていない場合、このキャッシュを使用するようにキャッシュコンポーネントを設定できます。実際のキャッシュサポートが有効になっている場合は、対応するキャッシュコンポーネントを使用するように切り替えることができます。どちらの場合でも、Yii::$app->cache->get($key)という同じコードを使用して、Yii::$app->cachenullになる可能性を心配することなく、キャッシュからデータを取得しようとすることができます。
  • yii\caching\FileCache: 標準ファイルを使用してキャッシュデータを保存します。これは、ページコンテンツなど、大きなデータチャンクをキャッシュするのに特に適しています。
  • yii\caching\MemCache: PHPのmemcachememcached拡張機能を使用します。このオプションは、分散アプリケーション(例:複数のサーバー、ロードバランサーなど)でキャッシュを扱う場合、最速の選択肢と考えることができます。
  • yii\redis\Cache: Redisキーバリューストア(redisバージョン2.6.12以上が必要)に基づいてキャッシュコンポーネントを実装します。
  • yii\caching\WinCache: PHPのWinCacheこちらも参照)拡張機能を使用します。
  • yii\caching\XCache (非推奨): PHPのXCache拡張機能を使用します。
  • yii\caching\ZendDataCache (非推奨): Zend Data Cacheを基盤となるキャッシュメディアとして使用します。

ヒント: 同じアプリケーションで異なるキャッシュストレージを使用できます。一般的な戦略は、メモリベースのキャッシュストレージを使用して、小さくても常に使用されるデータ(例:統計データ)を保存し、ファイルベースまたはデータベースベースのキャッシュストレージを使用して、大きく、使用頻度の低いデータ(例:ページコンテンツ)を保存することです。

キャッシュAPI

すべてのキャッシュコンポーネントは同じ基底クラスyii\caching\Cacheを持つため、以下のAPIをサポートしています。

  • get(): 指定されたキーでキャッシュからデータ項目を取得します。データ項目がキャッシュに見つからないか、期限切れ/無効になっている場合は、false値が返されます。
  • set(): キャッシュにキーで識別されるデータ項目を保存します。
  • add(): キーがキャッシュに見つからない場合、キャッシュにキーで識別されるデータ項目を保存します。
  • getOrSet(): 指定されたキーでキャッシュからデータ項目を取得するか、渡されたコールバックを実行し、コールバックの戻り値をキーでキャッシュに保存して、そのデータを返します。
  • multiGet(): 指定されたキーでキャッシュから複数のデータ項目を取得します。
  • multiSet(): キャッシュに複数のデータ項目を保存します。各項目はキーによって識別されます。
  • multiAdd(): キャッシュに複数のデータ項目を保存します。各項目はキーによって識別されます。キーが既にキャッシュに存在する場合、データ項目はスキップされます。
  • exists(): 指定されたキーがキャッシュに見つかるかどうかを示す値を返します。
  • delete(): キャッシュからキーで識別されるデータ項目を削除します。
  • flush(): キャッシュからすべてのデータ項目を削除します。

**注意:** get()メソッドは `false` 戻り値を使用してデータ項目がキャッシュに見つからないことを示すため、`false` ブール値を直接キャッシュしないでください。 この問題を回避するには、`false` を配列に入れて、代わりにこの配列をキャッシュすることができます。

MemCache、APCなど、一部のキャッシュストレージでは、バッチモードで複数のキャッシュ値を取得することができ、キャッシュデータの取得に伴うオーバーヘッドを削減できます。API multiGet() and multiAdd() は、この機能を活用するために提供されています。基盤となるキャッシュストレージがこの機能をサポートしていない場合は、シミュレートされます。

yii\caching\CacheArrayAccessを実装しているため、キャッシュコンポーネントは配列のように使用できます。以下はいくつかの例です。

$cache['var1'] = $value1;  // equivalent to: $cache->set('var1', $value1);
$value2 = $cache['var2'];  // equivalent to: $value2 = $cache->get('var2');

キャッシュキー

キャッシュに保存される各データ項目は、キーによって一意に識別されます。キャッシュにデータ項目を保存する場合、そのキーを指定する必要があります。後でキャッシュからデータ項目を取得するときは、対応するキーを指定する必要があります.

文字列または任意の値をキャッシュキーとして使用できます。キーが文字列でない場合は、自動的に文字列にシリアル化されます。

キャッシュキーを定義する一般的な戦略は、すべての決定要因を配列で含めることです。たとえば、yii\db\Schemaは、データベーステーブルに関するスキーマ情報をキャッシュするために、次のキーを使用します。

[
    __CLASS__,              // schema class name
    $this->db->dsn,         // DB connection data source name
    $this->db->username,    // DB connection login user
    $name,                  // table name
];

ご覧のとおり、キーにはデータベーステーブルを一意に指定するために必要なすべての情報が含まれています.

注意: multiSet() または multiAdd() を介してキャッシュに保存される値は、文字列または整数のキーのみを持つことができます。 より複雑なキーを設定する必要がある場合は、set() または add() を介して値を個別に保存します。

異なるアプリケーションで同じキャッシュストレージを使用する場合、キャッシュキーの競合を避けるために、各アプリケーションに一意のキャッシュキープレフィックスを指定する必要があります。これは、yii\caching\Cache::$keyPrefixプロパティを設定することで実行できます。たとえば、アプリケーション設定で次のコードを記述できます。

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
        'keyPrefix' => 'myapp',       // a unique cache key prefix
    ],
],

相互運用性を確保するために、英数字のみを使用する必要があります。

キャッシュの有効期限

キャッシュに保存されたデータ項目は、何らかのキャッシュポリシーの適用(例:キャッシュスペースがいっぱいになり、最も古いデータが削除される)によって削除されない限り、永久にそこに残ります。この動作を変更するには、set()を呼び出してデータ項目を保存するときに、有効期限パラメータを指定できます。パラメータは、データ項目がキャッシュ内で有効な秒数を示します。get()を呼び出してデータ項目を取得するときに、有効期限が過ぎている場合、メソッドはfalseを返し、データ項目がキャッシュに見つからないことを示します。たとえば、

// keep the data in cache for at most 45 seconds
$cache->set($key, $data, 45);

sleep(50);

$data = $cache->get($key);
if ($data === false) {
    // $data is expired or is not found in the cache
}

2.0.11以降、デフォルトの無制限の期間よりもカスタムのキャッシュ期間を希望する場合は、キャッシュコンポーネント設定でdefaultDuration値を設定できます。これにより、set()に毎回カスタムの`duration`パラメータを渡す必要がなくなります。

キャッシュの依存関係

有効期限の設定に加えて、キャッシュされたデータ項目は、いわゆる*キャッシュの依存関係*の変更によっても無効になる場合があります。たとえば、yii\caching\FileDependencyは、ファイルの変更時刻への依存関係を表します。この依存関係が変更されると、対応するファイルが変更されたことを意味します。その結果、キャッシュで見つかった古いファイルコンテンツは無効になり、get()呼び出しはfalseを返す必要があります。

キャッシュの依存関係は、yii\caching\Dependencyの子孫クラスのオブジェクトとして表されます。set()を呼び出してキャッシュにデータ項目を保存するときに、関連付けられたキャッシュ依存関係オブジェクトを渡すことができます。たとえば、

// Create a dependency on the modification time of file example.txt.
$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);

// 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 are met.
$data = $cache->get($key);

以下は、使用可能なキャッシュの依存関係の概要です.

注意: 依存関係と共に exists() メソッドを使用しないでください。 キャッシュされたデータに関連付けられた依存関係があるかどうか、変更されたかどうかはチェックしません。そのため、get() の呼び出しは `false` を返す可能性がありますが、exists() は `true` を返します。

クエリキャッシュ

クエリキャッシュは、データキャッシュの上に構築された特別なキャッシュ機能です。データベースクエリの結果をキャッシュするために提供されます。

クエリキャッシュには、DB接続と有効なcache アプリケーションコンポーネントが必要です。クエリキャッシュの基本的な使い方は次のとおりです。$dbyii\db\Connectionインスタンスであると想定しています。

$result = $db->cache(function ($db) {

    // the result of the SQL query will be served from the cache
    // if query caching is enabled and the query result is found in the cache
    return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();

});

クエリキャッシュは、DAOActiveRecordに使用できます。

$result = Customer::getDb()->cache(function ($db) {
    return Customer::find()->where(['id' => 1])->one();
});

情報: 一部のDBMS(例:MySQL)は、DBサーバー側でのクエリキャッシュもサポートしています。いずれかのクエリキャッシュメカニズムを選択できます。上記のクエリキャッシュには、柔軟なキャッシュの依存関係を指定できることと、潜在的に効率的であるという利点があります。

2.0.14以降、次のショートカットを使用できます。

(new Query())->cache(7200)->all();
// and
User::find()->cache(7200)->all();

設定

クエリキャッシュには、yii\db\Connectionを介してグローバルに設定可能な3つのオプションがあります。

  • enableQueryCache: クエリキャッシュをオンまたはオフにするかどうか。デフォルトはtrueです。クエリキャッシュを効果的にオンにするには、queryCacheで指定されているように、有効なキャッシュも必要です。
  • queryCacheDuration: これは、クエリ結果がキャッシュ内で有効な秒数を表します。0を使用して、クエリ結果がキャッシュに永久に残ることを示すことができます。このプロパティは、期間を指定せずにyii\db\Connection::cache()が呼び出されたときに使用されるデフォルト値です。
  • queryCache: これは、キャッシュアプリケーションコンポーネントのIDを表します。デフォルトは'cache'です。有効なキャッシュアプリケーションコンポーネントがある場合にのみ、クエリキャッシュが有効になります。

使用方法

複数のSQLクエリでクエリキャッシュを活用する必要がある場合は、yii\db\Connection::cache() を使用できます。使い方は以下のとおりです。

$duration = 60;     // cache query results for 60 seconds.
$dependency = ...;  // optional dependency

$result = $db->cache(function ($db) {

    // ... perform SQL queries here ...

    return $result;

}, $duration, $dependency);

無名関数内のSQLクエリは、指定された期間、指定された依存関係でキャッシュされます。クエリの結果がキャッシュ内で有効であることが判明した場合、クエリはスキップされ、代わりにキャッシュから結果が提供されます。 $duration パラメータを指定しない場合、queryCacheDuration の値が代わりに使用されます。

cache() 内で、特定のクエリに対してクエリキャッシュを無効にしたい場合があります。この場合は、yii\db\Connection::noCache() を使用できます。

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    $db->noCache(function ($db) {

        // SQL queries that do not use query caching

    });

    // ...

    return $result;
});

単一のクエリに対してのみクエリキャッシュを使用する場合は、コマンドを作成する際に yii\db\Command::cache() を呼び出すことができます。例えば、

// use query caching and set query cache duration to be 60 seconds
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();

単一のコマンドに対してクエリキャッシュを無効にするには、yii\db\Command::noCache() を使用することもできます。例えば、

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    // do not use query caching for this command
    $customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();

    // ...

    return $result;
});

制限事項

クエリキャッシュは、リソースハンドラを含むクエリ結果では機能しません。たとえば、一部のDBMSで BLOB カラムタイプを使用する場合、クエリ結果はカラムデータのリソースハンドラを返します。

一部のキャッシュストレージにはサイズ制限があります。たとえば、memcacheは各エントリの最大サイズを1MBに制限しています。そのため、クエリ結果のサイズがこの制限を超えると、キャッシュは失敗します。

キャッシュのフラッシュ

保存されているすべてのキャッシュデータを無効にする必要がある場合は、yii\caching\Cache::flush() を呼び出すことができます。

コンソールから yii cache/flush を呼び出すことによっても、キャッシュをフラッシュできます。

  • yii cache: アプリケーションで使用可能なキャッシュを一覧表示します
  • yii cache/flush cache1 cache2: キャッシュコンポーネント cache1cache2 をフラッシュします(スペースで区切って複数のコンポーネント名を渡すことができます)
  • yii cache/flush-all: アプリケーションのすべてのキャッシュコンポーネントをフラッシュします
  • yii cache/flush-schema db: 指定された接続コンポーネントのDBスキーマキャッシュをクリアします

情報: コンソールアプリケーションは、デフォルトで別の設定ファイルを使用します。適切な効果を得るために、Webアプリケーションとコンソールアプリケーションの設定に同じキャッシュコンポーネントがあることを確認してください。

タイプミスを見つけましたか、またはこのページの改善が必要だと思いますか?
githubで編集してください !