みなさん、こんにちは!フリューでモバイルサイト開発を行っている鷲見といいます。
現在、あるソーシャルプラットフォーム上のアプリケーションを構築するプロジェクトでの、クラウド環境の導入の進行状況をそのまま記事にしています。
前回はSimpleDBの詳細な特徴と制限についてお話しました。
前回説明したSimpleDBの制限としては
- サイズ・容量の制限
- 文字列型の制限
- 整合性の制限
- その他の制限
の4つをあげました。
今回はこれらのSimpleDBの制限の回避方法について説明します
サイズ・容量の制限の回避
基本的にサイズ・容量の制限を超えそうな大容量のデータを扱うのであればRDSを選択する方がよいかもしれませんが、それでもSimpleDBを使う必要があるのであれば、以下のような方法で制限回避方法を検討するのがよいかもしれません。
1アイテムあたりの属性数の制限の回避
SimpleDBではJoinができないという制限もあり、冗長なデータ構造をとることが多くなり、属性数が通常のRDBより多くなることが予想されます。しかし、1アイテムあたりの属性ペアの数が256個までという制限もあるので、無制限に属性を追加することができません。
このような制限を回避するために以下のような方法が考えられます。
動的に属性・属性値が増えるような設計をしない
SimpleDBはスキーマレスなデータベースなので、アプリケーションから新たに属性を追加することが可能です。もし、アプリケーションから動的に属性を追加することができるようになっている場合、この属性値のサイズ制限を超えてしまうことになりかねません。また、属性は複数の値を持つことができますが、この属性値が動的に増えることによっても同じ制限に引っかかってしまうことになります。
動的に属性・属性値が追加されるような構成の場合は、事前にアイテムの属性数を確認し、アプリケーション側から属性・属性値の追加を制限する必要があります。
ドメインの分割
予め属性数が256個を超えそうなことが予測される場合は、ドメインを複数に分割し、保存先を複数にすることで、1ドメインあたりの属性数を削減することができます。
属性値サイズの制限
SimpleDBには属性名・属性値・アイテム名のサイズの上限は1,024バイトまでという制限があります。
日本語の文字列にして500文字ちょっとですので、ちょっと長いテキストデータを保存したい場合には、以下のような方法で制限を回避する必要があります。
複数の属性を利用する
保存するデータのサイズに応じて属性を予め複数用意しておく、または動的に変更できるようにしておくことで上記の制限を回避することができます。
例えば、最大2,000文字のテキストを保存する場合、属性名にdescription-1,descrption-2,description-3,description-4の様にサフィックスをつけて属性を作成し、データを分割してサフィックスの値の小さな順に保存していくことで、大きなサイズのテキストデータも保存することができます。
ただし、上述の属性値数の上限に注意しておかないと制限に引っかかってしまうことが考えられます。
S3を利用する
保存したいデータがあまりに大容量の場合は、属性値を複数にする対応にも限界があります。
このような場合は、データそのものをテキストファイルとしてS3上に保存し、属性にはS3の保存先情報を保存しておくという方法が考えられます。
この方法を使えばバイナリデータも扱うことができ、保存するデータサイズにほぼ上限がなくなりますが、データが一意になるような保存先の情報管理をアプリケーション側で行う必要があります。
1ドメインあたりの容量および属性数の制限の回避
SimpleDBにはドメインあたりのサイズが10GBまで、ドメインあたりの属性数が10億個までという制限があります。
履歴データのような増え続けるデータの場合は、運用を続けている内にデータが増え、この制限に引っかかってしまうことが想定されます。
このような事態が予想される場合、以下のような方法で制限を回避することが考えられます。
シャーディング
データの水平分散手法であるシャーディングを行い、ドメインを複数に分割し、1ドメインあたりのサイズ・属性数を減らすことで制限を回避します。
シャーディングではIDや日付といった特定の属性の値によって保存先を変更します。たとえばIDが数値として管理されているような場合、IDの値が奇数の場合はドメイン1に、偶数の場合はドメイン2に保存するといったような方法で、データの保存先を分散させます。
この方法ではアプリケーション側でデータ操作の際に、分散のキーとなる属性(パーティショニングキー)の値によって、操作対象ドメインを変更するといった対応が必要になります。また、分散のキーとなる属性(パーティショニングキー)の設定次第では、データの参照効率が落ちることが考えられるので、よく検討して設計を行う必要があります。
文字列型の制限の回避
SimpleDBのデータ型はすべて文字列型となっています。それゆえ、数値型として扱い、ソートを行う場合に制限があります。
詳細は前回の記事を参照していただくとして、数値型でソートを行うような場合、以下のような制限回避方法を行う必要があります。
ゼロ埋めを行う
数値型のソートで問題となるケースとしては以下のようなケースがあります。
『1』,『9』,『50』,『10』を昇順でソートすると、辞書順になるので『1』,『10』,『50』,『9』の順になる。
このようなケースを回避するために、予め数値として扱う属性毎に桁数を決めておき、指定桁数に満たない部分に関しては『0』を埋め、正しくソートを行えるようにします。
上述のケースで桁数を3桁で『0』埋めを行うと、
『001』,『009』,『050』,『010』を昇順でソートすると、辞書順になるので『001』,『009』,『010』,『050』の順になる。
となり想定した通りの結果となることがわかります。
基準値を決める
マイナス値を含む数値型のソートで問題となるケースとしては以下のようなケースがあります。
『9』,『8』,『−8』,『-9』を昇順でソートすると、辞書順で『9』,『8』,『−9』,『−8』という順になる。
このようなケースを回避するために、予め基準値を決めておき、基準値と値を合算した値を保存します。
例えば、上述のケースで基準値を『100』とし、3桁で『0』埋めを行うと、
『109 (9)』,『108 (8)』,『092 (-8)』,『091 (-9)』を昇順でソートすると、辞書順で『091』,『092』,『108』,『109』という順になる。
となり、想定した通りの結果となることがわかります。
ただし、基準値からの計算を行わないと値がわからないので、パッと見て値がわからないというデメリットもあります。
整合性の制限の回避
こちらに関しては特に制限を回避する方法はなく、アプリケーションの要求に応じ、呼び出し箇所の整合性オプションを適宜変更する必要があります。
その他の制限の回避
ドメイン名の制限
SimpleDBにはRDBでいうところのデータベースのようなものが存在しません。1つのアカウントの1つのリージョンに対して、1つのデータベースが与えられているというイメージになります。
データベース内でテーブル名が重複してはいけないように、SimpleDBでもドメイン名の重複は許可されていません。
これによって何が困るかというと、同じアカウントで開発環境と本番環境を構築した場合、同じドメイン名を利用することができないという事態が発生します。
このような事態での対応としては以下のような方法が考えられます。
同じドメインをテスト環境と本番環境で共同利用する
例えば、『Employee』というドメインがあったとして、属性『environment』が『PRODUCT』のアイテムは本番環境、『TEST』のアイテムはテスト環境というようにして区別します。
ただし、同一ドメインにテストデータと本番データが混在することになるので、データの誤操作が発生する可能性があります。
ドメイン名にプレフィックスを用いる
例えば、『Employee』というドメインがあったとして、テスト環境では『TEST-Employee』、本番環境では『PRODUCT-Employee』といったケースです。
ただし、同一アカウントの同一リージョンにテストデータと本番データが混在することになるので、データの誤操作が発生する可能性があります。
本番環境とテスト環境でアカウントを分ける
本番環境とテスト環境で別々のAWSアカウントを利用することで同じドメイン名が利用することができます。
ただし、AWSの操作やアカウント管理が煩雑になります。
本番環境とテスト環境でSimpleDBのリージョンを分ける
同じアカウントでも別リージョンであれば同じドメイン名を利用することができます。
本番環境は東京リージョン、テスト環境はシンガポールリージョンと分けることで、同じドメイン名を利用することが出来ます。
AWSの操作やアカウント管理は簡単ですが、別リージョンとの通信が発生するため課金が発生することと、東京リージョン以外との通信をおこなうため、ネットワークのレイテンシが発生します。
まとめ
今回はSimpleDBで発生する制限の回避方法について説明しました。
制限の回避方法を簡単にまとめると以下のようになります。
- サイズ・容量の制限については、データの分割と複数属性の効果的な利用で制限を回避する
- 文字列型の制限については、ゼロ埋めと基準値の利用で制限を回避する
- 整合性の制限については、アプリケーション側で適切なオプションを利用することで回避する
- ドメイン名の制限については、ドメイン名のプレフィックスの利用やアカウント・リージョンを分けることで制限を回避する
次回はSimpleDBを用いたプログラミングについてAWS SDK for Javaを利用するケースを説明したいとおもいます。