9

私は、Azure Table Storage から約 1 億行のデータをダウンロードする任務を負っています。ここで重要なのはスピードです。

使用しているプロセスは、Azure テーブル ストレージから 10,000 行をダウンロードしています。それらを Sql Server のローカル インスタンスに処理します。行の処理中に、Azure テーブルから一度に 100 行を削除します。このプロセスは、一度に 10,000 行をダウンロードする 8 つのスレッドを持つようにスレッド化されています。

これに関する唯一の問題は、私たちの計算によると. 保存した約 1 億行をダウンロードして処理するには、約 40 日かかります。このタスクを達成するためのより速い方法を知っている人はいますか?

副次的な質問: ダウンロード プロセス中に、Azure はデータをまったく含まない xml を送り返します。エラーは返されません。しかし、それはこれを送ります:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="azure-url/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
  <title type="text">CommandLogTable</title>
  <id>azure-url/CommandLogTable</id>
  <updated>2010-07-12T19:50:55Z</updated>
  <link rel="self" title="CommandLogTable" href="CommandLogTable" />
</feed>
0

他の誰かがこの問題を抱えていて、それを修正していますか?

4

6 に答える 6

16

Disabling Naglingの提案に加えて、Azure Table Storage のパフォーマンスの向上に関する非常に優れた投稿があります。実際に ADO.NET デシリアライゼーションの速度を向上させると、 Sqwarea ( Lokad.Cloudフレームワークで構築された大規模なオンライン マルチプレイヤー ゲーム) の速度が 10 倍になりました。

ただし、テーブル ストレージは、大規模なストレージ シナリオ(数百万を超えるレコード)には最適なソリューションではない可能性があります。ここでの致命的な要因はレイテンシです。それを回避するために、私はファイルベースのデータベース ストレージをうまく使用してきました。この場合、変更はローカルで行われ (CLAP のネットワーク遅延なし)、ファイルをアップロードすることで BLOB にコミットされます (同時実行性とスケールアウトはLokadによってここで強制されました)。 .CQRS App Engine for Windows Azure)。

一度に 1,000 万件のレコードを SQLite データベースに挿入する (トランザクション内で、各レコードは 2 つのフィールドによってインデックス化され、ProtoBuf を介してシリアル化されたスキーマのない任意のデータを持っていた) 平均で合計 200 秒しかかかりませんでした。結果ファイルのアップロード/ダウンロード - 平均で約 15 秒。インデックスによるランダム読み取り - 瞬時 (ファイルがローカル ストレージにキャッシュされ、ETag が一致している場合)。

于 2010-07-13T03:44:56.750 に答える
7

副次的な質問ですが、「継続トークン」を取得していると思います。.NET ストレージ クライアント ライブラリを使用している場合は、クエリに .AsTableServiceQuery() を追加してみてください。

主な質問に関しては、クエリを展開することが最善の方法です。(Windows Azure ではなく) ローカル マシンからストレージにアクセスしているようです。もしそうなら、テーブル ストレージからデータをフェッチする小さなサービスを Windows Azure にデプロイすることで、処理をかなり高速化できると思います (データ センター内の帯域幅が広く、待ち時間が短いため、はるかに高速です)。結果をローカル マシンに送り返します。XML Windows Azure テーブルの返送には多くのオーバーヘッドがあるため、それを取り除いて行をまとめると、おそらく転送時間が大幅に節約されます。

于 2010-07-12T20:11:48.867 に答える
2

Amazon ではサポートされていますが、まだ Azure ではサポートされていませんが、データを取得する最速の方法は、USB ディスク (USB スティックでも) を発送し、ディスクにデータを入れて返送してもらうことです。

もう 1 つのオプションは、AppFabric Service Bus を使用して、一度にすべてをダウンロードするのを待つのではなく、データが作成されたときに別のシステムにデータを取得することです。

于 2010-07-30T20:49:33.730 に答える
2

帯域幅の制限に関する提案は別として、各テーブル パーティションは 1 秒あたり約 500 トランザクションに制限されているため、ストレージ アカウントの制限に簡単に直面する可能性があります。

さらに、展開された最適化 (Nagle のアルゴリズム) があり、小さな読み取り (1K データ読み取りなど) で実際に速度が低下する可能性があります。Nagling の無効化に関するブログ投稿を次に示します。これにより、特にインターネットの待機時間のない Azure サービスで直接実行している場合は、読み取りが大幅に高速化される可能性があります。

于 2010-07-12T23:58:37.790 に答える
1

ほとんどの場合、制限要因は処理ではなくネットワーク帯域幅です。その場合、唯一の本当の希望は拡張することです。つまり、より多くのマシンでより多くのスレッドを実行してデータをダウンロードすることです。

ところで、Azure は、すべての行を手動でダウンロードする必要をなくす「エクスポート」メカニズムを公開していませんか?

于 2010-07-12T20:08:04.570 に答える
1

ここでの大きな要因は、データがパーティション間でどのように分散されるかです。パーティション境界にまたがるクエリは、問題のパーティションに 0 行がある場合でも、再送信が必要な各境界で返されます。データが 1 パーティション = 1 行の場合、速度は遅くなりますが、スレッド数を 8 より大きく増やすことができます。データが n パーティション = m 行にある場合は、以下のアイデアで速度が向上するはずです。

複数のパーティションがあり、それぞれにいくつかの行があると仮定すると、最速の方法は、できるだけ多くのスレッドを起動することです (.Net を使用している場合は、PLINQ または Parallel.ForEach(partition) または QueueWorkItem())。スレッドにすべての行のパーティションをスキャンさせ、処理し、SQL にポストし、戻る前に削除します。

関連するレイテンシー (数十ミリ秒) と複数回の往復を考えると、8 スレッドを使用しても、おそらく思ったほどビジーではありません。また、使用している VM については言及しませんが、さまざまなサイズをプロファイリングすることをお勧めします。

または、これを行う別の方法は、キューといくつかの 'n' 個のワーカーを利用することです。パーティション (またはパーティションのセット) ごとに、メッセージをキューに入れます。ワーカーにキュー (マルチスレッド) からプルさせ、クエリ/プロセス/ポスト/リピートを実行させます。必要な数のワーカーをスピンアップし、より多くのデータ センターに分散させることができます (つまり、より多くのスループットなど)。

于 2010-07-15T00:47:09.187 に答える