NoSQL ドライバーの機能比較



この記事では、さまざまなベンダーが提供する標準ベースのドライバーが、さまざまな NoSQL ユースケースをどのように処理するかを比較します。MongoDB をサンプルデータソースとして使用し、特定のテーブル内のすべてのデータを取得する単純なリクエストから、埋め込み配列を含む複雑なクエリまでを対象とします。

この比較では、MongoDB, Inc が提供する restaurants データセット(こちらからダウンロード可能)のインスタンスに対して各クエリを送信しています。以下に、データセット内のドキュメントの代表的なサンプルを示します。

比較するユースケース



サンプルドキュメント



{
  "_id" : ObjectId("5780046cd5a397806c3dab38"),
  "address" : {
    "building" : "1007",
    "coord" : [-73.856077, 40.848447],
    "street" : "Morris Park Ave",
    "zipcode" : "10462"
  },
  "borough" : "Bronx",
  "cuisine" : "Bakery",
  "grades" : [{
      "date" : ISODate("2014-03-03T00:00:00Z"),
      "grade" : "A",
      "score" : 2
    }, {
      "date" : ISODate("2013-09-11T00:00:00Z"),
      "grade" : "A",
      "score" : 6
    }, {
      "date" : ISODate("2013-01-24T00:00:00Z"),
      "grade" : "A",
      "score" : 10
    }, {
      "date" : ISODate("2011-11-23T00:00:00Z"),
      "grade" : "A",
      "score" : 9
    }, {
      "date" : ISODate("2011-03-10T00:00:00Z"),
      "grade" : "B",
      "score" : 14
    }],
  "name" : "Morris Park Bake Shop",
  "restaurant_id" : "30075445"
}


SELECT * FROM restaurants



従来のリレーショナルデータベースを操作する場合、特定のテーブル内のすべてのデータを取得する最も簡単な方法は、SELECT * FROM table クエリを送信することです。MongoDB のデータは従来のリレーショナルデータとは異なることが多いため、特定のドライバーがこのようなクエリをどのように処理するかを理解することが重要です。 以下に、デフォルトの接続プロパティを使用した各ドライバーの SELECT * ... クエリの結果を示します。

Competitor 1 のドライバーは、データベースの解析時に grades 配列と address オブジェクトを別々のテーブルとして解析します。Competitor 2 のドライバーは、grades 配列と address.coord 配列を別々のテーブルとして解析します。別々のテーブルを作成することで NoSQL データベース内のさまざまなデータタイプを区別するのに役立ちますが、親テーブルと子テーブルの両方からデータをクエリする際にはいくつかの欠点が生じる可能性があります。CData ドライバーは、デフォルトで最も多くのデータを公開し、address オブジェクトをフラット化し、grades 配列内の要素で利用可能なフィールドを取得します。

CData Software

_id address.building address.coord.0 address.coord.1 address.street address.zipcode borough cuisine name restaurant_id grades.0.date grades.0.grade grades.0.score
5780046cd5a397806c3dab38 1007 -73.856077 40.848447 Morris Park Ave 10462 Bronx Bakery Morris Park Bake Shop 30075445 2014-03-03T00:00:00.000Z A 2
5780046cd5a397806c3dab39 469 -73.961704 40.662942 Flatbush Avenue 11225 Brooklyn Hamburgers Wendy'S 30112340 2014-12-30T00:00:00.000Z A 8
5780046cd5a397806c3dab3a 351 -73.98513559999999 40.7676919 West 57 Street 10019 Manhattan Irish Dj Reynolds Pub And Restaurant 30191841 2014-09-06T00:00:00.000Z A 2
5780046cd5a397806c3dab3b 2780 -73.98241999999999 40.579505 Stillwell Avenue 11224 Brooklyn American Riviera Caterer 40356018 2014-06-10T00:00:00.000Z A 5

Competitor 1

BOROUGH RESTAURANT_ID _ID CUISINE NAME
Bronx 30075445 5780046CD5A397806C3DAB38 Bakery Morris Park Bake Shop
Brooklyn 30112340 5780046CD5A397806C3DAB39 Hamburgers Wendy'S
Manhattan 30191841 5780046CD5A397806C3DAB3A Irish Dj Reynolds Pub And Restaurant
Brooklyn 40356018 5780046CD5A397806C3DAB3B American Riviera Caterer

Competitor 2

_id address_building address_street address_zipcode borough cuisine name restaurant_id
5780046cd5a397806c3dab38 1007 Morris Park Ave 10462 Bronx Bakery Morris Park Bake Shop 30075445
5780046cd5a397806c3dab39 469 Flatbush Avenue 11225 Brooklyn Hamburgers Wendy'S 30112340
5780046cd5a397806c3dab3a 351 West 57 Street 10019 Manhattan Irish Dj Reynolds Pub And Restaurant 30191841
5780046cd5a397806c3dab3b 2780 Stillwell Avenue 11224 Brooklyn American Riviera Caterer 40356018


埋め込み配列を別テーブルとして扱う



