7

Azure テーブル/Blob/SQL ストレージの比較をたくさん読んで、それらすべてを十分に理解していると思います。おそらく、同様のシナリオの経験があり、推奨を行うことができる人です。

私が持っているもの

記事を varchar(max) 列内の生の HTML に格納する SQL Azure DB。各行には、簡単にクエリを実行できるように、多くのメタデータ列と多くのインデックスもあります。このテーブルには、ユーザー、サブスクリプション、タグなどへの参照が多数含まれているため、私のプロジェクトでは常に SQL DB が必要になります。

どうしたの

このテーブルにはすでに約 500,000 の記事があり、年間数百万の記事が増えると予想しています。各記事の HTML コンテンツは、数 KB から 1 MB の範囲で、ごくまれに 1 MB を超えることがあります。

2 つの問題が発生します。Azure SQL ストレージは高価であるため、これを格納するためのコストを考えると、遅かれ早かれ頭を悩ませることになります。また、遅かれ早かれ 150 GB の DB サイズ制限にも達します。これらの 500,000 件の記事は、すでに 1.6 GB の DB スペースを消費しています。

私が欲しいもの

これらの HTML コンテンツが SQL DB の外に出なければならないことは明らかです。記事テーブル自体は、ユーザー、サブスクリプション、タグなどに結合して、必要な記事をリレーショナルにすばやく検出するために残しておく必要がありますが、少なくとも HTML コンテンツを保持する列は、安価なストレージにアウトソーシングできます。

一見すると、Azure テーブル ストレージは完璧に適合するように見えます

非常に安価な価格と高速なクエリで 1 つの大きなテーブルに数テラバイトのデータを格納 - SQL DB へのアドオンとして記事のコンテンツを保持する単一のテーブル ストレージ テーブルを用意するのは完璧に思えます。

しかし、ここでの比較を読むと、それはオプションでさえないかもしれないことがわかります: 私の記事の 98 % には列あたり 64 KB で十分ですが、残りの 2 % があり、いくつかの単一の記事では、行制限の 1 MB 全体でさえも可能性があります。十分ではありません。

BLOB ストレージは完全に間違っているように聞こえますが、...

したがって、Azure に残されたオプションは 1 つだけです。ブロブです。さて、それは思ったほど間違っていないかもしれません。ほとんどの場合、一度に 1 つの記事のコンテンツのみが必要です。これは、Blob Storage で問題なく高速に動作するはずです。

しかし、コンテンツも含めて一度に50、100、またはそれ以上の行が必要なクエリもあります。そのため、SQL クエリを実行して必要な記事を取得し、Blob ストレージからすべての記事を取得する必要があります。私はそれについての経験はありませんが、それを行うときにクエリのミリ秒のタイムスパンにとどまることができるとは信じられません。また、数秒かかるクエリは、私のプロジェクトでは絶対に禁止されています。

したがって、それも適切な解決策ではないようです。

私は計画を持った男のように見えますか?

少なくとも私は計画のようなものを持っています。適切なレコードのみを SQL テーブル ストレージや BLOB ストレージに "エクスポート" することを考えました。

「コンテンツが < 64 KB である限りテーブル ストレージにエクスポートし、それ以外の場合は SQL テーブルに保持します (または、この 1 つの XL レコードを BLOB ストレージにエクスポートすることもできます)」のようなものです。

それは十分にうまくいくかもしれません。しかし、それは物事を複雑にし、おそらく不必要なエラーを起こしやすくします.

それらの他のオプション

MongoDB や CouchDB など、私のニーズにより適していると思われる NoSQL DB が他にもいくつかあります (少なくとも、紙の仕様を読んだばかりの私の単純な観点からは、それらの経験はありません)。しかし、彼らは自己ホスティングを必要とするでしょう.可能であれば、私はそれを避けたいと思っています. 私は Azure を使用して、セルフ ホスティング サーバーとサービスに関して必要最小限のことを行っています。

本当にここまで読んだ?

それから、あなたの貴重な時間と私の問題について考えてくれてありがとう:)

どんな提案でも大歓迎です。ご覧のとおり、私には私のアイデアと計画がありますが、前に道を歩いた人の経験に勝るものはありません:)

