環境変数EntriesPerRebuildでMovable Typeの再構築時間を短縮する
Movable Typeのスタティックパブリッシング(静的生成)の再構築時間は、環境変数EntriesPerRebuildを設定することで短縮できる場合があります。
移転先のサーバで実験してみましたので、報告します。ただし、共有型のレンタルサーバでは500エラーになる可能性もありますのでご注意ください。
1.EntriesPerRebuildについて
環境変数EntriesPerRebuildは、1回のプロセスでブログ記事アーカイブを再構築するブログ記事数を設定します。デフォルトは「40」です。
この値を変更するには、mt-config.cgiにEntriesPerRebuildを設定します。「100」にする場合は次のように記述します。
EntriesPerRebuild 100
2.EntriesPerRebuildと月別アーカイブの関係
環境変数EntriesPerRebuildは、ブログ記事アーカイブだけでなく、月別アーカイブ(月別ブログ記事リスト)にも関係します。具体的には、指定した値のブログ記事に対応する月別アーカイブページを生成します。
この件については、小川さんの以下のページが参考になるでしょう。
3.再構築時間測定
EntriesPerRebuildの値を振って、ブログ記事アーカイブと月別アーカイブの再構築時間を測定しました。占有型のマネージドサーバなので、ブレのない値がとれていると思います。再構築対象データの条件は次の通りです。
- ブログ記事数:約3000件
- 月数:82ヶ月
ブログ記事アーカイブの再構築時間は次の通りです。100あたりで頭打ちになっています。

月別アーカイブの再構築時間は次の通りです。再構築時間の単位は秒です。

こちらは400~500あたりで頭打ちになっています。
ということで、月別アーカイブの再構築時間を考えると、EntriesPerRebuildには400~500を設定すると良いようです。
Movable Type で特定の範囲のブログ記事を再構築する
Movable Type で途中のブログ記事から再構築を開始する方法です。バックグラウンド再構築の環境がなく、再構築の途中で500エラーになった場合などに有効です。
1.管理画面を使ったブログ記事の部分再構築
そもそもブログ記事を部分的に再構築する機能は管理画面で提供されています。画面のようにブログ記事一覧から再構築したいブログ記事をチェックし、「公開」をクリックすればOKです。

2.URLの直接入力による再構築範囲の指定
次のURLを打ち込めば、ブログ記事の範囲を指定して再構築を実行できます。
http://user-domain/mt.cgi?__mode=rebuild&blog_id=[ブログID]&type=Individual&next=0&offset=[オフセット]&limit=&total=[ブログ記事数]
パラメータの意味は次の通りです。
- blog_id
- 再構築対象のブログIDを設定します。
- offset
- 再構築を開始するブログ記事のオフセットを指定します。例えば 100 を指定すれば、最新のブログ記事100 件分をスキップして、101 件目から再構築を開始します。
- total
- 通常の再構築動作では公開ブログ記事数が設定されます。手動で実行する場合、offset より大きい値であれば正常に動作します。
具体的な設定イメージを図に示します。ブログ記事10が最新記事、ブログ記事1が一番古い記事で、offset に3、total に8を設定して再構築すれば、ブログ記事7~ブログ記事3の5件が再構築されます。

