2013年2月18日

Windows Azure Tableの検索パフォーマンス

大分昔(2011年の年末あたり)にAzure Tableへのクエリパターン別の検索パフォーマンスを測って記事を書いていたのですが、公開してませんでした(忘れてた。。。)。

その後いわゆるGen 2のストレージが現れたりしているので、絶対値的には参考にならないと思います。ただ、クエリエンジンがより最適化されるようになったとかっていう話は聞かないので、各クエリ別の相対的な評価としては通用するかと思います。

このまま公開しないのももったいないので、以下最初に書いた時のままですが公開したいと思います。


Windows Azure Tableを使うにあたって、どんなクエリだとどの程度のパフォーマンスが出るのかは気になるところだと思います。昨年末あたりにパフォーマンス計測だけして放っていたので、そろそろ書きます。

ここでは単一パーティションでのクエリ性能を調べるため、単一パーティション内における「RowKeyによる検索とプロパティによる検索」と、「レンジ検索とOR検索」でそれぞれパフォーマンス差がどの程度あるかという点をベンチマークします。そこでベンチマーク対象のクエリは以下の6種類です。

  1. RowKeyの完全一致
  2. RowKeyのレンジ検索
  3. RowKeyのOR検索
  4. プロパティの完全一致
  5. プロパティのレンジ検索
  6. プロパティのOR検索

検索データの作成

まずはベンチマークをとる前にクエリを投げる対象となるデータを作りました。データ生成につかったソースは以下の通りで、ひとつのパーティション内にRowKeyとString型のプロパティ"Value"に必ず同じ値を持つエンティティを10000件作成してます。(もっと件数を増やしてもいいかもしれないけど、ひとつのパーティション内という前提ならこれぐらいが妥当かなと思います)

		private static void Init() {
			var acc = CloudStorageAccount.Parse(CONNECTION_STRING);
			var client = acc.CreateCloudTableClient();
			client.CreateTableIfNotExist("Entities");

			var ctx = client.GetDataServiceContext();

			for ( int i = 0; i < 10000; i++ ) {
				ctx.AddObject("Entities", new Entity() {
					PartitionKey = "0",
					RowKey = String.Format("{0:D4}", i),
					Value = String.Format("{0:D4}", i)
				});

				if ( ctx.Entities.Count % 90 == 0 ) {
					ctx.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
				}
			}

			ctx.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
		}

ベンチマーク結果

そして、作成したデータに対して以下のクエリを1000回ずつ実行した際の平均処理時間と標準偏差が以下の通りです。

種別 実行したLINQクエリ(Where条件のみ記載) 平均処理時間[ms] 標準偏差
RowKeyの完全一致
e.RowKey == value
6.3 12.6
RowKeyのレンジ検索
e.RowKey.CompareTo(begin) > 0 && e.RowKey.CompareTo(to) < 0
7.2 8.1
RowKeyのOR検索
( e.RowKey == value1 || e.RowKey == value2 || e.RowKey == value3 )
78.1 20.7
プロパティの完全一致
e.Value == value
75.3 13.5
プロパティのレンジ検索
e.Value.CompareTo(begin) > 0 && e.Value.CompareTo(to) < 0
94.8 26.6
プロパティのOR検索
( e.Value == value1 || e.Value == value2 || e.Value == value3 )
137.4 18.4

この結果を見ると、完全一致やレンジ検索に関してはやはりRowKeyとプロパティでは、10倍以上パフォーマンスに差がありました。ただOR検索については、RowKey、プロパティどちらの場合でもあまり良いパフォーマンスは得られませんでした。

まとめ

このベンチマークにより、Azure Tableのクエリパフォーマンスに関して以下のことがわかりました。

  1. RowKey検索の方がプロパティ検索より大体10倍位速い。
  2. レンジ検索は改善一致とほとんど変わらないパフォーマンスが得られる。
  3. ただRowKey完全一致においても、平均6.3msとMySQLとかと比べても結構遅い。
  4. OR検索については、RowKey/プロパティどっちでも遅い。

OR検索が思った以上に遅いため、複数のエンティティをまとめて取得したい時でも、下手にORで繋げるよりも別々のクエリとして投げた方が良さそうです。

以前の記事「Azure Tableによるデータ検索 - エンティティの結合(Join)」に記述した「クエリを2つに分割して、LINQ TO OBJECTで結合させる」方法はイマイチってことですね。(件数次第でどちらが良いかは変わりそうですが)

0 件のコメント:

コメントを投稿