magento-indexing-caching について
Magento のインデックスとキャッシュを管理する開発者・運用担当者向けのスキルです。インデクサー、Varnish のフルページキャッシュ、Redis、キャッシュ無効化の調査を扱います。
主な機能
- 01インデクサーの状態とモードの確認・管理
- 02部分的または全件の再インデックス
- 03Varnish フルページキャッシュの設定
- 04Redis キャッシュとセッションストレージの設定
- 05キャッシュタグによる対象ページの無効化
活用シーン
- 01価格の誤りや商品非表示の調査
- 02本番環境での Varnish と Redis の設定
- 03大規模カタログのインデックス実行管理
- 04カタログや CMS 更新後のキャッシュ無効化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill magento-indexing-cachingインストール後、Claude Code で/magento-indexing-cachingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonevals/custom-module-cache-tag-invalidation/criteria.jsontask.mdevals/indexer-production-configuration/criteria.jsontask.mdevals/redis-cache-and-session-configuration/criteria.jsontask.md詳細
Magentoのインデックス作成とキャッシュ
概要
Magentoのパフォーマンスアーキテクチャは、2つの異なるレイヤーに依存しています。1つは、非正規化データ(商品価格、検索インデックス、カテゴリパス)をフラットテーブルに事前計算するインデクサー、もう1つは、レンダリング済みのHTMLページ全体を保存するフルページキャッシュ(FPC)です。本番環境では、Magento組み込みのファイルベースキャッシュに代わり、VarnishをFPCバックエンドとして使用することが推奨されています。アプリケーションキャッシュ、セッションストレージ、デフォルトキャッシュ(ブロックHTML、設定、レイアウト)のバックエンドには、Redisが推奨されています。インデックスの設定ミスや古いインデックスは、価格の誤りや商品の表示問題を引き起こす最も一般的な原因のひとつです。
このスキルを使用する場面
- カタログの更新後に、商品価格が正しくない、または商品が表示されない場合
- Magento本番サーバーに初めてVarnishを導入する場合
- オンザフライの価格計算が原因でカテゴリページの読み込みが遅い場合に診断するとき
- Magentoのセッションおよびブロックキャッシュストレージ用にRedisを設定するとき
- Magentoのキャッシュタグを使用して、カタログまたはCMSの更新後にキャッシュを無効化する設定を行うとき
- 大規模なカタログ(商品数が50,000を超える)で、全件再インデックスによるロックを防ぐためにインデクサーのスケジュールを管理するとき
基本手順
-
Magentoのインデクサーとモードを理解する
# List all indexers and their status bin/magento indexer:info bin/magento indexer:status # Example output: # catalog_category_product Category Products valid Update on Save # catalog_product_category Product Categories valid Update on Save # catalog_product_price Product Price invalid Update by Schedule # catalogsearch_fulltext Catalog Search valid Update by Schedule # catalogrule_product Catalog Rule Product invalid Update on Saveチェックアウトのブロックを防ぐため、本番環境のすべてのインデクサーを
Update by Scheduleモードに設定します。bin/magento indexer:set-mode schedule catalog_category_product bin/magento indexer:set-mode schedule catalog_product_price bin/magento indexer:set-mode schedule catalogsearch_fulltext bin/magento indexer:set-mode schedule catalog_product_flat bin/magento indexer:set-mode schedule catalog_category_flat # Verify modes bin/magento indexer:show-mode -
インデクサーと部分的な再インデックスを管理する
# Reindex a single indexer (less disruptive than full reindex) bin/magento indexer:reindex catalog_product_price # Reindex all (avoid on production during business hours) bin/magento indexer:reindex # Reset indexer to "invalid" to force next scheduled run bin/magento indexer:reset catalog_product_price # Check mview (materialized view) changelog tables — lists pending rows to process bin/magento indexer:show-changelog非常に大規模なカタログでは、並列インデックス作成を使用します。
# app/etc/env.php — enable parallel processing # In Admin → System → Index Management → Indexers → Configure # Or via config: bin/magento config:set dev/grid/async_indexing 1<?php // app/etc/env.php return [ // ... 'indexer' => [ 'batch_size' => [ 'catalog_product_price' => ['simple' => 200, 'configurable' => 50], 'catalogsearch_fulltext' => ['simple' => 500], ], ], ]; -
フルページキャッシュとしてVarnishを設定する
# In Admin → System → Configuration → Advanced → System → Full Page Cache # Set Caching Application: Varnish Cache # Export Varnish configuration: bin/magento varnish:vcl:generate --export-version=6 --output-file=/etc/varnish/magento.vcl生成されたVCLで理解しておくべき主なセクションは次のとおりです。
# /etc/varnish/magento.vcl (excerpts from generated config) sub vcl_recv { # Do not cache if private cookie is set (logged-in customer) if (req.http.cookie ~ "X-Magento-Vary=") { # Magento sets this cookie to vary cache by context (customer group, currency) # The cookie value changes only when the context changes — not per session } # Strip _ga, fbclid, utm_* params from cache key to prevent cache fragmentation set req.url = regsuball(req.url, "(\?|&)(utm_[^&]+|fbclid|gclid|mc_[^&]+)(&|$)", "\1"); } sub vcl_hash { # Include Magento's context cookie in the cache hash if (req.http.cookie ~ "X-Magento-Vary=") { hash_data(regsub(req.http.cookie, ".*X-Magento-Vary=([^;]+).*", "\1")); } } sub vcl_backend_response { # Respect Magento's Cache-Control headers if (beresp.http.Cache-Control ~ "no-store") { set beresp.uncacheable = true; set beresp.ttl = 120s; } # Strip Set-Cookie on cacheable responses if (beresp.ttl > 0s) { unset beresp.http.set-cookie; } } -
アプリケーションキャッシュとセッション用にRedisを設定する
<?php // app/etc/env.php — Redis cache and session configuration return [ 'cache' => [ 'frontend' => [ 'default' => [ 'id_prefix' => 'b0c_', 'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis', 'backend_options' => [ 'server' => '127.0.0.1', 'database' => '0', 'port' => '6379', 'password' => '', 'compress_data' => '1', 'compression_lib' => 'gzip', 'persistent' => 'mgto_cache', ], ], 'page_cache' => [ 'id_prefix' => 'b0c_', 'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis', 'backend_options' => [ 'server' => '127.0.0.1', 'database' => '1', // Separate DB for FPC 'port' => '6379', 'compress_data' => '0', // FPC data is already compressed HTML ], ], ], ], 'session' => [ 'save' => 'redis', 'redis' => [ 'host' => '127.0.0.1', 'port' => '6379', 'password' => '', 'timeout' => '2.5', 'persistent_identifier' => 'mgto_sessions', 'database' => '2', // Separate DB for sessions 'compression_threshold' => '2048', 'compression_library' => 'gzip', 'log_level' => '1', 'max_concurrency' => '6', 'break_after_frontend' => '5', 'max_lifetime' => '7200', 'disable_locking' => '1', // Improves performance but reduces session safety ], ], ]; -
カスタムモジュールにキャッシュタグによる無効化を実装する
Magentoは、データの変更時にキャッシュ済みページを選択的に無効化するためにキャッシュタグを使用します。カスタムモジュールでは、キャッシュに適切なタグを付け、正しくクリアする必要があります。
<?php // Declare cache tags in your block/model namespace MyVendor\CustomModule\Block; use Magento\Framework\View\Element\Template; use Magento\Framework\DataObject\IdentityInterface; class CustomProductWidget extends Template implements IdentityInterface { private array $productIds = []; public function getIdentities(): array { // Return cache tags so Magento invalidates this block when any of these products change $tags = [\Magento\Catalog\Model\Product::CACHE_TAG]; foreach ($this->productIds as $id) { $tags[] = \Magento\Catalog\Model\Product::CACHE_TAG . '_' . $id; } return $tags; } }<?php // In your observer or command — flush only relevant pages after product update namespace MyVendor\CustomModule\Observer; use Magento\Framework\Event\ObserverInterface; use Magento\Framework\App\Cache\TypeListInterface; use Magento\PageCache\Model\Cache\Type as PageCacheType; class ProductSaveObserver implements ObserverInterface { public function __construct( private readonly TypeListInterface $cacheTypeList, private readonly \Magento\Framework\App\Cache\Tag\Resolver $tagResolver ) {} public function execute(\Magento\Framework\Event\Observer $observer): void { $product = $observer->getEvent()->getProduct(); // Invalidate only pages tagged with this product's cache tag // Varnish will purge via PURGE request using X-Magento-Tags-Pattern header $this->cacheTypeList->invalidate(PageCacheType::TYPE_IDENTIFIER); } }
例
価格の誤りを引き起こすインデックスの遅延を診断する
# Check if mview changelog has pending rows
bin/magento indexer:show-changelog
# If catalog_product_price has > 0 pending rows, prices are stale
# Run the indexer to catch up
bin/magento indexer:reindex catalog_product_price
# Check cron_schedule table for missed cron jobs (should run indexers every minute)
bin/magento cron:run --group index &
# Or manually via:
mysql -u root -e "SELECT job_code, status, finished_at FROM magento.cron_schedule WHERE job_code LIKE '%index%' ORDER BY finished_at DESC LIMIT 20;"
デプロイ後にFPCをウォームアップする
#!/bin/bash
# scripts/warm-cache.sh — warm the FPC after deploy
set -e
MAGENTO_BASE_URL="https://www.mystore.com"
SITEMAP_URL="$MAGENTO_BASE_URL/sitemap.xml"
echo "Flushing Magento caches..."
bin/magento cache:flush
echo "Warming FPC via sitemap..."
# Download sitemap and curl each URL with a warm-cache header
curl -s "$SITEMAP_URL" | \
grep -oP '<loc>\K[^<]+' | \
head -500 | \
xargs -P 10 -I {} curl -s -o /dev/null -w "%{http_code} {}\n" \
-H "X-Warm-Cache: 1" {}
echo "Cache warming complete."
ベストプラクティス
- 本番環境では常に
Update by Scheduleモードを使用する —Update on Saveでは管理画面での保存中に同期的に再インデックスが行われるため、大規模なカタログではタイムアウトが発生します - キャッシュ、FPC、セッションでRedisのデータベースを分ける — すべてにデータベース0を使用するとキーが競合し、1種類だけをフラッシュできなくなります
- カスタムブロックに
IdentityInterfaceでタグを付ける — これにより、データ変更時にVarnishとMagentoのFPCが適切なページを無効化できます - インデクサーの変更ログテーブルのサイズを監視する —
catalog_product_price_clテーブルに数百万行ある場合、cronが実行されていないことを示します。テーブルサイズが原因で再インデックスがタイムアウトする前にcronを修正してください bin/magento cache:cleanをcache:flushより優先して使用する —cleanは無効なキャッシュエントリーのみを削除します(安全です)。flushは、同じRedisを共有する他のフレームワークのキャッシュも含め、すべてを消去します- 環境ごとに異なる
id_prefixを設定する — ステージング環境と本番環境でそれぞれ一意のプレフィックスを設定すれば、同じRedisサーバーを共有してもキャッシュ汚染を防げます curl -IとX-CacheヘッダーでVarnishをテストする —HITレスポンスはVarnishがキャッシュから応答していることを示します。MISSはすべてのリクエストでMagentoにアクセスしていることを意味します
よくある問題
| 問題 | 解決策 |
|---|---|
| インポート後に商品が表示されない、または価格が正しくない | 一括インポート後に bin/magento indexer:reindex を実行します。ResourceModel\Product::save を直接使用している場合、プログラムから商品を保存してもインデクサーが常に起動するとは限りません |
| Varnish がログイン済み顧客に古いページを配信する | Varnish の VCL ハッシュに X-Magento-Vary Cookie が含まれていることを確認します。ログイン済み顧客には異なる vary 値が割り当てられ、共有キャッシュを迂回します |
| Redis のメモリが不足する | キャッシュデータベースでは redis.conf に maxmemory-policy allkeys-lru を設定します。セッションデータベースでは、セッションが気付かないうちに失われるのを防ぐため、noeviction を使用します |
| 商品の保存後に FPC が無効化されない | Varnish の PURGE ACL で Magento サーバーの IP アドレスからのリクエストが許可されていることを確認します。curl -X PURGE http://varnish-ip/ でテストします |
| 全件再インデックスに何時間もかかり、テーブルがロックされる | env.php でインデクサーのバッチサイズを有効にし、--mode realtime を指定して部分的に再インデックスします。オフピーク時間帯に実行するようスケジュールします |
| Cron のインデクサーが実行されない | var/log/magento.cron.log でエラーを確認します。システムの crontab エントリーで、Web サーバーのユーザーとして bin/magento cron:run が毎分実行されていることを確認します |
関連スキル
- @magento-module-development
- @magento-graphql
- @magento-multi-store
- @caching-strategies
- @infrastructure-performance