ただし、total は EntriesPerRebuild の値が優先し、EntriesPerRebuild のデフォルト値 40 であれば、total - offset が 40件以下であっても、40件分は再構築されるようです。
再構築記事数が少ないのであれば、一覧画面から実行するより体感的に早い気がします。
2.URLの直接入力による再構築ブログ記事IDの指定
次のURLを打ち込めば、ブログ記事を個別に指定して再構築を実行できます。これは1項の動作と同じです。
http://user-domain/mt.cgi?__mode=rebuild_phase&return_args=__mode%3Dlist_entry%26blog_id%3D[ブログID]&id=[ブログ記事ID]&blog_id=[ブログID]
パラメータの意味は次の通りです。
- blog_id
- 再構築対象のブログIDを設定します。
- id
- 再構築を実行したいブログ記事IDを指定します。「&id=xx」のパラメータを繰り返せば、いくつでも実行できます。
Movable Type 4 の再構築負荷を軽減する8つのTips
Movable Type 4 の再構築負荷を軽減する方法をまとめました。Movable Type を運用していて、「再構築に時間がかかるな」と思い始めたときに参考になれば幸いです。
1.SSIによるモジュール化
サイドバーの「最近のブログ記事」「最近のコメント」「カテゴリーリスト」「月別アーカイブリスト」「タグクラウド」などは、メインページや各アーカイブページ・ブログ記事ページの各テンプレートから呼び出され、必要なページ分再構築を繰り返します。
例えば、あるブログに100のブログ記事が投稿されていると仮定すると、ブログ記事ページは100ページあり、ブログ記事ページの再構築を行なった場合、サイドバーの情報も(同じ内容を出力する場合でも)100回再構築を繰り返すことになります。テンプレートタグを使っているリスト類が多いほど、再構築の負荷が大きくなります。
サイドバーのリスト類の再構築の負荷を軽減するには「モジュール化」がよく行なわれる手法です。モジュール化とは、サイドバーのリスト類をSSI(サーバーサイドインクルード)で呼び出すことです。
具体的には、各リストをテンプレートモジュールやウィジェットではなく、インデックステンプレートとして登録し、メインページや各アーカイブページ・ブログ記事ページから、そのインデックステンプレートをSSIで読み込みます。当ブログではPHPによるSSIを行なっています(下図)。

こうすることで、リスト類はインデックステンプレートの再構築1回だけで済み、負荷が大きく軽減されます。
関連記事:
Movable Type の PHP モジュール化の仕組みについて(その3:変更方法)
なお、SSI の設定はMovable Type 4 のデフォルト機能で行なうことも可能です。
ブログ管理画面の「設定」→「公開」

テンプレートモジュール/ウィジェット編集画面の「テンプレートの設定」

ただし、リスト類はテンプレートモジュールまたはウィジェットのまま、最初に再構築したテンプレートと一緒に出力(その後は出力しない)するのですが、リスト類の表示内容は最初に再構築したテンプレートに依存する可能性があるため、期待しない内容が表示される可能性があります(参考:アーカイブページのリストの表示内容が異なる理由)。
そのため、単純に「どのページもメインページと同じ表示内容にしたい」という場合は、本項のモジュール化の方がよいでしょう。
2.CSIによるモジュール化
考え方や、リスト類をインデックステンプレートにする方法は1項と同じですが、Ajax によるCSI(クライアントサイドインクルード)を行なうことで再構築の負荷を軽減します。
この方法であれば、SSI のように、ページをPHPなどに変更する必要はありません。当ブログはこの方法でリスト類の再構築負荷の軽減を図っています。

関連記事:
Ajax によるモジュール化
3.モジュールキャッシングする
Movable Type 4 にはモジュールキャッシング機能があります。これは再構築時にテンプレートモジュールやウィジェットの内容をDBにキャッシュし、以降の再構築はキャッシュを利用することで再構築の負荷を軽減します。

ブログ管理画面の「設定」→「公開」

テンプレートモジュール/ウィジェット編集画面の「テンプレートの設定」

1項で解説したデフォルト機能のSSIと同様、期待しない内容が表示されるケースがありますが、モジュールキャッシングは設定により適正に表示させる方法があります。
関連記事:
The blog of H.Fujimoto - テンプレートモジュールのキャッシュとその効果
The blog of H.Fujimoto - 複雑なキャッシュとその効果
4.インデックステンプレートの再構築トリガを制限する
Movable Type のインデックステンプレートを再構築するトリガは、再構築画面からの再構築以外に、ブログ記事の投稿やコメント投稿・トラックバック受信があります。
例えば、インデックステンプレートに、Google サイトマップや全ブログ記事タイトルを表示するアーカイブインデックスなどの再構築に時間のかかるページに加え、1項のモジュール化したリスト類がある状態でブログ記事の投稿やコメント投稿を行なうと、ブログ記事やコメントとは関係のないインデックステンプレートすべてが再構築されてしまいます(内容に変化がなければファイルとしては出力されません)。
図にすると下のようなイメージになります。