ありがとう、ベルンハルト

4

8 に答える 8

7

この質問を支援するためだけにサインアップしました。過去に、私は Stackoverflow から私の問題に対する有用な回答を見つけました - コミュニティに感謝します - それで、この質問で何かを返すことを試みるのは公正だと思いました (おそらく、公正というのは控えめな表現です)。 .

要するに、質問に記載されているすべての要因を考慮しながら、月あたりのトランザクションを適切に見積もることができる場合は、テーブル ストレージが最適なオプションである可能性があります。ドキュメント/html/データを分割(プレーンテキスト方式またはシリアル化)することで、言及した2つの制限、行と列の制限を解決できます。Table Storage に保存された 40 GB 以上のデータの経験から言えば、アプリはページにアクセスするたびにミリ秒単位で 10 行を超える行を頻繁に取得します。ここでは議論の余地はありません。時々 50 以上の行が必要な場合は、1 桁台の低い秒を調べているか、並列で (さらにデータを異なるパーティションに分割することで)、または非同期の方法で行うことができます。または、以下の推奨されるマルチレベル キャッシングをお読みください。

もう少し詳しく。SQL Azure、Blob (ページとブロックの両方)、および Table Storage を試しました。Mongo DB について話すことはできません。部分的には、ここで既に述べた理由から、私はそのルートに行きたくなかったからです。

  • テーブル ストレージは高速です。パーティションと行キーを使用してクエリを実行すると、20 ~ 50 ミリ秒の範囲で、場合によってはさらに高速になることもあります (たとえば、同じデータ センターで 10 ミリ秒まで低下したことがわかっています)。さらに、データとそれに関する知識に基づいて、何らかの方法でいくつかのパーティションを作成することもできます。
  • トランザクションではなく GB の観点から、より適切にスケーリングします
  • あなたが言及した行と列の制限は負担であり、同意しましたが、ショーストッパーではありません. エンティティを分割するための独自のソリューションを作成しました。簡単すぎるか、この既に作成されたソリューションを見ることができます (問題全体を解決するわけではありませんが、良いスタートです): https://code.google.com/ p/lokad-cloud/wiki/FatEntities
  • また、他の制限 (要求サイズが 4 MB 未満、アップロード帯域幅など) のためにエンティティをバッチ処理する場合でも、テーブル ストレージへのデータのアップロードには時間がかかることに注意する必要があります。

ただし、TableStorage だけを使用することは、最善の解決策ではない可能性があります (成長と経済を考えると)。最終的に実装した最適なソリューションは、静的クラス、Azure ロール ベースのキャッシュ、テーブル ストレージ、ブロック BLOB から始めて、マルチレベルのキャッシュ/ストレージを使用しました。読みやすくするために、これをそれぞれレベル 1A、1B、2、3 と呼びましょう。このアプローチを使用すると、中規模の単一インスタンス (2 つの CPU コアと 3.5 GB の RAM - 私のラップトップの方がパフォーマンスが優れています) を使用しており、100 GB 以上のデータを数秒で処理/クエリ/ランク付けできます (95% のケースで 1 秒未満)。 )。私たちがすべてをチェックしていることを考えると、これはかなり印象的だと思いますそれらを表示する前に「記事」(400万以上の「記事」)。まず、これはトリッキーであり、あなたのケースでは可能かもしれないし不可能かもしれません。私はデータとそのクエリ/処理の使用法について十分な知識を持っていませんが、データをうまく整理する方法を見つけることができれば、これは理想的かもしれません. 私は仮定を立てます: ユーザーといくつかのタグに関するいくつかの情報を与えられて、関連する記事を検索して見つけようとしているように思えます (おそらくニュース アグリゲーターの亜種で、そのような予感がしました)。この仮定は、提案を説明するために行われているため、正しくなくても、これがどのように採用されるかについて、あなたの助けになるか、新しいアイデアのきっかけになることを願っています.

