エンジニアリング チームは、DynamoDB のデータに対して複雑なフィルター、集計、テキスト検索を実行する必要がよくあります。しかし、DynamoDB はトランザクション処理用に最適化された運用データベースであり、リアルタイム分析用ではありません。その結果、多くのエンジニアリング チームは DynamoDB での分析の限界に達し、代替オプションを検討しています。
これは、運用ワークロードのアクセス パターンが複雑な分析ワークロードと大きく異なるためです。DynamoDB は限られた操作セットのみをサポートしているため、分析が困難になり、場合によっては分析が不可能になります。DynamoDB の背後にある企業であるAWSでさえ、企業に対して分析を他の専用ソリューションにオフロードすることを検討するようアドバイスしています。よく参照されるソリューションの 1 つが Elasticsearch であり、これについて今日詳しく説明します。
DynamoDBは最も人気のある NoSQL データベースの 1 つで、ゲーム、ソーシャル メディア、IoT、金融サービスなどの多くの Web スケール企業で使用されています。DynamoDB は、そのスケーラビリティとシンプルさから選ばれるデータベースであり、1 秒あたり 2,000 万リクエストの規模で 1 桁ミリ秒のパフォーマンスを実現します。この速度を大規模に実現するために、DynamoDB は、運用ワークロードのパフォーマンス、つまり個々のデータ レコードに対する高頻度で低レイテンシの操作を実現することに重点を置いています。
Elasticsearch は、Lucene 上に構築されたオープンソースの分散検索エンジンで、テキスト検索やログ分析のユースケースに使用されます。Elasticsearch は、分析ダッシュボードの視覚化ツールである Kibana を含む、より大きな ELK スタックの一部です。Elasticsearch は柔軟で高度にカスタマイズできることで知られていますが、複雑な分散システムであり、パフォーマンスを維持するにはクラスターとインデックスの操作と管理が必要です。Elastic と AWS から Elasticsearch のマネージド サービスが提供されているため、EC2 インスタンスで自分で実行する必要はありません。
恥知らずな宣伝: Rockset はクラウド用に構築されたリアルタイム分析データベースです。DynamoDB へのコネクタが組み込まれており、1 秒未満の検索、集計、結合のためにデータを取り込み、インデックスを作成します。ただし、この投稿では、DynamoDB と Elasticsearch の使用例を取り上げます。このオプションを検討したい場合に備えてです。
AWS Lambda を使用すると、分析のために DynamoDB データを Elasticsearch に継続的にロードできます。仕組みは次のとおりです。
DynamoDB 用のLogstash プラグインを使用して Elasticsearch にデータを同期する別の方法もありますが、現在はサポートされておらず、構成が複雑になる可能性があります。
テキスト検索とは、文書内のテキストを検索して、最も関連性の高い結果を見つけることです。多くの場合、最適な結果を見つけるには、単語の一部、単語の同義語や反意語、または単語の文字列を検索する必要があります。一部のアプリケーションでは、検索語句の重要度に基づいて重み付けを変えることもできます。
DynamoDB は、パーティション化を使用してデータを絞り込むだけで、一部の限定的なテキスト検索ユースケースをサポートできます。たとえば、e コマース サイトの場合、製品カテゴリに基づいて DynamoDB のデータをパーティション化し、メモリ内で検索を実行できます。どうやら、 Amazon.com の小売部門は、多くのテキスト検索ユースケースをこのように処理しているようです。DynamoDB は、データの特定の部分文字列を含む文字列を検索できるcontains 関数もサポートしています。
電子商取引サイトでは、製品カテゴリに基づいてデータを分割する場合があります。ブランドや色など、検索対象のデータとともに追加の属性が表示される場合があります。
全文検索がアプリケーションの中核となるシナリオでは、関連性ランキングを備えた Elasticsearch などの検索エンジンを使用する必要があります。Elasticsearch でのテキスト検索の仕組みの概要は次のとおりです。
関連性ランキング: Elasticsearch には、検索結果にすぐに使用できる関連性ランキングが用意されています。また、特定のアプリケーションの使用例に合わせてランキングをカスタマイズすることもできます。デフォルトでは、Elasticsearch は用語の頻度、逆ドキュメント頻度、フィールド長の標準に基づいてランキング スコアを作成します。
テキスト分析: Elasticsearch はテキストをトークンに分割してデータをインデックスします。これをトークン化と呼びます。次に、正規化された用語にアナライザーを適用して検索結果を強化します。デフォルトの標準アナライザーは、Unicode コンソーシアムに従ってテキストを分割し、一般的な多言語サポートを提供します。
Elasticsearch には、あいまい検索、オートコンプリート検索などの概念もあり、アプリケーションの仕様に合わせてさらに高度な関連性を構成することもできます。
複雑なフィルターを使用すると、結果セットを絞り込むことができ、より速く効率的にデータを取得できます。多くの検索シナリオでは、複数のフィルターを組み合わせたり、一定期間などのデータの範囲でフィルター処理したりする必要があります。
DynamoDB はデータをパーティション分割し、適切なパーティション キーを選択すると、データのフィルタリングをより効率的に行うことができます。また、DynamoDB はセカンダリ インデックスもサポートしているため、データを複製し、別のプライマリ キーを使用して追加のフィルターをサポートできます。セカンダリ インデックスは、データに複数のアクセス パターンがある場合に役立ちます。
たとえば、物流アプリケーションは、配送状況に基づいてアイテムをフィルタリングするように設計できます。このシナリオを DynamoDB でモデル化するには、パーティション キーがItem_ID
、ソート キーがStatus
、属性が buyer、 ETA
、 SLA
である物流のベース テーブルを作成します。
また、配信遅延が SLA を超えた場合に備えて、DynamoDB で追加のアクセス パターンをサポートする必要もあります。DynamoDB のセカンダリ インデックスを活用して、SLA を超えた配信のみをフィルター処理できます。
ベース テーブルにすでに存在する ETA 属性のレプリカであるETADelayedBeyondSLA
フィールドにインデックスが作成されます。このデータは、ETA が SLA を超えた場合にのみETADelayedBeyondSLA
に含まれます。セカンダリ インデックスはスパース インデックスであり、クエリでスキャンする必要があるデータの量を削減します。 buyer
はパーティション キーであり、ソート キーはETADelayedBeyondSLA
です。
セカンダリ インデックスを使用すると、複雑なフィルターを含むアクセス パターンなど、アプリケーション内の複数のアクセス パターンをサポートできます。
DynamoDB のクエリおよびスキャン API には、式に一致しない結果をフィルタリングするためのfilterexpression操作があります。filterexpression filterexpression
クエリまたはスキャン テーブル操作の後にのみ適用されるため、クエリに対して 1 MB のデータ制限が適用されます。とはいえ、 filterexpression
アプリケーション ロジックの簡素化、応答ペイロード サイズの削減、有効期限の検証に役立ちます。要約すると、アプリケーションのアクセス パターンに応じてデータをパーティション分割するか、セカンダリ インデックスを使用して DynamoDB でデータをフィルタリングする必要があります。
DynamoDB は、高速なデータ取得のためにデータをキーと値で整理しますが、複雑なフィルタリングには適していません。複雑なフィルタが必要な場合は、Elasticsearch などの検索エンジンに移行するとよいでしょう。これらのシステムは、干し草の山から針を探すようなクエリに最適です。
Elasticsearch では、データは検索インデックスに保存されます。つまり、列値がポスティング リストとして保存されるドキュメントのリストです。述語を持つクエリ (例: WHERE
user=A) は、述語を満たすドキュメントのリストをすばやく取得できます。ポスティング リストはソートされているため、クエリ時にすばやくマージして、すべてのフィルタリング条件を満たすことができます。Elasticsearch は、頻繁にアクセスされる複雑なフィルター クエリの取得プロセスを高速化するために、シンプルなキャッシュも使用します。
フィルター クエリ (Elasticsearch では一般に非スコアリング クエリと呼ばれます) は、テキスト検索クエリよりも高速かつ効率的にデータを取得できます。これは、これらのクエリでは関連性が必要ないためです。さらに、Elasticsearch は範囲クエリもサポートしており、上限と下限の間のデータをすばやく取得できます (例: age
は 0 ~ 5 歳)。
集計とは、ビジネス インテリジェンスや傾向分析のためにデータを収集し、要約形式で表現することです。たとえば、アプリケーションの使用状況メトリックをリアルタイムで表示したい場合があります。
DynamoDB は集計関数をサポートしていません。AWS が推奨する回避策は 、DynamoDB と Lambdaを使用して、DynamoDB テーブル内のデータの集計ビューを維持することです。
Twitter のようなソーシャル メディア サイトでの「いいね!」の集計を例に挙げてみましょう。tweet_ID tweet_ID
主キーにし、ソート キーを「いいね!」を集計する時間枠にします。この場合、DynamoDB ストリームを有効にして Lambda 関数をアタッチし、ツイートが「いいね!」された (または「いいね!」されなかった) ときに、タイムスタンプ (つまりlast_ updated
) とともにlike_count
に集計されるようにします。
このシナリオでは、DynamoDB ストリームと Lambda 関数を使用して、like_count をテーブルの属性として集計します。
もう 1 つのオプションは、集計を Elasticsearch などの別のデータベースにオフロードすることです。Elasticsearch は本質的には検索インデックスであり、集計機能をサポートする拡張機能が追加されています。これらの拡張機能の 1 つがdoc valuesです。これは、インデックス作成時に構築され、列指向でドキュメント値を格納する構造です。この構造は、doc values をサポートするフィールドにデフォルトで適用され、doc values にはストレージの肥大化が伴います。DynamoDB データの集計のサポートのみが必要な場合は、幅広いデータセットに対する分析クエリ用にデータを効率的に圧縮できるデータ ウェアハウスを使用する方がコスト効率が良い場合があります。
Elasticsearch の集約フレームワークの概要は次のとおりです。
バケット集約: バケット化は、SQL データベースの世界のGROUP BY
に似たものと考えることができます。フィールド値または範囲に基づいてドキュメントをグループ化できます。Elasticsearch バケット集約には、結合サポートの欠如に対する一般的な回避策であるネストされた集約と親子集約も含まれます。
メトリック集計:メトリックを使用すると、ドキュメント セットに対してSUM
、 COUNT
、 AVG
、 MIN
、 MAX
などの計算を実行できます。メトリックは、バケット集計の値を計算するためにも使用できます。
パイプライン集計: パイプライン集計の入力は、ドキュメントではなく他の集計です。一般的な用途には、平均やメトリックに基づく並べ替えなどがあります。
集計を使用すると、特にElasticsearch を拡張する場合にパフォーマンスに影響が出る可能性があります。
Elasticsearch は DynamoDB のデータに対して複雑な検索や集計を行うための 1 つのソリューションですが、多くのサーバーレス支持者もこの選択に対する懸念を表明しています。エンジニアリング チームが DynamoDB を選択するのは、サーバーレスであり、運用上のオーバーヘッドをほとんどかけずに大規模に使用できるためです。別のブログでは、セットアップ、メンテナンス、クエリ機能、レイテンシーの容易さの観点から、Athena、Spark、Rockset など、 DynamoDB での分析に関する他のいくつかのオプションを評価しました。
Rockset は Elasticsearch の代替手段であり、Alex DeBrie が Rockset で SQL を使用してクエリをフィルタリングおよび集計する方法について説明しました。Rockset は、 DynamoDB へのコネクタが組み込まれたクラウドネイティブ データベースであり、複雑な結合を伴うユースケースを含む分析ユースケースを簡単に開始して拡張できます。300 ドルのクレジットが付いた無料トライアルで、Elasticsearch の代替手段として Rockset を試すことができます。