サンプルデータでは、restaurants テーブルの各ドキュメントに、grades 要素内に埋め込みドキュメントの配列が含まれており、レストランが時間の経過とともに受け取ったさまざまなグレードを表しています。MongoDB のドキュメントによると、「埋め込みドキュメントは、単一のドキュメント構造内にデータを格納することで、データ間の関係をキャプチャします」。デフォルトでは、Competitor 1 と Competitor 2 のドライバーは、埋め込みドキュメントを別々のテーブルとしてのみ認識するスキーマを作成し(Competitor 1 は配列を仮想テーブル、Competitor 2 は子テーブルと呼びます)、grades テーブルが restaurants テーブルと外部キー関係を共有するテーブルスキーマを作成します。CData ドライバーは、埋め込みドキュメントを元のドキュメント内の要素として維持しながら、埋め込み値を別々のテーブルとして扱うこともできます。

スキーマの定義方法に関係なく、すべてのドライバーは JOIN クエリを実行して、2 つのテーブルから関連データを取得できます。このセクションでは、各グレードをレストランの名前と ID とともに単一の行として返すために各ドライバーが必要とするクエリと、クエリのデータを取得するのに要した時間を比較します。

期待される結果セット

以下に、プレースホルダーデータで埋められた各ドライバーの期待される結果セットを示します。

restaurant_id date grade score P_id
30075445 2014-03-03T00:00:00.000Z A 2 568c37b748ddf53c5ed98932
30075445 2013-09-11T00:00:00.000Z A 6 568c37b748ddf53c5ed98932
30075445 2013-01-24T00:00:00.000Z A 10 568c37b748ddf53c5ed98932
30075445 2011-11-23T00:00:00.000Z A 9 568c37b748ddf53c5ed98932
30075445 2011-03-10T00:00:00.000Z B 14 568c37b748ddf53c5ed98932

ドライバー別のクエリと時間

各グレードを個別の行として取得するために各ドライバーが必要とするクエリは比較的似ており、いずれも暗黙の JOIN を使用していますが、Competitor 1 と Competitor 2 のドライバーは、2 つのテーブル間の関係を識別するために WHERE 句の使用が必要であることに注意してください。CData ドライバーは、垂直フラット化(子配列が親テーブル内のフィールドとして認識されますが、別々のテーブルとして扱うこともできる)を使用して JOIN クエリを管理します。Competitor 1 と Competitor 2 のドライバーは、デフォルトで grades 配列を別々のテーブルとして扱います。これは、両方のテーブルからデータがメモリに読み込まれ、ドライバーがクライアントサイドで JOIN を実行することを意味します。

ドライバー 時間(秒) クエリ(約 1,000 万件のレストランの全グレードを返す)
CData Software 252.9 (+35% - +59%) SELECT [restaurants].[restaurant_id], [restaurants.grades].* FROM [restaurants.grades] JOIN [restaurants]
Competitor 1 341.5 SELECT restaurants_grades.*, restaurants.restaurant_id FROM restaurants_grades, restaurants WHERE restaurants._ID = restaurants_grades.restaurants_id
Competitor 2 401.2 SELECT restaurants_grades.*, restaurants.restaurant_id FROM restaurants_grades, restaurants WHERE restaurants._ID = restaurants_grades._id


埋め込み配列とサブドキュメントをテーブル要素として扱う



MongoDB ドキュメントには、個々の要素として埋め込み BSON/JSON オブジェクトや配列が含まれることがよくあります。このセクションでは、水平方向にフラット化されたデータセット、つまりテーブル内の各レストランの ID と最初の 5 つのグレードを取得するために各ドライバーが必要とするクエリを検証します。

期待される結果セット

以下に、プレースホルダーデータで埋められた各ドライバーの期待される結果セットを示します。

restaurant_id grades.0.grade grades.1.grade grades.2.grade grades.3.grade grades.4.grade
123456780 A A A A A
123456781 B B B B B
123456782 C C C C C

CData Software

CData のドライバーでは、上記のようなデータを取得するために自由形式のクエリを送信するだけで済みます。ドライバーは、個々の配列オブジェクトやサブドキュメント内のフィールドへのリクエストを解釈するためにドット記法を使用します。

SELECT
  [restaurant_id], [grades.0.grade], [grades.1.grade], [grades.2.grade], [grades.3.grade], [grades.4.grade]
FROM
  [restaurants]

Competitor 1

Competitor 1 のドライバーは、ドキュメントの配列を仮想テーブルとして解釈するため、レストランとグレードの両方のデータを取得するには JOIN クエリを実行する必要があります。このデータの解釈方法では、特定のレストランのグレードを単一の行で取得する簡単な方法がありません。

Competitor 2

Competitor 2 のドライバーも、ドキュメントの配列を別々のテーブルとして解釈します。Competitor 1 のドライバーと同様に、レストランとグレードの両方のデータを取得するには JOIN クエリを実行する必要があり、特定のレストランのグレードを単一の行で取得する簡単な方法がありません。

関連記事



  •  NoSQL ドライバー:パフォーマンス比較 - NoSQL データソースから大規模なデータセットをクエリおよび処理する際の、さまざまなベンダーのドライバーのパフォーマンスを比較します。
  •  CData NoSQL 概要 - NoSQL を操作する際に CData のドライバー技術を際立たせる機能について説明します。

始める準備はできましたか?

MongoDB 用ドライバーの詳細、または無料トライアルをダウンロード:

今すぐダウンロード