つまり、インデックステンプレートによって再構築するイベントを決めておくことで、イベントと関係のないインデックステンプレートの再構築を避け、ブログ記事投稿やコメント投稿、トラックバック受信処理時の再構築負荷を軽減することができます。

当サイトでは、以前、コメント投稿から完了までに30秒ほどかかり、500エラーが多発していましたが、再構築イベントを絞り込んだところ、コメント投稿時間が10秒前後で完了するようになり、劇的に改善しました。
この対策を行なうには、RebuildIndexFilterプラグインを利用します。
関連記事:
RebuildIndexFilter プラグイン
5.バックグラウンドで再構築する
スタティックパブリッシングで、リアルタイムに再構築する必要がない場合、バックグラウンドパブリッシングをお勧めします。
ブログ管理画面の「デザイン」→「テンプレート」→「公開プロファイルを設定」

なお、バックグラウンドで再構築するにはスケジュールタスクの設定が必要です。
6.ページのアクセスがあったときに再構築する
動的生成のページに対して、最初にそのページへのアクセスがあった時に再構築(静的HTMLファイルを生成)を行います。
この対策を行なうには、RebuildAt1stView プラグインを利用します。詳細はプラグインのページをごらんください。
関連記事:
Junnama Online (Mirror) - RebuildAt1stView(Beta)
Junnama Online (Mirror) - Greg Packer's Publishingその後。
7.ダイナミックパブリッシングに移行する
再構築はスタティックパブリッシングで必要な作業であるため、ダイナミックパブリッシングに移行することで再構築の手間から開放されます。MT3ではディレクトリを手動で作成するなどの設定がやや面倒でしたが、MT4では管理画面の設定のみでダイナミックパブリッシングに移行できます。
ブログ管理画面の「デザイン」→「テンプレート」→「公開プロファイルを設定」

また、ダイナミックパブリッシングは、上記の公開プロファイルによる一律設定の他、テンプレート別に設定することも可能です。
ブログ管理画面の「デザイン」→「テンプレート」→「任意のインデックステンプレート/アーカイブテンプレート」→「テンプレートの設定」

さらに、「キャッシュ」や「条件付き取得」の設定も可能です。
ブログ管理画面の「設定」→「公開」(ダイナミックパブリッシングの設定を行なうと表示されます)

