インデックス作成ポリシーの検討
Cosmos DBでは、デフォルトの設定としてドキュメント内の全てのJSONプロパティに対してインデックスを作成するようになっており、これによってさまざまなクエリを用いても読み取り10msの性能(SLA)を担保できるように設計されています。
しかし、全てのJSONプロパティに対してインデックスを作成すると、その分インデクシングのオーバーヘッドも余分にかかることから、データ書き込み時の性能に影響を与えることになります。
インデックス作成ポリシーでは、インデックスの作成タイミングやインデックスを作成するプロパティの指定などを細かく調整することができます。
ユースケースに応じたインデックス作成ポリシーを適用することで、性能の改善とストレージ・RUを節約することができます。
なお、インデックス作成ポリシーはJSON形式でまとめられており、Azureポータル上から編集することができます。
Time To Liveの設定と同様に、「設定」メニューからポリシーを編集することができます。
インデックス作成ポリシーには、以下の3つの要素があり、それぞれの設定を最適化していく必要があります。
- インデックス作成モード
- インデックス化パスの指定
- インデックスのデータ型、種類
それぞれについて説明していきます。
インデックス作成モードの指定
インデックス作成モードとは、インデックスを作成するタイミングを設定する要素です。インデックスの作成タイミングにより、書き込みの性能と読み取りの整合性を調整することができます。
インデックス作成モードには以下の3種類が存在します。
(1)同期(Consistent)
整合性がデータベースアカウントで設定した一貫性レベルに準拠するため、読み取りの整合性を重視したいミッションクリティカルなアプリケーションに適しています。
(2)非同期(Lazy)
書き込み性能を重視したモードで、読み取りは結果整合性(Eventual:Cosmos DBの一貫性レベルのうち最も高速に動く)となります。バッチ処理など、書き込みと読み取りのタイミングが完全に分離されているユースケースに適しています。
(3)なし(None)
インデックスを作成しないモード。ドキュメントへのアクセス方法がIDによる検索のみに絞られるため、KVSとして利用するケースに適しています。IoT分野等での、センサーデータやログデータといった小さなデータを大量に保存する用途で、このモードが使われることがあります。
インデックス作成モードは、デフォルトでは同期モードに設定されています。
アプリケーションの特性から非同期モードやインデックス作成なしを選択しても問題がない場合は、インデックス作成モードを変更することでパフォーマンスを改善することができます。
インデックス化するパスの指定
Cosmos DBでは、JSONドキュメントの階層をツリーとしてモデル化し、インデックスを生成していきます。
ツリーに含まれるJSONドキュメントのプロパティから、インデックス作成するもの、あるいは除外するものを選択することができます
インデックス作成するツリーが少なければ少ないほど、書き込みの性能が上昇し、インデックス情報を保存する際のストレージ使用量を抑えることができます。
また、インデックス作成対象とするツリー(プロパティ)は、階層が深くなるほどインデックス作成時と検索時のコストがかかる傾向があるため、なるべくフラットなドキュメントとなるように意識しましょう。
インデックス化するパスが決まったら、次にそのパスに対してデータ型や種類といったインデックスの設定を行います。
インデックスのデータ型、種類
インデックスに設定できるデータ型には、文字列と数値型を表すString、Numberと、地図座標上での距離の計算等を行う空間クエリで使うPoint、Polygon、LineStringの5つの型が用意されています。
StringとNumberは、JSONの文字列型、数値型に準拠したデータ型です。Point、LineString、Polygon型については、それぞれ以下の通りです。
- Point:地図上のある1地点の座標を表す型
- LineString:2つ以上の座標を配列で持ち、直線を表現できる型
- Polygon:3つ以上の座標を配列で持ち、エリアを表現できる型
また、データ型とは別に、インデックスの種類を設定します。これによって、使用できるクエリが決まります。
インデックスの種類には、Hash、Range、Spatialの3種類が存在します。
Hashは、等価クエリをサポートします。等価クエリはWHERE句にて「=」演算子を使うクエリを指します。
Rangeは、等価クエリの他、範囲クエリとOrder Byクエリをサポートします。
範囲クエリは、「>、<、>=、<=、!=」の演算子を使ったクエリを実行でき、Order ByクエリはORDER BY句を使い結果をソートすることができるクエリです。
等価、範囲、Order Byクエリは、StringとNumberのデータ型のインデックスに対して設定することができます。
リスト3は等価、範囲、Order Byクエリを使った、SQLの簡単な例です。
-- 等価クエリ SELECT * FROM c WHERE c.auther = 'akiba' -- 範囲クエリ SELECT * FROM c WHERE c.age > 30 -- Order Byクエリ SELECT * FROM c ORDER BY c.birthDate
Spatialは、空間クエリをサポートします。空間クエリは座標を使った検索をサポートしており、例えば現在地から10km以内にあるコンビニを検索する、といった使い方ができます。対応するデータ型は、Point、LineString、Polygonです。
おわりに
今回は設計段階で考慮すべきポイントについて紹介しました。次回は実装編として、SDKを用いたドキュメントの操作方法を紹介します。