カテゴリ: C# 更新日: 2026/02/04

C#のLINQパフォーマンス改善ガイド!初心者でもわかる高速化の秘訣

C#のLINQのパフォーマンス改善ポイントをまとめて解説
C#のLINQのパフォーマンス改善ポイントをまとめて解説

先生と生徒の会話形式で理解しよう

生徒

「LINQって便利ですけど、大量のデータを扱うと動作が重くなるって聞いたことがあります。本当ですか?」

先生

「使い道を間違えると、確かにパソコンに負担をかけて処理が遅くなることがあります。でも、コツさえ掴めば驚くほど速く動かすことができるんですよ。」

生徒

「どうすれば速くなるのか知りたいです!難しい設定が必要なんですか?」

先生

「いいえ、ちょっとした書き方のルールを守るだけです。今回はパフォーマンスを劇的に改善するポイントを、初心者の方にもわかりやすく解説しますね!」

1. LINQのパフォーマンスとは?

1. LINQのパフォーマンスとは?
1. LINQのパフォーマンスとは?

C#の便利な機能であるLINQ(リンク)は、データの集まりから必要なものだけを取り出したり、並び替えたりするのが得意な道具です。しかし、この道具は「魔法」ではありません。裏側ではコンピュータが一生懸命計算をしています。

「パフォーマンス」とは、このコンピュータの処理速度や、メモリ(作業机の広さ)をどれくらい効率よく使えているかという指標のことです。処理が遅いということは、コンピュータが何度も同じ計算を繰り返していたり、不必要なデータを大量に抱え込んだりしている状態を指します。

特にプログラミング未経験の方が陥りやすいのが、「便利だから」といって何でもLINQに任せてしまうことです。正しい知識を持っていないと、データが増えた時に突然アプリが動かなくなることもあります。そこで、効率的なデータクエリ(データの問い合わせ)の書き方を学びましょう。

2. 列挙の回数を最小限にする(Countの問題)

2. 列挙の回数を最小限にする(Countの問題)
2. 列挙の回数を最小限にする(Countの問題)

LINQを使うときによくやってしまうのが、データの数を数えるためにCount()を何度も使ってしまうことです。実は、Count()を呼び出すたびに、LINQはデータの最初から最後までを数え直すことがあります。

例えば、1,000ページある本の内容を確認するとき、毎回1ページ目から数え直していたら時間がかかりますよね。一度数えたら、その結果を変数に保存しておくのが賢いやり方です。


var query = users.Where(u => u.IsActive);

// 悪い例:何度も数え直している
if (query.Count() > 0)
{
    var total = query.Count();
    Console.WriteLine(total);
}

// 良い例:一度だけ数えて結果を取っておく
var activeUsers = query.ToList(); // ここでリストにする
var count = activeUsers.Count; // リストのCountは一瞬で終わる
if (count > 0)
{
    Console.WriteLine(count);
}

用語解説:ToList(トゥーリスト)とは、LINQの実行結果を「リスト」という形式のデータに変換して確定させる命令です。これを行うと、その後の計算がスムーズになります。

3. 「Any」を使いこなして高速化

3. 「Any」を使いこなして高速化
3. 「Any」を使いこなして高速化

「データが一つでもあるかどうか」を確認したいときに、Count() > 0と書いていませんか?これはパフォーマンスを下げる原因になります。Count()は最後まで数えようとしますが、Any()(エニー)という命令を使えば、「一つ見つかった時点で終了」してくれます。

これは、落とし物を探しているときに、「全部で何個落ちているか調べる」のと「一つでも落ちているか確認する」の違いに似ています。一つ見つかればいいのなら、全部探す必要はありませんよね。


// 効率の悪い書き方
bool hasDataSlow = users.Where(u => u.Name == "田中").Count() > 0;

// 効率の良い書き方
bool hasDataFast = users.Any(u => u.Name == "田中");

(結果はどちらも同じですが、Anyの方が圧倒的に速いです)

4. 遅延実行と即時実行の違いを理解する

4. 遅延実行と即時実行の違いを理解する
4. 遅延実行と即時実行の違いを理解する

LINQの最大の特徴であり、初心者が混乱しやすいのが遅延実行(ちえんじっこう)です。LINQの命令(WhereやSelectなど)を書いただけでは、実はまだデータを取りに行っていません。実際にデータの中身が必要になった瞬間(foreachで回す時やToListを呼んだ時)に、初めて計算が始まります。

これを「後回しにする」という意味で遅延実行と呼びます。これの何が問題かというと、知らないうちに同じ計算を何度も繰り返してしまう可能性がある点です。

例えば、フィルタリングした結果を3回使い回すなら、最初に一度だけToList()ToArray()を使って、計算結果をメモリに「確定」させておきましょう。これを即時実行と呼びます。

5. フィルタリング(Where)を先に行う

5. フィルタリング(Where)を先に行う
5. フィルタリング(Where)を先に行う

データクエリの基本中の基本は、「対象を小さくしてから加工する」ことです。例えば、1万人の社員データから「東京支店の人の名前を大文字にする」という処理を考えます。