レベル 1A データ。 主要なエンティティまたはそのプロパティを静的クラスで識別して追加します (更新の予測方法に応じて定期的に)。ユーザーの好み (人口統計や興味など) とタグ (テクノロジー、政治、スポーツなど) を特定するとします。これは、ユーザーが誰であるか、その設定、およびタグをすばやく取得するために使用されます。これらをキーと値のペアと考えてください。たとえば、キーはタグであり、その値は記事 ID のリストまたはその範囲です。これにより、問題の小さな部分が解決されます。つまり、一連のキー (ユーザー設定、タグなど) が与えられた場合、どの記事に関心があるかということです。このデータは、適切に編成されていれば、サイズが小さいはずです (たとえば、記事のパスを保存する代わりに、数値のみを保存できます)。*注意: 静的クラスでのデータ永続化の問題は、Azure のアプリケーション プールが既定で 20 分ほど非アクティブになるたびにリセットされるため、静的クラスのデータは永続化されなくなり、インスタンス間で共有されることです ( 1)以上ある場合は負担になる可能性があります。レベル 1B の救助にようこそ。

レベル 1B データ 私たちが使用したソリューションは、レイヤー 1A データを Azure キャッシュに保持することです。これは、必要に応じて静的エンティティを再設定するという唯一の目的のためです。レベル 1B データは、この問題を解決します。また、アプリケーション プールのリセットのタイミングで問題が発生した場合は、プログラムで変更できます。したがって、レベル 1A と 1B は同じデータを持ちますが、一方が他方よりも高速です (CPU キャッシュと RAM に十分近い例えです)。

レベル 1A と 1B について少し 説明する 静的クラスとキャッシュを使用するのは、より多くのメモリを使用するため、やり過ぎだと指摘する人もいるかもしれません。しかし、実際に私たちが見つけた問題は、まず静的で高速であることです。第 2 に、キャッシュにはいくつかの制限があります (つまり、オブジェクトごとに 8 MB)。ビッグデータでは、それは小さな限界です。データを静的クラスに保持することで、8 MB を超えるオブジェクトを保持し、それらを分割してキャッシュに格納できます (つまり、現在 40 を超える分割があります)。ところで、Azure の次のリリースでこの制限を増やすために投票してください。ありがとうございます! リンクは次のとおりです。

レベル 2 データ キー/値エンティティ (レベル 1A) から値を取得したら、その値を使用して Table Storage のデータを取得します。この値から、必要なパーティションと行キーがわかります。ここで解決される問題: ユーザー/検索コンテキストに関連する行のみをクエリします。ご覧のとおり、レベル 1A のデータを持つことは、テーブル ストレージからの行のクエリを最小限に抑えることです。

レベル 3 データ テーブル ストレージ データには、記事の要約、最初の段落、またはその性質のものを保持できます。記事全体を表示する必要がある場合は、Blob から取得します。テーブル ストレージには、BLOB 内の完全な記事を一意に識別する列も必要です。BLOB では、次の方法でデータを整理できます。

  1. 各記事を別々のファイルに分割します。
  2. n 個の記事を 1 つのファイルにグループ化します。
  3. すべての記事を 1 つのファイルにグループ化します (最初の印象ほど悪くはありませんが、お勧めしません)。

最初のオプションでは、記事のパスをテーブル ストレージに保存し、Blob から直接取得します。上記のレベルのため、ここでいくつかの完全な記事を読むだけで十分です。

2 番目と 3 番目のオプションでは、シークを使用して、ファイルのパスと、読み取り位置と読み取り停止位置の開始位置と終了位置をテーブル ストレージに格納します。

C# のサンプル コードは次のとおりです。

YourBlobClientWithReferenceToTheFile.Seek(TableStorageData.start, SeekOrigin.Begin);
        int numBytesToRead = (int)TableStorageData.end - (int)TableStorageData.start;
        int numBytesRead = 0;

        while (numBytesToRead > 0)
        {

          int n = YourBlobClientWithReferenceToTheFile.Read(bytes,numBytesRead,numBytesToRead);
            if (n == 0)
                break;
            numBytesRead += n;
            numBytesToRead -= n;
        }

これが本にならなかったことを願っています。フォローアップの質問やコメントがある場合は、お気軽にお問い合わせください。ありがとう!

于 2013-06-02T21:22:42.637 に答える
1