8.定期的に再構築する
記事の主旨からやや外れますが、バックグラウンドで定期的に再構築するには mt-rebuild プラグインを利用します。
関連記事:
mt-rebuild
プラグインの利用にはスケジュールタスクの設定が必要です。
Movable Typeの再構築の出力制御について
ご存知の方も多いと思いますが、Movable Type で再構築(スタティックパブリッシング)を行った時、指定したすべてのファイルは無条件に出力されない仕様になっています。
例えば、すべてのインデックステンプレートで、「再構築オプション」をチェックしている状態(4.15以降であれば「スタティック」を選択)で、再構築画面から「すべてのファイル」または「インデックスのみ」を指定して再構築した場合、スタイルシートやJavaScript(mt.js)を最近編集していないのであれば、それらのファイルのタイムスタンプは更新されません。
極端な条件にすると、ブログ記事やテンプレート、あるいはコメント・トラックバックなど、前回の再構築からブログの情報が全く変更されていない状態で、再構築画面から「すべてのファイル」を選択して再構築を行っても、ファイルはひとつも出力(更新)されません。
この仕様に、最近まで全く気がついていませんでした。
レンタルサーバやローカルPCのタイムスタンプを確認しましたので、おそらく間違いはないと思いますが、認識誤りがありましたらご指摘ください。
1.ファイルが出力される条件
再構築でファイルが出力される条件を示します。
ソースをトレースすれば明確な条件が分かると思いますが、時間がないので(というかトレース能力が低いので)再構築を実際に行って、確認した限りの内容です。
- テンプレートを編集した場合
- 変更した情報に関連するテンプレートタグがテンプレートに記述されている場合
- 管理画面からファイルの出力内容に関係する設定の変更が行われた場合
- 再構築対象のファイルがなくなっている場合
2.各条件の詳細
1番目の条件は自明ですが、テンプレートの内容に変更があった場合、対象のテンプレートを再構築することによってファイルが出力されます。
2番目の条件は、例えば、コメントを投稿(公開)したときに、「最近のコメント」といったコメント関連のテンプレートタグが存在するテンプレートだけが再構築対象になります。逆に、コメント関連のテンプレートタグが存在しないテンプレートは再構築対象になりません。
3番目の条件は、例えば、ブログ記事編集画面でコメント・トラックバックの受信設定を変更した場合、そのブログ記事の内容を変更していなくても、コメントフォームやトラックバックURLの表示が変わるため、保存によって再構築され、ファイルが出力されます。
4番目の条件は、テンプレートの変更や該当するテンプレートタグがなくても、ファイルが何らかの要因でなくなってしまった場合は再構築されます。これはパスやファイル名が変更されたときも同じと思われます。
3.ファイルを出力したい場合
プログラムをハックすれば出力できる手段があるはずですが(または環境変数)、管理画面上で簡単に全てのファイルを再構築するには、テンプレートで共通に呼び出しているテンプレートモジュールを適当に編集してから再構築するのが無難ではないでしょうか。
4.再構築の最適化
テンプレートタグの有無で再構築が制御できることが間違いないのであれば、部品を単純にインクルードするよりも、コメントやトラックバックなどの特定テンプレートタグをモジュール化することで、再構築時間はより短縮できると思います。
4.15のSSIを用いれば、独自にPHP化せずにそのようなことが実現可能かもしれません。
5.再構築の定義
ふと思ったのですが、画面上再構築は行われているのに、仮にファイルがひとつも出力されない場合は「再構築」という表現は正しいのでしょうか(単に素朴な疑問です)。
内部処理では再構築するためのチェックが行われていると思いますし、それを含めて再構築(処理)と定義するのかもしれませんが...。
一括再構築は別として、例えば、個別再構築の場合「前回から変更がなかったのでファイルは更新されませんでした」というメッセージ出力も可能な気がします。
すいません。ちょっと疲れてます。
Movable Type 3.2-ja-2 再構築のパフォーマンス
以前エントリーした Movable Type 3.3b1-ja 再構築のパフォーマンスの後、「3.2の測定もして欲しい」というリクエストがありました。遅くなりましたが本エントリーで測定結果をお知らせします。相変わらず目分量です。
実行環境等は下記の通りです。
- OS:Windows XP Service Pack 2(Pen4 2.8GHz メモリ1.5GBで700MBほど使用中)。自宅サーバです。
- Perl:5.6.1
- DB:MySQL/SQLite
- 再構築対象:エントリー・アーカイブ
- 利用テンプレート:小粋空間3.2テンプレートのエントリー・アーカイブテンプレートを用い、再構築時間に影響があると思われる「最近のコメント *1」「カテゴリーリスト」「サブカテゴリーリスト」をいずれかひとつ設定。その他(カレンダー・最近のエントリー・最近のトラックバック・月別アーカイブ)のリストは常に設定。
- エントリー:約1000
- コメント:約7000
- トラックバック:約2500
- カテゴリー:103
以下、測定結果です。
1.エントリー・アーカイブの再構築時間
数値は最初の120エントリー(40エントリー×3)の平均を元に算出しています。
| MySQL | SQLite | |
|---|---|---|
| 最近のコメント | 18s/40エントリー | 22s/40エントリー |
| カテゴリーリスト | 24s/40エントリー | 124s/40エントリー |
| サブカテゴリーリスト | 33s/40エントリー | 227s/40エントリー |
| 上記リストなし | 18s/40エントリー | 22s/40エントリー |
2.CPU使用率
再構築中は常にほぼ100%。ただし「SQLite+リストなし」のみ96?97%でした。
3.メモリ使用率
再構築時間に比例して増加することはありませんでした(再構築単位でリソースが解放されている模様)。
*1 MTEntries に lastn属性値5を追加しています。lastn 属性を設定しない場合、1エントリーの再構築に30s以上かかるようです(MySQL・SQLiteとも)。
Movable Type 3.3b1-ja 再構築のパフォーマンス
このサイトのバックアップデータを利用して Movable Type 3.3b1-ja の再構築時のパフォーマンスを測定しました。測定といっても目分量ですが。
実行環境等は下記の通りです。
- OS:Windows XP Service Pack 2(Pen4 2.8GHz メモリ1.5GBで700MBほど使用中)。自宅サーバです。
- Perl:5.6.1
- DB:MySQL/SQLite
- 再構築対象:エントリー・アーカイブ
- 利用テンプレート:小粋空間3.2テンプレートのエントリー・アーカイブテンプレートを用い、再構築時間に影響があると思われる「最近のコメント *1」「カテゴリーリスト」「サブカテゴリーリスト」をいずれかひとつ設定。その他(カレンダー・最近のエントリー・最近のトラックバック・月別アーカイブ)のリストは常に設定。
- エントリー:約1000
- コメント:約7000
- トラックバック:約2500
- カテゴリー:103
以下、測定結果です。
1.エントリー・アーカイブの再構築時間
数値は最初の120エントリー(40エントリー×3)の平均を元に算出しています。
| MySQL | SQLite | |
|---|---|---|
| 最近のコメント | 22s/40エントリー | 35s/40エントリー |
| カテゴリーリスト | 27s/40エントリー | 147s/40エントリー |
| サブカテゴリーリスト | 38s/40エントリー | 270s/40エントリー |
| 上記リストなし | 19s/40エントリー | 23s/40エントリー |
2.CPU使用率
再構築中は常にほぼ100%。
3.メモリ使用率
再構築時間に比例して増加することはありませんでした(再構築単位でリソースが解放されている模様)。
*1 MTEntries に lastn属性値5を追加しています。lastn 属性を設定しない場合、1エントリーの再構築に30s以上かかるようです(MySQL・SQLiteとも)。
Movable Type で再構築エラーになる場合の原因と対処
Movable Type 3.2-ja-2 で再構築エラーに関する質問を頂くことが多いので、本エントリーにまとめました。
1.エラー現象
「再構築エラー」とは、主に下記の現象を指します。- 500エラーが表示される
- テンプレート内で MTLink タグを使用していると、そこでエラーとなる(場合がある)
いわゆる「500エラー」とは、 Internal Server Error つまり内部サーバエラーのことで、CGI等のプログラムが何らかの理由で実行できない、あるいはプログラムにエラーがある場合に発生します。
MTLink タグのエラーも500エラーと同様で、MTLink タグのエラーに見えるのは、たまたまそこでエラーメッセージを表示できる実装になっているからではないかと推測しています。
2.再構築エラーの原因
Movable Type で再構築エラーが発生する原因としては、これまで頂いたご質問を集計すると、- Movable Type の DB に BerkeleyDB を使用
→ BerkeleyDB はお手軽ですがパフォーマンスに難があります - エントリー・アーカイブの再構築単位
→ デフォルトの再構築単位は40(エントリー)ですが、この値では再構築エラーになる確率が高いです - エントリー・アーカイブの「最近のコメント」で recently_commented_on を利用している
→ lastn 属性を使用しない recently_commented_on 属性の使用はメモリ消費量が増大します
によるものがほとんどのようです。
そしてこれらを誘発する原因として下記が考えられます。
- サーバのパフォーマンス
- サーバのメモリ量
よくある例として、複数名で共有しているレンタルサーバが考えられます。このケースでは CPU やメモリ等の事実上のスペックは、マシンを占有する人数や使用頻度に反比例して低下していきます。故に再構築の成功率も同時に低下することになります。
また上記の要因が複合すれば再構築エラーが発生する確率はさらに高くなります。
3.エラー解消方法
とりあえず目前のエラーを回避する方法と、本格的な対処の2通りを紹介します。3.1 とりあえず回避する
- デフォルトテンプレートに戻す
デフォルトテンプレートの状態であれば再構築時のエラーはほぼ皆無という認識です。理由は次の内容をご覧ください。 - エントリー・アーカイブのサイドバーを削除してみる
例えば、当サイトの公開テンプレートとデフォルトテンプレートとの大きな違いは、アーカイブページのサイドバーの有無です。公開テンプレートのアーカイブ・テンプレートにはサイドバーにリスト類(カレンダー・最近のエントリー/コメント/トラックバック・カテゴリーリスト・月別アーカイブリスト)を色々と表示しており、その分、MTタグからHTMLマークアップを生成する時間が増加し、結果的に再構築時間に影響を与えることになります。つまりサイドバーにリスト類を表示している場合、それらを全てなくすことで再構築時間を短縮することができます。
なお、再構築エラーは前述の通り複合的な要因で発生します。公開テンプレートでアーカイブテンプレートのサイドバーに情報を表示すること自体についてはテンプレートのバグではありません。その点誤解なきようお願い致します。
3.2 本格的な対処
対処しやすい順番に並べています。- 再構築単位を少なくする
mt-config.cgi の下記の部分を
から# EntriesPerRebuild 40
に書き換えます。10でもエラーになる場合は値をさらに小さくしてください。かなりの方がこれで解消されています。EntriesPerRebuild 10
3.3 では mt-config.cgi にこの設定自体がなくなっていますので新たに追加してください。
- rebuild支援ツールを利用する
再構築を部分的に行うためのツールです(プラグインではありません)。
rebuild支援ツール for MovableType
- DB を MySQL または SQLite または PostgreSQL に移行する
パフォーマンスに問題のある BerkeleyDB の使用をおやめになることを強く推奨します。SQLite の移行方法については、Movable Type + SQLite を参照ください。
MySQL自体の性能は高いのですが、ひとつのDBを多くのユーザでシェアしている場合は解消されないかもしれません。心配な場合はレンタルサーバのサポートに確認してください(自宅サーバ+MySQLはかなり快適です)。PostgreSQL については MySQL と同等とお考えください。
ロリポップの場合は SQLite への移行をお勧めします。
- PHPモジュール化を行う
サイドバーのリスト類をモジュール化(部品化)することで再構築時のパフォーマンスが向上します。ただし、ページ閲覧時に PHP が起動するため、アクセスの多いサイトでの CGI版 PHP の利用は 503 エラーを誘発する可能性があります。PHP モジュール化を行う場合は「条件付きGET」を有効にしてください。関連記事:
Movable Type の PHP化(その1)
PHPモジュール化の仕組みについて
HTTP/1.1 の「条件付きGET」を利用して PHP ファイルアクセスによるサーバ負荷を削減する
PHP における「モジュール版」と「CGI 版」の比較 + WordPress の適用例
- ダイナミックパブリッシングにする
ページを毎回動的に生成する方法です。静的なファイルを作らないため再構築時間が劇的に縮小します。関連記事:
Movable Type の再構築を不要にする「ダイナミック・パブリッシング」(その1:概要)
Movable Type の再構築を不要にする「ダイナミック・パブリッシング」(その2:設定方法)
- サーバを変更する
レンタルサーバもピンキリで、最終的にはサーバや DB のパフォーマンスに依存します。何をやっても事象が好転しない場合はこれをお勧めします。
2006.04.28 追記
rebuild支援ツールとダイナミックパブリッシングを追加しました。
2006.06.20 追記
文言等修正。