「全員の名前を大文字にしてから東京支店の人を探す」のと、「東京支店の人を探してから名前を大文字にする」のでは、後者の方が圧倒的に計算量が少なくなります。Where(絞り込み)はできるだけ最初に書きましょう。


// 効率が悪い:先に全員分を加工(Select)している
var badWay = employees.Select(e => e.Name.ToUpper()).Where(name => name.StartsWith("T"));

// 効率が良い:先に絞り込んで(Where)から加工している
var goodWay = employees.Where(e => e.Name.StartsWith("T")).Select(e => e.Name.ToUpper());

6. データベース連携(Entity Framework)での注意点

6. データベース連携(Entity Framework)での注意点
6. データベース連携(Entity Framework)での注意点

C#でデータベースを扱う際、LINQを使ってデータを取得することが多いです。このとき、「IQueryable(アイクエリアブル)」という型を意識する必要があります。

もし、データベースから100万件のデータをすべてパソコンのメモリに読み込んでからLINQで絞り込みを行うと、パソコンがフリーズしてしまいます。正しい書き方をすれば、LINQはSQL(データベース専用の言葉)に翻訳され、データベース側で高速に処理されます。

ポイントは、ToList()を呼ぶタイミングです。Whereなどで条件をすべて指定し終わる前にToList()を書いてしまうと、その時点で全データが手元のパソコンにダウンロードされてしまいます。絞り込みが終わるまでは、リスト化しないのが鉄則です。

7. 大きなデータの並び替え(OrderBy)に注意

7. 大きなデータの並び替え(OrderBy)に注意
7. 大きなデータの並び替え(OrderBy)に注意

データを並び替えるOrderByは非常に便利な機能ですが、非常に重い処理でもあります。すべてのデータを比較して順番を決めなければならないため、コンピュータのパワーをたくさん使います。

もし、特定の1件だけが欲しいのであれば、並び替える必要はありません。例えば「一番年齢が高い人の名前」が欲しい場合、全員を年齢順に並び替えるよりも、最大値を探すMaxBy(.NET 6以降)などを使う方が効率的です。


// 重い:全員を並び替えてから先頭を取る
var oldestSlow = users.OrderByDescending(u => u.Age).First();

// 速い:最大値を持つ人を探すだけ
var oldestFast = users.MaxBy(u => u.Age);

8. メモリ節約!構造体とLINQの相性

8. メモリ節約!構造体とLINQの相性
8. メモリ節約!構造体とLINQの相性

プログラミングを始めたばかりだと意識しにくいですが、コンピュータには「メモリ」という作業スペースがあります。LINQで大量の新しいオブジェクト(データの塊)をSelectで作ると、このメモリを圧迫します。

特に、不必要なデータを大量に含む「匿名型(名前のない型)」をたくさん作るのは避けましょう。必要なデータだけを最小限の形で受け取るように設計することが、アプリ全体の動作を軽くするコツです。初心者のうちは、「今、自分はどれくらいのデータをメモリに読み込もうとしているのか?」を少しだけ想像してみるだけで、コードの質がグッと上がります。

9. パフォーマンス改善の第一歩は「計測」から

9. パフォーマンス改善の第一歩は「計測」から
9. パフォーマンス改善の第一歩は「計測」から

最後に、一番大切なことをお伝えします。どこが遅いのかわからないまま改善しようとするのは、暗闇で的を射ようとするようなものです。C#には処理時間を測るための道具が用意されています。

「この処理は1秒かかるけれど、こっちの書き方なら0.1秒で済む」といった実測結果に基づいて改善を行いましょう。LINQは非常に書きやすいため、つい見た目の綺麗さを優先してしまいがちですが、大量のデータを扱うプロフェッショナルな現場では、こうした細かなパフォーマンスの積み重ねが重要視されます。

カテゴリの一覧へ
新着記事
New1
C#
C#のメモリ管理とガーベジコレクションの基礎を理解しよう
New2
C#
C#の参照型と値型の違いを初心者向けにやさしく解説!
New3
C#
C#のクエリ式とメソッド式の書き換え方を完全ガイド!LINQの2つの書き方をマスター
New4
C#
C#の戻り値にタプルを使う方法!複数の値を返すテクニック
人気記事
No.1
Java&Spring記事人気No1
C#
C#で文字列が数値か判定する方法を解説!char.IsDigitやTryParseの基本
No.2
Java&Spring記事人気No2
C#
C#のLINQでOrderByを使った並び替えを完全ガイド!初心者でもわかるソート方法
No.3
Java&Spring記事人気No3
C#
C#のpartialクラスとは?初心者でも理解できるクラス分割の基本
No.4
Java&Spring記事人気No4
C#
C#のrefとoutキーワードとは?引数の参照渡しを理解しよう
No.5
Java&Spring記事人気No5
COBOL
COBOLの数値データ型「PIC 9」の使い方と注意点をやさしく解説!
No.6
Java&Spring記事人気No6
C#
C#の引数と戻り値の基本!値を受け渡し・返す仕組みを理解しよう
No.7
Java&Spring記事人気No7
C#
C#のラムダ式の書き方と構文を初心者向けに完全解説
No.8
Java&Spring記事人気No8
C#
C#で型を調べる方法!GetType()・typeof演算子の違いと使い方