記事検索

検索ワードを入力してください。
Sky Tech Blog
【AWS】【DynamoDB】DynamoDBに​おける​ページングや​ソート

【AWS】【DynamoDB】DynamoDBに​おける​ページングや​ソート

本記事では、AWS OpenSearch Serviceではなく、DynamoDBを使用し、大量データのソートやページング機能を実現する方法を解説します。DynamoDBの特性を活かしてコストを抑えた方法を紹介します。

SKYPCEはSaaSとして提供されるサービスであるため、新規機能開発において、AWSを用いた開発が多く行われています。

今回の​機能の​構成

今回の機能は、以下のような構成になっています。

機能の​詳細

今回開発する機能では、大量のデータからユーザーのリクエストに応じたデータを検索して画面表示させるために、AWS側でソート、ページングの機能を搭載する必要がありました。
さて、AWS側でソート / ページングするとなると、その機能を持つリソースを使う必要があります。最初に思いついたのは、検索機能が充実している"AWS OpenSearch Service"でした。

AWS OpenSearch Serviceとは

「AWS OpenSearch Service」とは、簡単に言うと、便利な検索が高速にできるものです。もちろん、ソートやページングも余裕でできます(いくつか制限はあります)が、非常に高額であるため、それに見合うような使い方をする必要があります。
今回の要件では、データ中の特定のキーの組み合わせでソート/ページングできれば充足するので、比較的に高額な"AWS OpenSearch Service"を使うほどのものではありません。

コストを​抑えた​ソート / ページング機能の​実現

まず「DynamoDB」の存在を思い出しました。
DynamoDBとは、"サーバレスなフルマネージド型のNoSQLデータベースサービス"で、簡単に説明すると「サーバ構築などの必要がない、SQL言語を使わずに使えるDB」です。
データのスキーマを事前に定義する必要がないので、多様なデータに対応できます。主キーさえあればいいので、以下のようなデータを持たせることができます。

PartitionKey SortKey data1 data2
1 - XXX (なし)
2 - (なし) YYY
3 - WWW ZZZ

※PartitionKeyとSortKeyをあわせてPrimaryKeyと呼び、PrimaryKeyは一意である必要があります(PartitionKeyは必須)。

ただし、弱点もあり、複雑なクエリを実行するのがとても苦手です。データの検索をするにも「フルスキャン」と「クエリ」の2択しかありません。

フルスキャンと​クエリ

フルスキャンはその名の通り、テーブル全体を検索して探していく方法で、条件指定をすることで必要なデータを取得しますが、母数が大量のテーブルには不向きです。
クエリはプライマリキー (パーティションキーとソートキー) を指定して特定の範囲のアイテムを検索することができますが、構成を工夫する必要があります(詳しくはコチラ)。
これだけではほとんどやりたいことができないため、DynamoDBではグローバルセカンダリインデックス(GSI)やローカルセカンダリインデックス(LSI)というそれぞれにプライマリキーを持つインデックスを作成することができます。

GSIの​活用例

例えば、以下のようなDBがあって、

PrimaryKey 部署 名前 年齢 入社年
1 部署1 A 22 2020
2 部署2 B 23 2021
3 部署3 C 41 1990
4 部署1 D 42 1995
5 部署2 E 45 2010
6 部署3 F 33 2013
7 部署1 G 31 2025
8 部署2 H 35 2015

「部署1だけを取りたい」「部署2をAge順にソートして出したい」という場合はDepartmentをPartitionKey、AgeをSortKeyにしたGSIを構築したうえで、GSIに対して取得したい対象の部署を指定してクエリすることで狙ったデータだけを取ることができます。
※クエリはPartitionKeyを一つしか指定できないため、「部署1と部署2を両方とりたい」という場合は分けてクエリするか、専用のGSIを構築する必要があります。

今回の​要件

今回の要件でやりたかったことは、例えば上のデータを例にすると、エンドユーザが指定した「部署」にヒットした人のデータを「年齢+入社年月」の降順に取得することだったので、以下のようにDynamoDBにデータを持たせることで

  • 「部署」をPartitionKeyに、「年齢と入社を組み合わせたもの」をSortKeyにしたGSIでクエリして元テーブルの「PrimaryKey」を取得する
  • GSIでとれた元テーブルの「PrimaryKey」から本データを取ってくる

というように、2段階でデータを取得するようにしています。

PrimaryKey(PK) 部署(GSIのPK) 名前 年齢 入社年 年齢+入社年(GSIのSK) その他の情報
1 部署1 A 22 2020 22#2020 (data)
2 部署2 B 23 2021 23#2021 (data)
3 部署3 C 41 1990 41#1990 (data)
4 部署1 D 42 1995 42#1995 (data)
5 部署2 E 45 2010 45#2010 (data)
6 部署3 F 33 2013 33#2013 (data)
7 部署1 G 31 2025 31#2025 (data)
8 部署2 H 35 2015 35#2015 (data)

ページングの​実現

「部署」の単位でソートして取ることができることは分かったとして、「ページングはどうするの?」という疑問が残ります。
実は、UI(AWS コンソール)では見えませんが、クエリAPIやスキャンAPIを実行した際に取得上限に達すると、「LastEvaluatedKey」という「次データを取るならココ!」というしおりのようなデータが得られます。
クエリAPIにこのLastEvaluatedKeyを指定して取得すると、なんと続きからデータが得られます(詳しくはコチラ)。
そのため、ページング機能も無事に搭載することができました。

まとめ

今回は、DynamoDBでのソート/ページング方法についてまとめてみました。
DynamoDBは少し扱いづらい部分はありますが、最初に考えたOpenSearch Serviceを使わなくても工夫次第で費用もぐっと抑えることができました。
他の要件でも、「これしかない!」と固執せずに「他に工夫できるところはないか」と模索することでよりよい構成になるのではないかと感じています。

本記事が少しでも皆様のお役に立てれば幸いです。


XFacebookLINE
キャリア採用募集中!

入社後にスキルアップを目指す若手の方も、ご自身の経験を幅広いフィールドで生かしたいベテランの方も、お一人おひとりの経験に応じたキャリア採用を行っています。

Sky株式会社のソフトウェア開発や製品、採用に関するお問い合わせについては、下記のリンクをご確認ください。
お問い合わせ
ホーム