WordPress ディレクトリプラグインがスケールで失敗する理由(および代わりに使用するもの)
より多くの失敗したWordPress ディレクトリを再構築してきました。その物語は常に同じです:誰かが GeoDirectory または Business Directory Plugin をインストールし、数百のリスティングをロードし、すべてが正常に機能します。6ヶ月後、30,000 のリスティングがあり、ページ読み込み時間が 8 秒以上に膨らみ、ホスティング料金が 3 倍になり、完全な再構築を目にしています。
不満な点は?これらの失敗は完全に予測可能です。WordPress ディレクトリプラグインは悪いソフトウェアではありません。WordPress が設計されていない何かをするよう求められているだけです。ものが崩れ落ちるところを正確に説明し、実際の技術的制約が何であるか、そしてディレクトリ規模のデータを処理する通用するアーキテクチャについて説明します。
目次
- WordPress ディレクトリプラグインの魅力
- WordPress ディレクトリプラグインが崩れるところ
- 誰も話さないデータベースの問題
- パフォーマンスベンチマーク:プラグイン vs. ヘッドレス
- 私が見た実際のプラグイン障害
- 代わりに何を使うか:アーキテクチャオプション
- ヘッドレスディレクトリスタック
- WordPress ディレクトリが実際に意味をなす場合
- 移行戦略:WordPress プラグインから脱出する
- FAQ
WordPress ディレクトリプラグインの魅力
わかります。ピッチは説得力があります。プラグインをインストールし、いくつかのフィールドを構成し、テーマを選択すると、午後中に機能的なディレクトリができました。2025 年の最も人気のあるオプション -- GeoDirectory、Business Directory Plugin(BDP)、Jetrocket の Jetrocket Directory、および Jetrocket Jetrocket -- は初期セットアップエクスペリエンスで本当に良くなりました。
ここで典型的な WordPress ディレクトリプラグインが提供するもの:
- リスティング用のカスタム投稿タイプ
- 構造化データ用のカスタムフィールド(電話、住所、営業時間など)
- 検索とフィルタインターフェース
- マップ統合(通常は Google Maps または OpenStreetMap)
- ユーザー送信フォーム
- 有料リスティングの支払い統合
- レビューおよび評価システム
200 のビジネスを持つローカル商工会議所?完璧です。1,000 以下のリスティングを持つニッチなディレクトリとそれほど多くはないトラフィック?完全に問題ありません。実際に成功すると問題が始まります。
WordPress ディレクトリプラグインが崩れるところ
失敗モードは、私が使用してきたすべての WordPress ディレクトリプラグインで一貫しています。5 つのカテゴリにまとまります。
クエリの複雑さが爆発する
ディレクトリ検索は単純なブログ投稿クエリではありません。典型的なディレクトリ検索は以下でフィルタする必要があるかもしれません:
- 場所(半径ベースの地理空間クエリ)
- 複数のカテゴリタクソノミー
- カスタムフィールド値(価格範囲、アメニティ、評価)
- 営業時間(時間ベースのロジック)
- 可用性またはステータス
WordPress の WP_Query は、投稿を日付、カテゴリ、および 1 つか 2 つのメタ値で取得するために設計されました。5 つまたは 6 つの meta_query パラメータを地理空間計算の上にスタックすると、DBA を泣かせるような SQL を生成しています。
-- 典型的なディレクトリ検索が内部で生成するもの
SELECT DISTINCT p.ID FROM wp_posts p
INNER JOIN wp_postmeta pm1 ON p.ID = pm1.post_id
INNER JOIN wp_postmeta pm2 ON p.ID = pm2.post_id
INNER JOIN wp_postmeta pm3 ON p.ID = pm3.post_id
INNER JOIN wp_postmeta pm4 ON p.ID = pm4.post_id
INNER JOIN wp_term_relationships tr ON p.ID = tr.object_id
WHERE p.post_type = 'directory_listing'
AND p.post_status = 'publish'
AND pm1.meta_key = '_price' AND pm1.meta_value BETWEEN 50 AND 200
AND pm2.meta_key = '_rating' AND pm2.meta_value >= 4
AND pm3.meta_key = '_latitude'
AND pm4.meta_key = '_longitude'
AND tr.term_taxonomy_id IN (45, 67, 89)
ORDER BY (
3959 * acos(
cos(radians(40.7128)) * cos(radians(pm3.meta_value))
* cos(radians(pm4.meta_value) - radians(-74.0060))
+ sin(radians(40.7128)) * sin(radians(pm3.meta_value))
)
) ASC
LIMIT 20;
wp_postmeta での 4 つの自己結合 -- 50,000 のリスティングと 20 のメタフィールドを持つテーブルには 100 万行が含まれています。各結合は仕事を掛けます。MySQL のクエリオプティマイザーは本質的に放棄します。
wp_postmeta ボトルネック
これは独自のセクションに値しますが、簡潔に:WordPress は、すべてのカスタムフィールドデータを単一のテーブルにキーバリュペアとして格納します。これはエンティティ属性値(EAV)パターンであり、スケールでのパフォーマンスが悪いことで悪名高い。実際のデータ値に適切な列インデックスはありません。フィルタされた検索はすべて、この巨大な型なしテーブルのスキャンまたは結合を必要とします。
プラグインの膨れとフックのオーバーロード
ほとんどのディレクトリプラグインは、すべてのページロードで完全なスタックをロードします。40,000 のリスティングを実行している GeoDirectory を持つサイトをプロファイルし、以下を発見:
- プラグインが登録した 847 フィルターフック
- 23 の追加 JavaScript ファイル
- 14 の別の CSS ファイル
- すべてのリクエストで実行される REST API エンドポイント
WordPress のフックシステムは強力ですが、すべての add_filter と add_action にはコストがあります。単一のプラグインが数百を登録するとき、すぐに合計される時間を追加しています。
マップレンダリングが壁に当たる
単一の Google Maps インスタンスで 5,000 のマップマーカーを表示してみてください。ブラウザタブは 500MB 以上の RAM を消費し、マップは本質的に使用不可になります。ほとんどのディレクトリプラグインは、マーカークラスタリングを正しく実装していないか、ビューポートに関係なくすべてのリスティングをマップにロードしています。
マップページだけで 12 秒のインタラクティブになるのを見てきたクライアントサイトがあります。プラグインがすべてのリスティングの座標をページロード時に JavaScript 配列にダンプしていたため。
実際に検索しない検索
WordPress のネイティブ検索はキーワードベースで悪い。ディレクトリプラグインは通常、postmeta に対する LIKE '%term%' クエリを使用してそれら自体の検索をボルトで留めます。インデックスを使用できず、毎回完全なテーブルスキャンを実行します。50,000 のリスティングで、単一の検索クエリは合理的なハードウェアで 3-5 秒かかる可能性があります。
Elasticsearch、Meilisearch、または Typesense のような専用の検索エンジンと比較してください。50ms 未満で結果を返します。
誰も話さないデータベースの問題
ディレクトリプラグイン開発者がマーケティングに載せていない数学を説明します。
wp_postmeta 成長
| リスティング | リスティングあたりのメタフィールド | wp_postmeta 行 | 概算テーブルサイズ |
|---|---|---|---|
| 1,000 | 15 | 15,000 | ~2 MB |
| 10,000 | 15 | 150,000 | ~20 MB |
| 50,000 | 15 | 750,000 | ~100 MB |
| 100,000 | 15 | 1,500,000 | ~200 MB |
| 500,000 | 15 | 7,500,000 | ~1 GB |
そしてそれは 単なる リスティングメタです。WooCommerce、ユーザーメタ、その他のプラグインを追加します -- 50K のディレクトリリスティングを持つ実世界の wp_postmeta テーブルには、2-3 百万行があります。
MySQL の InnoDB エンジンは、適切にインデックスされた型付き列を使用して百万行テーブルを正常に処理します。wp_postmeta の EAV パターンはすべての機能を無効にします。meta_value 列は LONGTEXT 型です。つまり、数値比較でもクエリ時の型キャストが必要です。
適切なスキーマの外観
ここに適切に正規化された構造の同じデータがあります:
CREATE TABLE listings (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL,
description TEXT,
category_id INTEGER REFERENCES categories(id),
price DECIMAL(10,2),
rating DECIMAL(3,2),
latitude DECIMAL(10,7),
longitude DECIMAL(10,7),
status VARCHAR(20) DEFAULT 'active',
created_at TIMESTAMP DEFAULT NOW(),
INDEX idx_price (price),
INDEX idx_rating (rating),
SPATIAL INDEX idx_location (latitude, longitude)
);
型付き列。適切なインデックス。地理空間クエリの空間インデックス。wp_postmeta に対して 3 秒かかる同じ検索は、このスキーマに対して 15ms かかります。同等ではありません。
パフォーマンスベンチマーク:プラグイン vs. ヘッドレス
2024 年後半に同じ DigitalOcean ドロップレット(4 vCPU、8GB RAM)で 50,000 のリスティングを使用してこれらのベンチマークを実行しました。
| メトリック | WP + GeoDirectory | WP + BDP | Next.js + PostgreSQL | Astro + Directus |
|---|---|---|---|---|
| ホームページ TTFB | 1.2s | 1.4s | 85ms | 45ms (static) |
| 検索(3 フィルター) | 3.8s | 4.2s | 120ms | 110ms |
| リスティング詳細ページ | 0.9s | 1.1s | 95ms | 40ms (static) |
| マップ(1000 マーカー) | 6.5s インタラクティブ | 7.1s インタラクティブ | 1.2s インタラクティブ | 1.1s インタラクティブ |
| 同時ユーザー(安定) | ~50 | ~40 | ~500 | ~2000 (CDN) |
| Lighthouse パフォーマンス | 34 | 28 | 92 | 98 |
| 月間ホスティングコスト | $80-150 | $80-150 | $20-40 | $5-15 |
これらの数字は選別されていません。WordPress ディレクトリサイトは、これほど多くの CSS、JavaScript を配信し、これほど多くのブロッキングリクエストを作成しているため、Lighthouse Performance では 25-45 の範囲で一貫してスコアを付けます。ヘッドレスセットアップと静的生成またはISR は、単に異なるパフォーマンス階層に住んでいます。
私が見た実際のプラグイン障害
不動産ディレクトリ
クライアントは WordPress で ListingPro を使用して不動産リスティングサイトを構築しました。8,000 のリスティングで、検索に 5 秒以上かかりました。彼らの解決策?さらにキャッシングレイヤーを追加します。Redis オブジェクトキャッシュ、Varnish、フルページキャッシング。キャッシュされたページは高速でしたが、すべての検索(リアルタイムフィルタリングが必要)は、すべてのキャッシュをバイパスし、データベースに直接アクセスしました。ユーザーが数十のフィルター組み合わせを組み合わせることができるとき、動的検索結果を効果的にキャッシュすることはできません。
私たちはそれを Next.js と Meilisearch で再構築しました。検索は 30ms に低下しました。ホスティング料金は月額 $200 から月額 $45 に低下しました。
レストランディレクトリ
食品配達アグリゲーターは Jetrocket Directory を使用して WordPress で開始しました。25,000 のレストランで、彼らの管理パネルはほぼ使用不可になりました -- リスティング管理画面は 20 秒かかりました。WP 管理リスト表は、すべての列について postmeta をクエリしていたため。彼らは 3 人の異なる WordPress 開発者を雇い、誰もが異なる最適化アプローチを試しました。なし働きました。
再構築は PostgreSQL を持つ Payload CMS と Astro フロントエンドを使用しました。管理インターフェースは瞬時でした。6 週間で移行を処理しました。
専門サービスディレクトリ
このもの傷ついた。クライアントは、ディレクトリを強化する高度なカスタムフィールド(ACF)を持つカスタム WordPress テーマに $40,000 を投資していたため。ACF は -- 推測してください -- wp_postmeta にすべてを格納します。15,000 の各フィールドを持つ専門家で、データベースには postmeta だけで 500,000 行以上がありました。ファセット検索が壊れました。サイトの平均 TTFB は 2.1 秒でした。
代わりに何を使うか:アーキテクチャオプション
正しいアーキテクチャはスケール、予算、チームに依存します。私が機能していると見てきたアプローチはここにあります。
オプション 1:ヘッドレス CMS + モダンフロントエンド
これはほとんどのディレクトリのスイートスポットです。コンテンツ管理に Directus、Payload、Strapi、または Sanity などのヘッドレス CMS を使用し、Next.js または Astro などのフレームワークを使用します。
最適なもの: 5,000-500,000 のリスティング、JavaScript エクスペリエンスを持つチーム。
Social Animal では、これはディレクトリクライアント向けに最も構築するアーキテクチャです。私たちの ヘッドレス CMS 開発 仕事はパターンがこれほど自然に適合しているため、ディレクトリを含む頻繁になります。
オプション 2:カスタムアプリケーション
真に大規模なディレクトリ(500K+ リスティング)またはディレクトリ(予約システム、リアルタイム可用性、マーケットプレイス機能)の複雑なビジネスロジックの場合、Rails、Django、Laravel、または Node.js フレームワークなどのようなものに構築されたカスタムアプリケーション完全な制御を提供します。
最適なもの: 100,000+ のリスティング、複雑なワークフロー、専用の開発チーム。
オプション 3:専用ディレクトリプラットフォーム
Jetrocket Directory(WordPress プラグインではなく SaaS)、Jetrocket、または Jetrocket のようなプラットフォームは、ディレクトリ向けに構築されています。彼らはインフラストラクチャの懸念を処理しますが、カスタマイズを制限します。
最適なもの: 非技術的な創設者、MVP 検証、10,000 のリスティング未満のシンプルディレクトリ。
オプション 4:静的生成 + 検索サービス
リスティングが頻繁に変わらないリード-ヘビーなディレクトリでは、すべてのページを静的に生成し、検索を専用サービスにオフロードできます。Astro はこのパターンに素晴らしいです。
最適なもの: 1,000-100,000 のリスティングはまれに更新、最大パフォーマンス要件。
私たちは Astro 開発 実践でこの方法でいくつかのディレクトリを構築しました。パフォーマンス数は不合理です -- グローバル CDN から提供されるため、100ms 未満のページロード。
ヘッドレスディレクトリスタック
ここに 2025 年の実際のスケール処理が必要なディレクトリで推奨するスタック:
データレイヤー
プライマリデータベースの PostgreSQL。以下の機能をネイティブでサポートしている:
- フルテキスト検索(多くの使用例で十分な)
- 地理空間クエリ用の PostGIS 拡張
- 柔軟なスキーマ部分の JSONB 列
- 型付き列の適切なインデックス作成
// 例:Node.js バックエンドで PostGIS を使用した地理検索
const listings = await db.query(`
SELECT id, title, slug,
ST_Distance(
location,
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography
) as distance
FROM listings
WHERE ST_DWithin(
location,
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography,
$3 -- 半径(メートル)
)
AND category_id = ANY($4)
AND rating >= $5
ORDER BY distance
LIMIT 20
`, [longitude, latitude, radiusMeters, categoryIds, minRating]);
そのクエリは 100,000 のリスティングに対して 20ms 未満で実行されます。wp_postmeta を使用してそれを行ってみてください。
検索レイヤー
Meilisearch または Typesense 即座検索とファセットフィルタリング用。両方ともオープンソースで、自己ホストされたテイカーであり、このユースケース用に特別に設計されています。
| 機能 | Meilisearch | Typesense | Algolia |
|---|---|---|---|
| オープンソース | はい | はい | いいえ |
| 自己ホストコスト | $0 | $0 | N/A |
| クラウド価格(2025) | $30/月から | $25/月から | $110/月から |
| タイプミスを許容します | 優れた | 良い | 優れた |
| 地理検索 | 組み込み | 組み込み | 組み込み |
| ファセットフィルタリング | はい | はい | はい |
| 平均クエリ時間 | 10-50ms | 5-30ms | 10-40ms |
CMS レイヤー
Payload CMS(ディレクトリに対する私の現在のお気に入り)または Directus。両方とも PostgreSQL を直接使用し、適切な管理 UI を提供し、フロントエンドの API を公開します。
Payload 3.0 は特に優れています。これは Next.js の中で実行されるため、CMS とフロントエンドを一緒に配置できるためです。管理パネルは React ベースで、EAV テーブルではなく型付きデータベース列をクエリするため、大きなデータセットでも高速です。
フロントエンドレイヤー
リアルタイム検索とフィルタリングが必要なインタラクティブなディレクトリ向けの Next.js。SEO とパフォーマンスが最重要なコンテンツに焦点を当てたディレクトリ向けの Astro。
我々はしばしば、ライブマップ更新、瞬時の検索、リアルタイムの可用性が必要なディレクトリのために Next.js 開発 サービスを推奨します。コンテンツ焦点のディレクトリの場合、島嶼アーキテクチャを持つ Astro は、可能な限り最高のパフォーマンスを提供します。
マップレイヤー
MapLibre GL JS(オープンソース)または Mapbox GL JS 適切なマーカークラスタリング:
// クラスタリング付きの MapLibre - 100K+ マーカーをスムーズに処理
map.addSource('listings', {
type: 'geojson',
data: '/api/listings/geojson',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'listings',
filter: ['has', 'point_count'],
paint: {
'circle-color': '#4F46E5',
'circle-radius': [
'step', ['get', 'point_count'],
20, 100, 30, 750, 40
]
}
});
WebGL 経由で GPU でクラスタリングが発生するため、100,000 マーカーを壊すことなく処理します。Google Maps インスタンスに 5,000 の DOM マーカーを落とすことと比較してください。
WordPress ディレクトリが実際に意味をなす場合
WordPress はディレクトリ向けに常に間違っていると言うつもりはありません。それは不誠実です。WordPress ディレクトリプラグインは以下の場合の合理的な選択肢です:
- 2,000 個未満のリスティングがある
- トラフィックは月間 10,000 以下の訪問者
- 検索複雑さは低い(単一カテゴリ、単一位置)
- 数日で起動する必要があります。数週間ではなく
- 予算は $5,000 未満
- 実際の構築にコミットする前にアイデアを検証している
そのうちの 3 つ以上が当てはまる場合は、GeoDirectory または BDP を使用してください。ただし、天井を知ってください。
移行戦略:WordPress プラグインから脱出する
WordPress プラグインから脱出する準備ができたら、私たちために機能してきたアプローチを次に示します。
- すべてをエクスポート -- WP-CLI を使用して、すべてのメタを使用してすべてのリスティングを JSON にダンプします。プラグイン export 機能を信頼しないでください。通常は不完全です。
wp post list --post_type=directory_listing --format=json --fields=ID,post_title,post_name,post_content,post_status > listings.json
wp post meta list --format=json > listing_meta.json
データを変換する -- EAV 構造を適切に型付けされたレコードにマップする移行スクリプトを記述します。これは退屈ですが、批判的です。
リダイレクトを設定する -- 古い URL を新しい URL にマップします。ディレクトリサイトにはしばしば数千のインデックス付きページがあります。その SEO エクイティを失うことはできません。
両方のシステムを並行して実行 -- WordPress サイトを新しいシステムを構築して QA する間はそのままにします。確信が持てるまで、トラフィックのみを送信をリダイレクトしてください。
ユーザーアカウントを移行 -- ユーザー送信リスティングがある場合、アカウントを移行して、パスワードリセットフローを設定する必要があります。WordPress パスワードハッシュは別のアルゴリズムを使用しているため。
移行を見ていて、スコープを決める際に支援が必要な場合、私たちのチームはこれを何度も十分に実行して、反復可能なプロセスを行いました。スケールができる典型的なディレクトリ再構築が何か見ているために 価格 をチェックするか、あなたの特定の状況を話すために 直接アクセスしてください。
FAQ
パフォーマンスが低下する前に、WordPress は何個のリスティングを処理できますか?
私の経験では、臨界点は典型的なディレクトリプラグインで 5,000-10,000 のリスティング周辺です。5,000 周辺のより遅い管理画面を気付き始める、フロントエンド検索パフォーマンスは 10,000 までに著しく低下します。積極的なキャッシングとビーフィなサーバーを使用して、おそらく 20,000 に押し上げることができます -- しかし、あなたはその時点でアーキテクチャと戦っています。
WP_Query は WordPress ディレクトリの主なボトルネックですか?
それは主なボトルネックの 1 つですが、根本原因はより深い:それは wp_postmeta EAV テーブル構造です。WP_Query をバイパスしてカスタム SQL を記述しても、型なしキーバリュテーブルに対してクエリしています。データ列の適切なインデックスがありません。実際の修正は完全に異なるデータモデルを必要とします。
オブジェクトキャッシング(Redis)は WordPress ディレクトリパフォーマンスを修正できますか?
Redis は、繰り返し同じクエリをキャッシュします -- ホームページリスティンググリッドやポピュラーなカテゴリページなど。しかし、ディレクトリ検索には、効果的にキャッシュするために多くのフィルター順列が含まれています。10 個のフィルターを持つ 5 つのオプションで各フィルターに、それは数百万の可能な組み合わせです。それらすべてをプリキャッシュすることはできず、検索クエリのキャッシュ命中率は通常 5% 未満です。
スケーラブルなディレクトリを構築する最も安い方法は何ですか?
見た中で最も費用効果的なスケーラブルスタックは Astro + Directus(自己ホスト)+ SQLite/PostgreSQL + Meilisearch Cloud です。小さな VPS で月額 $30 未満でこれをホストでき、100,000 以上のリスティングを処理でき、1 秒未満のページロードを処理できます。開発コストは WordPress プラグインよりも初期段階では高いですが、2-3 年以上の総所有コストはほぼ常に低いです。
ディレクトリ検索に Elasticsearch または Meilisearch を使用するべきですか?
ほとんどのディレクトリでは、Meilisearch または Typesense は Elasticsearch より優れています。Elasticsearch は信じられないほど強力ですが、operationally で複雑です -- 重要な RAM(最小 4GB)、慎重なインデックス管理、チューニングの専門知識が必要です。Meilisearch は検索機能の 90% を与えて、運用オーバーヘッドの 10% を与えます。複雑な集計、多言語分析が必要な場合、または数百万のドキュメントをインデックスしている場合にのみ Elasticsearch と一緒に進んでください。
WordPress を CMS として保つことができ、ヘッドレスフロントエンドを使用できますか?
技術的には yes、WordPress REST API または WPGraphQL を使用します。しかし、あなたはまだ wp_postmeta データレイヤーと一緒に立ち往生しています。クエリパフォーマンスの問題は、フロントエンドを変更しても消えません。フロントエンドを分離するつもりなら、通常は CMS レイヤーも切り替えるのは理にかなっています。適切なリレーショナルスキーマを持つものへ。
WordPress ディレクトリをヘッドレスアーキテクチャに移行するのにどのくらい時間がかかりますか?
50,000 のリスティング未満を含むシンプルなディレクトリの場合、開発時間の 6-10 週間を計画します。データ移行自体は通常数日かかります。仕事の大部分は、フロントエンド、検索機能、カスタムビジネスロジックの再構築です。ユーザーアカウント、支払いシステム、ブッキング機能を含む複雑なディレクトリは 12-16 週間かかる可能性があります。
postmeta の代わりにカスタム データベーステーブルで WordPress を使用するについてはどうですか?
これは実際に実行可能な中間路線です。Meta Box や Jetrocket などのプラグインは、wp_postmeta の代わりにカスタムテーブルにデータを格納できます。一部のプラグイン互換性を失いますが、パフォーマンス向上は劇的です。それでもあなたは WordPress の他の制限に対処しています -- フックシステムのオーバーヘッド、モノリシック PHP アーキテクチャ、フロントエンドパフォーマンス天井。それは絆創膏です。治療ではなく。