データ・モデリング
データ・モデリング文書は、このシリーズの最初のベスト・プラクティス文書です。 以下のベスト・プラクティスが示されています。
- APIについて知っておくべきこと。
- データをどのようにモデル化するか。
- 使用する必要がある文書のサイズ。
- 回避すべきこと
- データベースを構成する方法。
詳しくは、索引付けと照会 または 実践における IBM Cloudant を参照してください。
本書の内容は、2019 年 11 月 21 日に Stefan Kruger が「Best and worst practice」というブログ記事として執筆したものです。
対象となる API を理解する
Java™、 Python、 Go、 Node.js 、またはその他のユース・ケース固有の言語やプラットフォームを使用できます。 これらの言語の中には、ユーザーがツールに期待する規約に従って、IBM Cloudant のアクセスを適切に統合する、便利なクライアント・サイドのライブラリーを備えているものもあります。 これらの言語は、プログラマーの効率性には優れていますが、API を非表示にします。
この抽象化はユーザーが望んでいるものであり、繰り返される冗長な作業を削減することがクライアント・ライブラリーを使用する理由でもあります。 しかし、トラブルシューティングや問題報告をする際には、基礎となるAPIを理解することが不可欠だ。 疑わしい問題を IBM Cloudant のサポート・チームに報告するとき、問題を再現する方法を提供していただけると、サポート・チームがユーザーを支援する際に役立ちます。
この依頼は、アプリケーションの Java™ ソースをごっそりそのまま切り取ってサポート・チケットに張り付けることを意味するものではありません。そうしていただいても、サポート・チームはおそらくそれをビルドできません。 また、クライアント・サイドのコードは、問題がどこにあるのか (ユーザー側にあるのか、それとも IBM 側にあるのか) 不確定な要素を含んでいます。
その代わりに、 IBM Cloudant 'のサポートチームは通常、問題を実証するAPIコールのセットを、理想的には彼らが実行できる curl コマンドのセットとして要求する。 トラブルシューティングにこのようなアプローチを採用することで、問題がどこで失敗しているかをピンポイントで特定しやすくなります。 ユーザーのコードが予期しない動作をしている場合は、API への直接アクセスのみを使用して問題を再現してみてください。
できない場合、その問題は IBM Cloudant サービス自体の問題ではありません。
パフォーマンスの問題を調査している場合は、IBM Cloud® が提供するログを参照してください。 ユーザーの要求が IBM Cloudant によって迅速に処理されていることがログに示されているが、アプリケーションが遅い場合、その問題の根本はクライアント・サイドのアプリケーション・コードにあります。 ロギングとモニタリングに関する規則を参照してください。
公式にサポートされているクライアント・ライブラリーに問題があると思われる場合、その問題を実証する小さな自己完結型のコード・サンプルを作成してみてください。 この自己完結型のコード例では、他の依存関係をできる限り少なくします。 Java™ を使用している場合、最小限の テストハーネスを使用してライブラリの問題を浮き彫りにしていただけると助かります。
ときどき、IBM Cloudant に、裏付けとなる証拠なしに「IBM Cloudant が遅いため壊れている」というサポート・チケットが届きます。 ほとんどの場合、このケースは、クライアント・サイドのアプリケーション・コードの問題であるか、IBM Cloudant の動作に関する誤解です。
必ずではありませんが、ほとんどそうです。
API をよく理解することにより、特にパフォーマンスの観点から、IBM Cloudant の動作に関する経験を積むこともできます。 クライアント・ライブラリーを使用している場合は、少なくとも、特定の関数呼び出しによってどの HTTP 要求が生成されるかを調べる方法を知っておく必要があります。 詳しくは、以下の Web サイトを参照してください。
ほとんど同時に変更されるデータは文書内でグループ化する必要がある
データをモデル化を開始すると、遅かれ早かれ、文書がどのように構造化されるかという問題にぶつかります。 これで、 IBM Cloudant が正規化を強制していないこと、そして、例えば、以下のようなトランザクションがないことがわかっただろう、 Postgres. ユーザーは、各文書にできるだけ多くのものをパックし、HTTP の使用量を節約したいと思うかもしれません。
しかし、それはお勧めしません。
同時に変更されない情報をグループ化するモデルを使用している場合は、更新の競合が発生する可能性が高くなります。
例えば、複数のユーザーがいて、それぞれに一連の注文が関連付けられているとします。 その場合は、注文をユーザーの文書内の配列として表すことができます。
{ // DON'T DO THIS
"customer_id": 65522389,
"orders": [
{
"order_id": 887865,
"items": [
{
"item_id": 9982,
"item_name": "Iron sprocket",
"cost": 53.0
},
{
"item_id": 2932,
"item_name": "Rubber wedge",
"cost": 3.0
}
]
}
]
}
注文を追加するには、完全な文書を取り出し、JSON をアンマーシャルし、項目を追加し、新規 JSON をマーシャルして、それを更新として返送する必要があります。 1 人のユーザーだけがこれを実行するのであれば、しばらくは問題ないかもしれません。 しかし、文書が同時に更新されたり、複製されたりすると、更新の競合が発生する可能性があります。
代わりに、顧客 ID を参照して、注文を独自の文書タイプとして分離するようにします。 これで、モデルは不変になります。 注文を追加するには、データベースに新しい注文書を作成する。
特定の顧客のすべての注文を取得できるようにするには、ビューを使用します。これについては、後で説明します。
既存の文書の一部分の更新に依存するような構造は、できる限り避けてください。 悪いデータモデルは、本番稼動後に変更するのが難しいことが多い。
前のパターンは、パーティション・データベースを使用することで効率的に解決できます。これについては、後で詳しく説明します。
詳しくは、以下の資料を参照してください。
- IBM Cloudant のデータ・モデリングのガイド
- データベース・パーティション
文書を小さく保つ
IBM Cloudant では、最大文書サイズが 1 MB に設定されています。 この制限は、1 MB に近い文書サイズが適切であることを意味するものではありません。 一方、KB が 1 桁を超える文書を作成している場合は、おそらくモデルを見直す必要があります。 IBM Cloudant のいくつかの要素は、文書が大きくなるにつれてパフォーマンスが低下します。 例えば、JSON のデコードにはコストがかかります。
*「ほとんど同時に変更されるデータは文書内でグループ化する必要がある」と「文書を小さく保つ」*の各セクションを見てみましょう。 更新に依存するモデルでは、文書サイズのカットオフ値である 1 MB が最大ボリューム制限であることに留意してください。 文書サイズが大きいことは望ましくありません。
添付ファイルを使用しない
IBM Cloudant では、添付ファイルを文書と一緒に格納することがサポートされています。この機能は、CouchDB から継承した長年存在する機能です。 ウェブ・アプリケーションのバックエンドとして IBM Cloudant を使用する場合、小さなアイコンや、CSSや JavaScript ファイルなどの静的アセットもデータと一緒に保存することができます。
ただし、特に画像や動画などの大きな資産については、IBM Cloudant で添付ファイルを使用する前に、以下のことを考慮する必要があります。
- IBM Cloudant は、ブロック・ストアとして高価である。
- IBM Cloudant の内部実装は、大量のバイナリー・データを処理するのに効率的ではない。
そのため、遅くて高価である。
IBM Cloudant は、資産が小さい場合や、たまに使用する程度なら十分に使用できます。 原則として、IBM Cloudant の文書と一緒にバイナリー・データを格納する必要がある場合は、その目的に適した別のソリューションを使用することをお勧めします。 添付ファイルのメタデータだけを IBM Cloudant ドキュメントに保存すればよい。 つまり、ユーザーが選択した適切なブロック・ストアに添付ファイルをアップロードするには、いくつかの追加のコードを書く必要があります。 それが正常に実行されたことを検証してから、IBM Cloudant 文書に添付ファイルへのトークンまたは URL を格納する必要があります。
データベースは、より小さく、より安く、より速く、そしてより簡単に複製できるようになります。 詳しくは、以下の Web サイトを参照してください。
- 添付ファイルに関する IBM Cloudant の資料
- Object Storage への IBM Cloudant 添付ファイルの切り離し
データベースの数は少ない方が良い
可能であれば、IBM Cloudant アカウントあたりのデータベース数を 500 以下に制限してください。 この数は魔法ではありませんが (IBM Cloudant はそれ以上の数を安全に処理できます)、アカウント内のデータベース数が多いと悪影響を受けるユース・ケースがいくつか存在します。
レプリケーター・スケジューラーには、同時に実行できるレプリケーション・ジョブの数に制限があります。 データベースの数が増えるにつれて、アカウントに含まれるすべてのデータベースを複製しようとすると、複製の待ち時間が長くなる可能性があります。
同じコインの裏側には、運用の側面があります。IBM Cloudantの運用チームは、アカウントの移動も複製に頼ります。 データベースの数を抑えると、アカウントをある場所から別の場所に移動する必要がある場合に、運用チームの助けになります。
では、どのような場合に、単一のデータベースを使用し、ビューを使用して異なる文書タイプを区別しなければならないのでしょうか。そして、どのような場合に、複数のデータベースを使用してデータをモデル化しなければならないのでしょうか。IBM Cloudant は、複数のデータベース間でビューを統合することはできません。 決して "結合 "できない、あるいは一緒に照会できない無関係なデータがある場合、そのデータは複数のデータベースに分割する候補となり得る。
拡大し続けるデータ・セット(ログ、センサーの読み取り値、その他のタイプの時系列データなど)がある場合、拡大し続ける巨大なデータベースを 1 つ作ることもお勧めしません。 この種のユース・ケースにはタイム・ボックスが必要です。これについては、後で詳しく説明します。
ユーザーごとのデータベースのアンチパターンを徹底的に避ける
IBM Cloudant の上にマルチユーザー・サービスを構築している場合、各ユーザーがアプリケーション・ アカウント下にある別のデータベースにデータを保存できるようにしたくなる。 それは、ユーザーの数が少ない場合には、大抵うまくいきます。
ここで、クロスユーザー分析を導出する必要性を追加します。 そのためには、すべてのユーザー・データベースを 1 つの分析用データベースに複製します。 これで問題ありません。 このアプリは突然成功し、ユーザー数は 150 人から 20,000 人の範囲に増加します。 分析データベースを最新に保つためだけに、20,000 万個の複製があります。 Active-Active Disaster Recovery のセットアップで実行する場合、さらに 20,000 個の複製を追加すると、システムは機能しなくなります。
代わりに、ユーザー・データを少数のデータベースに多重化するか、ユーザーを一連のデータベースまたはアカウント (あるいはその両方) にシャードします。 この方法では、分析データベースを提供するために複製する必要はありませんが、IBM Cloudant はデータベース・レベルでの認証しか提供しないため、認証はより複雑になります。
IBM Cloudant の権限は「データベースごと」であるため、「ユーザーごとのデータベース」アプローチは魅力的ですが、このパターンが出現したのは実際にはユーザーのせいではありません。
カスタムの JavaScript reduce 関数の使用は避ける
IBM Cloudant の MapReduce ビューは非常に優れています。 しかし、大きな力には大きな責任が伴います。 MapReduce ビューの Map 部分は段階的に構築されるため、マップ内の粗悪なコードは、照会時間ではなく、索引付け作成時間にのみ影響します。 あいにく、reduce 部分は照会時に実行されます。 IBM Cloudant は、 Erlangに内部で実装される一連の組み込み削減関数を提供します。 これらの関数は大規模に実行できますが、手書きの JavaScript の削減は大規模に実行できません。
リデュース関数を書いていることに気づいたら、一度立ち止まって、リデュース関数を書く必要がないようにデータを再編成できないか考えてみてください。 あるいは、組み込みの reduce 関数を使用するようにしてください。
パーティショニングされたデータベース上のビューは、カスタム削減をサポートしていません。これは、そのようなビューのみが提供できるクエリの大幅なスピードアップの要因の1つです。
詳しくは、 reduceに関する IBM Cloudant の資料を参照してください。
拡大し続けるデータ・セットにはタイム・ボックス化されたデータベースを使用する
IBM Cloudant で拡大し続けるデータベースを持つことは、一般的にお勧めしません。 大規模なデータベースは、バックアップが難しく、拡大しても優れたパフォーマンスを維持するには「再ハーディング」を必要とし、索引構築時間が長くなるという問題があります。
この問題を軽減する 1 つの方法は、共通パターンであるタイム・ボックス化されたデータベース (大きなデータ・セットが小さなデータベースに分割される。それぞれのデータベースは、例えば 1 カ月などの時間窓を表す) を使用することで、代わりに複数の小さなデータベースを使用することです。
orders_2019_01orders_2019_02orders_2019_02
新規データは今月のデータベースに書き込まれ、過去のデータの照会は過去の月のデータベースに送信できます。 ある月のデータが不要になったら、そのデータをオブジェクト・ストレージ にアーカイブし、毎月の IBM Cloudant データベースを削除して、ディスク容量を回復できます。 詳しくは、以下の Web サイトを参照してください。