それがベスト プラクティスかどうかはわかりませんが、アプリに ensureIndex を入れない傾向があります。私は通常、dbシェルを使用して必要になると確信しているものを入れます。次に、負荷テスト中 (または本番環境で速度が低下し始めたとき) に注意を払い、見逃したものをシェルに追加します。ensureIndex({a : 1}, {background : true}) を実行することで、バックグラウンドでインデックスを作成できるため、後で作成しても他のデータベースほどひどいものではありません。
MongoDB には、速度が低下しているものを見つけるための優れたプロファイラーがあります: http://www.mongodb.org/display/DOCS/Database+Profiler。
10gen (MongoDB の商用版) には無料の監視サービスがあり、私はまだ使用していませんが、よく話題になっています: http://www.10gen.com/mongodb-monitoring-service。
ただし、コレクションが作成される前に db.collection.ensureIndex() を呼び出すとどうなるかという限りでは、コレクションが作成され、それにインデックスが配置されます。
アプリで確実に必要な場合は、各操作の前ではなく、2番目のオプション(データベース接続の直後にインデックスを確認する)を使用します。私が行ったときにおそらくデータベースに何かを保存するので、2つ以上ある場合は毎回実行されません。PHPはわかりませんが、ここに疑似コードがあります:
var test = db.systemChecks.findOne({indexes : true})
if (test == null) //item doesn't exist
{
//do all the ensureIndex() commands
db.systemChecks.insert({indexes : true})
}
後でインデックスを実行するためにさらにインデックスが必要な場合は、systemCheck アイテムを削除することを忘れないでください。