大規模なWordPressサイトでは、記事数が数万件を超えるケースも珍しくありません。
その場合、1つのサイトマップにすべてのURLを収録すると以下の問題が発生します。
- XMLファイルが巨大化し、クローラーの処理が遅くなる
- メモリ消費が増え、サーバー負荷が高くなる
- 50,000件以上のURLを含むと Googleの制限に引っかかる
このようなケースでは、サイトマップを分割して複数のXMLに分ける 方法が有効です。
サイトマップ分割の基本ルール
- 1ファイルあたり 50,000 URL または 50MB 未満 が上限(Google / Bing共通ルール)
- インデックスファイル(
sitemap.xml
)から各分割ファイルを参照する必要がある - 分割数に制限はない(
sitemap-1.xml
,sitemap-2.xml
…のように増やせる)
実装例:専用サイトマップを分割出力する
以下のコードは、カスタム投稿タイプ company
のサイトマップを 2,000件ごとに分割 して出力する例です。
<?php
/**
* 分割サイトマップの実装例
*/
// インデックスに分割サイトマップを登録
add_filter('aioseo_sitemap_indexes', function ($indexes) {
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
return $indexes;
}
// 投稿数を取得
$count = wp_count_posts('company')->publish ?? 0;
$per_file = 2000;
$pages = ceil($count / $per_file);
for ($i = 1; $i <= $pages; $i++) {
$indexes[] = [
'loc' => home_url("/sitemap-company-{$i}.xml"),
'lastmod' => current_time('Y-m-d\TH:i:sP'),
];
}
return $indexes;
});
// 分割されたサイトマップの出力
add_action('template_redirect', function () {
if (preg_match('#sitemap-company-(\d+)\.xml$#', $_SERVER['REQUEST_URI'], $m)) {
$page = (int) $m[1];
$per_file = 2000;
$offset = ($page - 1) * $per_file;
header('Content-Type: application/xml; charset=UTF-8');
$posts = get_posts([
'post_type' => 'company',
'post_status' => 'publish',
'posts_per_page' => $per_file,
'offset' => $offset,
'orderby' => 'date',
'order' => 'DESC',
'no_found_rows' => true,
]);
echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<?php foreach ($posts as $post): ?>
<url>
<loc><?php echo esc_url(get_permalink($post)); ?></loc>
<lastmod><?php echo esc_html(get_post_modified_time('c', true, $post)); ?></lastmod>
</url>
<?php endforeach; ?>
</urlset>
<?php
exit;
}
});
コード解説
- インデックス登録
aioseo_sitemap_indexes
に対して、分割数に応じた複数のsitemap-company-N.xml
を追加。 get_posts()
のoffset
とposts_per_page
各ページに収録する件数(例:2,000件)を指定し、offset
で開始位置を制御。- クエリ最適化 (
no_found_rows
=> true)
ページ数計算はすでに済んでいるため、SQLの総数計算を省略して高速化。
応用アイデア
- キャッシュと併用
前回の記事で解説した「Transients API」を使えば、分割ファイルごとにキャッシュ可能。sitemap-company-1.xml
などをキーにすれば効率的です。 - 条件付き分割
例えば「カテゴリごとに分割」「年ごとに分割」といった柔軟な構成も可能。
クローラーが無駄に読み込む必要がなくなり効率的になります。
まとめ
- サイトマップは 1ファイル5万件・50MB制限 があるため、大規模サイトでは分割必須
aioseo_sitemap_indexes
でインデックス登録し、分割ファイルを生成するoffset
とposts_per_page
を活用して効率的に出力- キャッシュや条件分割と組み合わせれば、さらに最適化可能
コメント