連載:[完全版]究極のC#プログラミング

Chapter15 LINQとクエリ式

川俣 晶
2010/03/17
Page 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

15.16 from句とjoin句のパフォーマンス

 さて、join句は制約が大きいことから、できればfrom句を使いたいと思う読者もいるだろう。はたして、from句とjoin句の差はどれぐらいあるのだろうか?

 ここでは、先のリスト15.17を少し変更し、クエリ式からIdの値が何回参照されているかを調べてみよう(リスト15.19参照)。

using System;
using System.Linq;

class Program
{
  class 商品情報
  {
    private int id;
    public static int ReadCount = 0;

    public int Id
    {
      get { ReadCount++; return id; }
      set { id = value; }
    }
    public string 名前;
    public int 定価;
  }

  class 商品販売価格
  {
    private int id;
    public static int ReadCount = 0;

    public int Id
    {
      get { ReadCount++; return id; }
      set { id = value; }
    }
    public int 価格;
  }

  static void Main(string[] args)
  {
    (商品情報データと商品販売価格データの定義は
                                  リスト15.17と同じなので省略)

#if false // from句を試す場合はtrueに書き換える

    var query = from x in 商品情報データ
                from y in 商品販売価格データ
                where x.Id == y.Id
                select new { Name = x.名前, Price = y.価格 };

#else

    var query = from x in 商品情報データ
                join y in 商品販売価格データ on x.Id equals y.Id
                select new { Name = x.名前, Price = y.価格 };

#endif

    foreach (var 商品 in query) {
      Console.WriteLine("{0} {1:C}", 商品.Name, 商品.Price);
    }

    Console.WriteLine(
      "商品情報.ReadCount={0},商品販売価格.ReadCount={1}",
      商品情報.ReadCount, 商品販売価格.ReadCount);
  }
}
リスト15.19 Idの参照回数を調べる

  …
商品情報.ReadCount=9,商品販売価格.ReadCount=9
リスト15.19の実行結果(from句の場合)

  …
商品情報.ReadCount=3,商品販売価格.ReadCount=3
リスト15.19の実行結果(join句の場合)

 この結果を見てわかるとおり、from句を2つ使った場合、クエリ対象の情報は、

ソース1の個数(3)× ソース2の個数(3)× 2 = 18回

の参照だが、join句を使用した場合は、

ソース1の個数(3)+ ソース2の個数(3)= 6回

しか参照されていない。これは、クエリ時のデータ参照の回数がfrom句では掛け算で増えるのに対して、join句では足し算で増えることを意味する。つまり、データの個数が増えれば増えるほど回数の差は劇的に増していく

 もちろん、データを参照する回数だけでパフォーマンスが決まるわけではない。では、具体的な時間差はどの程度あるのだろうか? 次のリスト15.20はそれを調べるために作成したソースコードである。

using System;
using System.Linq;

class Program
{
  (商品情報と商品販売価格の定義はリスト15.17と同じなので省略)

  static void Main(string[] args)
  {
    (商品情報データと商品販売価格データの定義は
                                  リスト15.17と同じなので省略)

    var query1 = from x in 商品情報データ
                 from y in 商品販売価格データ
                 where x.Id == y.Id
                 select new { Name = x.名前, Price = y.価格 };

    var query2 = from x in 商品情報データ
                 join y in 商品販売価格データ on x.Id equals y.Id
                 select new { Name = x.名前, Price = y.価格 };

    const int COUNT = 1000000;

    DateTime start1 = DateTime.Now;
    for (int i = 0; i < COUNT; i++) foreach (var 商品 in query1) { }
    Console.WriteLine("from句: {0}", DateTime.Now - start1);

    DateTime start2 = DateTime.Now;
    for (int i = 0; i < COUNT; i++) foreach (var 商品 in query2) { }
    Console.WriteLine("join句: {0}", DateTime.Now - start2);
  }
}
リスト15.20 from句とjoin句の時間差を調べる

from句: 00:00:03.5363536
join句: 00:00:01.9231923
リスト15.20の実行結果
デバッグビルド時。筆者のPCでの結果。

 このように、処理時間としても、歴然とした差が見て取れる。また、データの個数が増えれば、差はさらに拡大するだろう。両者には歴然とした効率の差があると考えてよいだろう。join句が使用できるときは、join句の利用がお薦めである。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter15 LINQとクエリ式
    1.15.1 LINQの面白さ
    2.15.2 LINQとは何か?
    3.15.3 「値の集まり」に対する演算
    4.15.4 なぜLINQなのか?
    5.15.5 最も基本的なLINQ
    6.15.6 LINQの本質は列挙
    7.15.7 LINQを使ううえでの注意点
    8.15.8 クエリ結果を加工する
    9.15.9 複数のソースからクエリする
    10.15.10 条件で絞り込む
    11.15.11 一部項目のみselectする
    12.15.12 シンプルなソート
    13.15.13 クエリの接続
    14.15.14 クエリ結果のグループ化
    15.15.15 複数ソースを関連付けるjoin句
  16.15.16 from句とjoin句のパフォーマンス
    17.15.17 join句のグループ化結合
    18.15.18 join句の左外部結合
    19.15.19 単独で使うDefaultIfEmptyメソッド
    20.15.20 内部列挙を伴うfrom句の二重使用
    21.15.21 let句
    22.15.22 クエリのインスタンス化
    23.15.23 クエリ結果の個数を得る
    24.15.24 Anyメソッドと存在チェック/【C#olumn】クエリ式のデバッグテクニック
    25.15.25 まとめ/【C#olumn】LINQの難しさ/【Exercise】練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間