これについての私の考え: MongoDB (または CouchDB) ルートに行くと、(高可用性のために) いくつかのサーバーを実行する必要があるため、追加のコンピューティングのコストがかかることになります。また、必要なパフォーマンスに応じて、2 コアまたは 4 コアのボックスを実行することになります。3 つの 4 コア ボックスは、SQL DB のコストよりも多く実行されます (さらに、ストレージのコストがかかり、MongoDB などは、デュアブル ストレージのために Azure BLOB にデータをバックアップします)。

さて、HTML を BLOB に保存することに関しては、これは非常に一般的なパターンで、大きなオブジェクトを BLOB ストレージにオフロードします。特にあなたが言及したファイルサイズの範囲では、GETはブロブストレージへの1回の呼び出し(1回のトランザクション)で実行できるはずです。また、各ブロブを連続して取得する必要はありません。TPL を利用して、複数の BLOB をロール インスタンスに並行してダウンロードできます。

もう 1 つ: コンテンツをどのように使用していますか? ロール インスタンスからストリーミングしている場合は、TPL について述べたことはうまく機能するはずです。一方、href出力ページに 's を挿入する場合は、blob の URL を html ページに直接挿入できます。また、プライバシーが心配な場合は、ブロブを非公開にし、短時間のアクセスを許可する短い TTL の「共有アクセス署名」を生成します (これは、ブロブの URL を他の HTML ページに挿入する場合にのみ適用されます。適用されません)。ロール インスタンスにダウンロードして、そこで何かを行う場合)。

于 2013-05-23T22:40:05.697 に答える
1

いくつかのコメント:

  • できることは、常に HTML コンテンツをBLOBストレージに格納し、BLOB の URL をテーブル ストレージに格納することです。個人的には、条件付きでデータを保存するという考えは好きではありません。つまり、HTML ファイルのコンテンツが 64 KB を超える場合にのみ、それを blob ストレージに保存し、それ以外の場合はテーブル ストレージを使用します。このアプローチから得られるその他の利点は、引き続きデータをクエリできることです。すべてを BLOB ストレージに格納すると、クエリ機能が失われます。
  • 他の NoSQL ストアの使用に関する限り、私が見た唯一の問題は、それらが Windows Azure でネイティブにサポートされていないことです。そのため、それらの管理も自分で行う必要があります。
于 2013-05-23T15:07:40.333 に答える
1

MongoDB の GridFS 機能を使用できます: http://docs.mongodb.org/manual/core/gridfs/

デフォルトでデータを 256k のチャンクに分割し (最大 16MB まで構成可能)、ファイルの保存と取得に使用できるファイル システムとしてシャード データベースを使用できるようにします。ファイルがチャンク サイズよりも大きい場合、mongo db ドライバーは、ファイルを取得する必要があるときにデータの分割/再構築を処理します。ディスク容量を追加するには、シャードを追加するだけです。

ただし、一部の mongodb ドライバーのみがこれをサポートしており、これはドライバーの規則であり、この動作を許可するサーバー機能ではないことに注意してください。

于 2013-05-23T14:33:11.427 に答える
0

あなたは言いませんが、おそらく問題を解決する記事を圧縮していない場合は、テーブルストレージを使用してください。

それ以外の場合は、テーブル ストレージを使用し、記事ごとに一意のパーティション キーを使用してください。記事が大きすぎて 2 行に収まらない場合は、パーティション キーでクエリを実行する限り、両方の行を取得し、行キーをインデックスとして使用して、記事がどのように組み合わされるかを示します。

于 2013-05-23T21:12:10.970 に答える
-1

私が持っている1つのアイデアは、CDNを使用して記事のコンテンツを保存し、クライアント側から直接リンクすることです.SQLからデータを取得してストレージに移動するマルチフェーズ操作ではありません。それは次のようなものになります

http://<cdnurl>/<container>/<articleId>.html

実際、Blob ストレージでも同じことができます。

ここでの利点は、これが非常に高速になることです。

ここでの欠点は、セキュリティ面が失われることです。

セキュリティのために Shared Access Signature のようなものを調査できますが、クライアント側のリンクにどの程度役立つかはわかりません。

于 2013-05-23T14:26:41.983 に答える