Lazy Load は関連データの遅延読み込みを行うパターンです。
関連テーブルに入ったデータが必要ではあるけど、意味があるのはそのうち一部の場合だけ、といったケースはよくあります。SQL で JOIN クエリを使って、いくつもの関連テーブルを連結させた巨大な表を読み込む (あるいは、クエリは段階的であったとしても、関連データをあらかじめ全て読み込む) 方針でプログラミングすると、せっかく読み込んだデータのほどんどが、使われることなく破棄されます。
Domain Model では、詳細を問わない他のビジネスロジックに処理を委譲します。そうすると、一部が使われないどころか、場合によっては、読み込んだ関連データを全く使わないかもしれないのです。逆に全て使ったうえで関連の関連まで辿っていくかもしれません。必要な関連データが事前に「わからない」ということこそが、Domain Model の価値 (抽象化による連携) の裏にある本質です。
Lazy Load は、全ての関連データを、最初には取得しません。関連データが入るはずのオブジェクトフィールドには、未取得であるというマークだけを残しておきます。実際にそのフィールドにあるはずのデータが求められたときに、初めて関連データを取得するクエリを発行します。こうすることで、仮想的に、全ての関連データが存在するように見せかけつつ、無駄なデータの読み込みを節約することができます。たとえば、仕事に関係ありそうな技術書をとりあえず一式買って本棚に入れておき、実際に必要になってから詳しく読むようなものです。
しかし、細切れになった随時データ読み込みは、場合によってはパフォーマンスを劣化させることがあります。欲しいデータの総量に対して、クエリの発行回数が多くなりすぎるためです。一括で関連データを 100 行得るのと、1 行しか取得しないクエリを 100 回発行するのを比べると、前者の方がはるかに高速です。そうしたパフォーマンス問題を解消するために、決め込みで事前に一括読み込みをしてしまうことを、Eager Load と呼びます。
Domain Model を基本方針としたとき、Lazy Load が適しているか Eager Load が適しているかは、あらかじめ決めることができません。全体の動作から統計的に判断するしかないのです。あらかじめどちらが適しているかを、関連の関連まで詳細に考えようとすると、実質的にそれはTransaction Script になっていきます。
「Lazy Load が思ったより多い」問題は、実際のクエリログからわかりますが、「Eager Load に無駄がある」問題は、いくら動作ログを見てもわかりません。まずは、パフォーマンスに問題はあっても、いったん全てを Lazy Load の方針で作り、仮想的に全データがメモリにあるものと考えてロジックの全体を成り立たせ、後からパフォーマンスを最適化する、という流れがセオリーです。これは優先度の問題でもあります。いくらパフォーマンスが良くても、ビジネスロジックが間違っていては何の意味もありませんよね。