(57)【特許請求の範囲】
【請求項１】
第１のデータソースから取り出したオブジェクトの累積スキーマを動的に作成するように構成されたスキーマ推論モジュールであって、
前記取り出したオブジェクトのそれぞれは、（ｉ）データと、(ii)前記データを記述するメタデータと、を含み、
前記累積スキーマの動的作成は、前記取り出したオブジェクトの各オブジェクトについて、（ｉ）前記オブジェクトからスキーマを推論することと、(ii)前記推論されたスキーマに従って前記オブジェクトを記述するように、前記累積スキーマを選択的に更新することと、を含み、
前記スキーマ推論モジュールは、
前記取り出したオブジェクトのデータ型に関する統計を収集し、
前記データ型に関する統計に基づいて、前記取り出したオブジェクトのデータが正確に型付けされているかどうかを決定する、
ように構成されている、前記スキーマ推論モジュールと、
前記累積スキーマに従って、前記取り出したオブジェクトの前記データをデータ宛先システムに出力するように構成されたエクスポートモジュールと、
を備えるデータ変換システム。
【請求項２】
前記データ宛先システムは、データウェアハウスを含む、請求項１に記載のデータ変換システム。
【請求項３】
前記データウェアハウスは、関係データを記憶する、請求項２に記載のデータ変換システム。
【請求項４】
前記エクスポートモジュールは、前記累積スキーマを関係スキーマに変換し、前記関係スキーマに従って、前記取り出したオブジェクトの前記データを前記データウェアハウスに出力するように構成された、請求項３に記載のデータ変換システム。
【請求項５】
前記エクスポートモジュールは少なくとも１つの、
前記関係スキーマに行われた変更を反映するよう前記データウェアハウスのスキーマを更新するようにという前記データウェアハウスに対するコマンドを生成すること、
前記関係スキーマに従って、前記取り出したオブジェクトの前記データから少なくとも１つの中間ファイルを作成すること、
を実行するように構成され、
前記少なくとも１つの中間ファイルは、所定のデータウェアハウスフォーマットを有し、
前記エクスポートモジュールは、前記少なくとも１つの中間ファイルを前記データウェアハウスにバルクロードするように構成された、請求項４に記載のデータ変換システム。
【請求項６】
前記取り出したオブジェクトから前記データをカラム形式で記憶するように構成されたインデックスストアをさらに備える、請求項１〜５のいずれか１項に記載のデータ変換システム。
【請求項７】
前記エクスポートモジュールは、前記インデックスストアの前記記憶されたデータから、ローベースのデータを生成するように構成された、請求項６に記載のデータ変換システム。
【請求項８】
前記スキーマ推論モジュールは、時間値を前記取り出したオブジェクトの識別子にマップする時間インデックスを、前記インデックスストアに作成するように構成され、
前記取り出したオブジェクトの各取り出したオブジェクトについて、前記時間値は、（ｉ）前記取り出したオブジェクトの作成に対応するトランザクション時間と、
（ｉｉ）前記取り出したオブジェクトに対応する有効時間の少なくとも１つを表す、請求項６または７に記載のデータ変換システム。
【請求項９】
（ｉ）後に前記インデックスストアに記憶するために、追加のオブジェクトをキャッシュし、かつ、（ｉｉ）前記キャッシュのサイズが閾値に達したことに応答して前記インデックスストアにバルクロードするために、前記追加のオブジェクトをパッケージ化するように構成される書き込み最適化ストアをさらに備える、請求項６〜８のいずれか１項に記載のデータ変換システム。
【請求項１０】
前記スキーマ推論モジュールは：
前記取り出したオブジェクトの前記メタデータ、または
前記取り出したオブジェクトの前記データ、
の少なくとも１つに関する統計を収集するように構成され、
前記統計は、最低、最大、平均、及び、標準偏差の少なくとも１つを含む、請求項１から９のいずれか１項に記載のデータ変換システム。
【請求項１１】
前記第１のデータソースから関係データを受信し、かつ、前記スキーマ推論モジュールが使用する前記オブジェクトを生成するよう構成されたデータコレクタモジュールをさらに含み、
前記データコレクタモジュールは、（ｉ）前記関係データの各項目を取り出すためのテーブルを示す第１のカラムと、（ｉｉ）前記関係データの各項目に関連付けられたタイムスタンプを示す第２のカラムと、を作成することによって、前記関係データをイベント化するように構成された、請求項１〜１０のいずれか１項に記載のデータ変換システム。
【請求項１２】
所定の依存情報に従って、前記スキーマ推論モジュールと前記エクスポートモジュールにジョブの処理を割り当てるように構成されたスケジューリングモジュールをさらに備える、請求項１から１１のいずれか１項に記載のデータ変換システム。
【請求項１３】
前記エクスポートモジュールは、前記累積スキーマを複数のテーブルにパーティション化するように構成され、前記複数のテーブルの各テーブルは、前記取り出したオブジェクトに一緒に現れるカラムを含み、
前記エクスポートモジュールは、前記取り出したオブジェクトの対応するグループであって、それぞれ、識別子要素について異なる値を有するグループ、にあるカラムに従って、前記累積スキーマをパーティション化するように構成された、請求項１〜１２のいずれか１項に記載のデータ変換システム。
【請求項１４】
前記スキーマ推論モジュールは、前記取り出したオブジェクトのそれぞれについて、ソース識別子を記録し、
前記取り出したオブジェクトの各オブジェクトについて、前記ソース識別子は、前記第１のデータソースの固有の識別子と、前記第１のデータソース内の前記オブジェクトの位置と、を含む、請求項１〜１３のいずれか１項に記載のデータ変換システム。
【請求項１５】
データ分析システム操作方法であって、
オブジェクトをデータソースから取り出すことであって、前記取り出したオブジェクトの各オブジェクトは、（ｉ）データと、（ｉｉ）前記データを記述するメタデータと、を含む、前記取り出すことと、
前記取り出したオブジェクトの各オブジェクトについて、
（ｉ）前記オブジェクトの前記メタデータと、前記オブジェクトの前記データの要素の推論されたデータ型とに基づいて、前記オブジェクトからスキーマを推論することであって、前記オブジェクトのうちの少なくとも１つのオブジェクトについて推論されたスキーマは、前記オブジェクトのうちの他のオブジェクトについての他の推論されたスキーマとは異なる、前記推論することと、
（ｉｉ）（ａ）前記推論されたスキーマが記述する前記オブジェクトと、（ｂ）累積スキーマが記述する累積したオブジェクトのセットと、の両方を記述する統合スキーマを作成することと、
（ｉｉｉ）前記統合スキーマを前記累積スキーマとして記憶することと、
前記取り出したオブジェクトのデータ型に関する統計を収集することと、
前記データ型に関する前記統計に基づいて、前記取り出したオブジェクトの前記データが正確に型付けされているかどうかを決定することと、
前記取り出したオブジェクトのそれぞれの前記データをデータウェアハウスにエクスポートすることと、
によって、前記累積スキーマを動的に生成することと、
を含む方法。
【発明の詳細な説明】
【関連出願の相互参照】
【０００１】
本開示は、２０１４年３月１４日出願のＵＳ特許出願番号１４／２１３，９４１に基づいて優先権を主張し、２０１３年３月１５日出願のＵＳ仮特許出願番号６１／８００，４３２に基づいて利益を主張する。上記出願の全ての内容を、援用により本明細書に組み込むものとする。
【技術分野】
【０００２】
本開示は、スケーラブルな対話型データベースプラットフォームに関し、より詳細には、記憶や計算を組み込んだ半構造データのためのスケーラブルな対話型データベースプラットフォームに関する。
【背景技術】
【０００３】
本明細書における背景技術の記載は、開示の文脈を一般的に示すためである。ここに現在名を挙げた発明者らの研究については、この背景技術の欄に記載の範囲まで、及び、出願時に先行技術として見なされない可能性のある背景技術の記載の態様は、本開示に対する先行技術として明示的にも暗示的にも認められない。
【０００４】
従来のデータベースシステムは、基礎的ストレージバックエンドと緊密に一体化されたクエリ実行エンジンを特徴とする。基礎的ストレージバックエンドは、典型的には、ブロックアドレス指定可能な、計算能力を持たない永続記憶装置からなる。これらの装置（ハードディスクドライブ及び／または半導体ドライブ）の特徴は、（ａ）データに連続的にアクセスするか、ランダムにアクセスするかによって、大きく異なるアクセスタイム（ｂ）ブロックの粒度で設定された、一定の最小サイズを有するアクセスユニット（ｃ）メインメモリより(桁が違うほど)大幅に遅いアクセスタイム、である。これらの特徴は、ストレージバックエンドが、非自明な（non-trivial）計算の能力を持たないという前提と併せて、ストレージ管理からクエリ実行、クエリ最適化まで、データベースシステムの設計に重要な影響を与えてきた。
【０００５】
データベースは、本来、日々の企業活動を管理する操作可能なストアの役割を果たすものであった。データベース技術が、性能及びコストの両面で改善されるにつれて、企業においては、その後の分析のために、ますます大量の操作履歴と業務状態を保管することが必要になった。このような分析は、企業が、自社のプロセスを洞察し、最適化するのを支援して、競争力を与え、利益を増加させる。
【０００６】
データウェアハウジングは、これらの需要によって生じた。ビジネスデータは、構造化が進んでいることが多く、関係テーブルに容易に適合する。データウェアハウスは、本来、スケーラブルな関係データベースシステムで、このビジネスデータのオフライン分析に構造化クエリ言語（ＳＱＬ：ｓｔｒｕｃｔｕｒｅｄ  ｑｕｅｒｙ  ｌａｎｇｕａｇｅ）を提供する、また、ほとんどが読み取り用の作業負荷のために最適化されている。例えば、データウェアハウスは、Ｔｅｒａｄａｔａ等の従来のシステムや、Ｖｅｒｔｉｃａ、Ｇｒｅｅｎｐｌｕｍ、Ａｓｔｅｒ  Ｄａｔａ等の新しいベンダを含む。それらはＳＱＬインタフェース、インデックス、及び、高速のカラムアクセスを提供する。
【０００７】
典型的に、データウェアハウスには、様々なソースや操作システムから採集したデータが、例えば、毎晩または毎週など、定期的にロードされる。このデータから不要なデータを取り除き、キュレートし、１つのスキーマに統合し、ウェアハウスにロードするプロセスは、抽出、変換、ロード（ＥＴＬ）として知られている。ソースとデータの種類が増えるにつれて、ＥＴＬプロセスの複雑さも増す。適切なスキーマを定義し、入力データを所定のスキーマに一致させることを含む、ＥＴＬを成功裏に実施することは、専門家にとって数週間も数か月もかかることであり、また、変更を行うことは難しいまたは不可能な場合がある。ＥＴＬプロセスを支援するための、Ａｂｉｎｉｔｉｏ、Ｉｎｆｏｒｍａｔｉｃａ、Ｐｅｎｔａｈｏ等の多くのツールが市場に出ている。にもかかわらず、ＥＴＬプロセスは、一般に、面倒で、脆弱で、高価なままである。
【０００８】
データ分析市場は、ビジネスユーザが、アドホックに、反復してウェアハウスのデータを分析するのを容易にする多くのビジネスインテリジェンス及び視覚化ツールで溢れている。ビジネスインテリジェンスツールは、ウェアハウスデータの多次元の集合体を構築し、ユーザが、そのデータをナビゲートして、そのデータの様々なスライス及び投影を見るのを可能にする。例えば、ビジネスユーザは、製品カテゴリ、地域、店舗ごとの月間総売上が知りたいかもしれない。また、特定のカテゴリの週間売上を掘り下げたい場合もあり、全て集めて全国の売上を知りたいかもしれない。多次元の集合体は、オンライン分析処理（ＯＬＡＰ）キューブとも称してよい。Ｂｕｓｉｎｅｓｓ  ＯｂｊｅｃｔｓやＣｏｇｎｏｓ等の多くのビジネスインテリジェンス（ＢＩ）ツールは、このような分析を可能にし、キューブにクエリを行うための多次元式（ＭＤＸ）と呼ばれる言語をサポートする。また、ビジネスユーザがこれらのキューブやデータウェアハウスに直観的にナビゲートできるようにする、ＭｉｃｒｏＳｔｒａｔｅｇｙ、Ｔａｂｌｅａｕ、Ｓｐｏｔｆｉｒｅ等の多くの視覚化ツールがある。
【０００９】
最近になって、企業が分析したいデータの種類が変わってきた。従来の実店舗だけによる企業が、オンライン化して、新しいオンラインビジネス形態になると、それらの企業は、ＧｏｏｇｌｅやＹａｈｏｏ等のトップ企業に殺到している種類のデータを分析する必要がある。そのデータには、ウェブページ、ページビューのログ、クリックストリーム、リッチサイトサマリー（ＲＳＳ）フィード、アプリケーションログ、アプリケーションサーバログ、システムログ、トランザクションログ、センサデータ、ソーシャルネットワークフィード、ニュースフィード、ブログポスト等のデータが含まれる。
【００１０】
これらの半構造データは、従来のウェアハウスにあまり適合しない。これらの半構造データは、ある特有の構造を有し、その構造には一貫性がない場合がある。その構造は、経時的に素早く変化し得るし、ソースに応じて異なり得る。構造は、当然ながら、表形式ではないので、ユーザがこれらのデータに対して実行したい、クラスタリング、分類、予測などの分析は、ＳＱＬで表すのは容易ではない。これらのデータを有効に利用するための既存のツールは、面倒で、不十分である。
【００１１】
結果として、新しい高度にスケーラブルなストレージ及び分析プラットフォーム、Ｈａｄｏｏｐが現れた。Ｈａｄｏｏｐは、ウェブクロールや検索を管理するためにＧｏｏｇｌｅで実施されている技術から着想を得たものである。要するに、Ｈａｄｏｏｐは、データを確実に記憶するためのクラスタファイルシステムであるＨａｄｏｏｐ分散ファイルシステム（ＨＤＦＳ：Ｈａｄｏｏｐ  Ｄｉｓｔｒｉｂｕｔｅｄ  Ｆｉｌｅ  Ｓｙｓｔｅｍ）と、より複雑な分析をサポートする基本的な平行分析エンジンＭａｐＲｅｄｕｃｅと、を提供する。これらの要素から始まって、Ｈａｄｏｏｐエコシステムは、インデックス付のオペレーショナルストアであるＨＢａｓｅや、ＭａｐＲｅｄｕｃｅに依存する新しいクエリインタフェースであるＰｉｇやＨｉｖｅを備えるようになった。
【００１２】
Ｈｉｖｅは、クエリ最適化、キャッシュ、及び、インデックス付けのために従来のウェアハウスで見られた最適化なしに、Ｈａｄｏｏｐにクエリ層を追加するＡｐａｃｈｅプロジェクトである。その代わり、Ｈｉｖｅは、単に、（Ｈｉｖｅ−ＱＬと呼ばれる)ＳＱＬのような言語のクエリをＭａｐＲｅｄｕｃｅジョブに変え、Ｈａｄｏｏｐクラスタに対して実行する。従来のビジネスユーザにとって、Ｈｉｖｅには３つの大きな問題がある。Ｈｉｖｅは、標準的ＳＱＬをサポートしておらず、動的スキーマも持たない。さらに、各Ｈｉｖｅクエリは、全てのソースデータを再度、構文解析するＭａｐＲｅｄｕｃｅジョブを必要とし、また、ソースデータを複数回パスすることが必要な場合が多いので、Ｈｉｖｅは、対話型クエリを可能にするほど高速ではない。
【００１３】
Ｉｍｐａｌａは、Ｃｌｏｕｄｅｒａ社のＨａｄｏｏｐの実装における、Ｈｉｖｅ−ＱＬクエリのためのリアルタイムエンジンである。Ｉｍｐａｌａは、Ｈｉｖｅのシーケンスファイルの分析を提供する、また、最終的には、ネストされたモデルをサポートし得る。しかしながら、Ｉｍｐａｌａは、動的スキーマを持たず、ユーザは、クエリするデータについて、前もってスキーマを提供する必要がある。
【００１４】
Ｐｉｇは、別のＡｐａｃｈｅプロジェクトで、Ｈａｄｏｏｐのログファイルの処理のためのスキーマフリーのスクリプト言語を提供する。Ｐｉｇは、Ｈｉｖｅ同様、全てをマップリデュースジョブに翻訳する。同様に、Ｐｉｇは、インデックスを利用せず、対話性を求めるには速さが十分でない。
【００１５】
Ｊａｑｌは、ジェイソン（ＪＳＯＮ：ＪａｖａＳｃｒｉｐｔ（登録商標）  Ｏｂｊｅｃｔ  Ｎｏｔａｔｉｏｎ）ログを分析するための（ＳＱＬのような宣言型言語とは違った)スキーマフリーの宣言型言語である。Ｐｉｇ同様、Ｊａｑｌは、Ｈａｄｏｏｐでマップリデュースプログラムにコンパイルされるので、対話に適したスピードでないことを含めて、同じ欠点を多く共有する。
【００１６】
Ｈａｄｏｏｐ自体は、かなり速く普及しつつあり、クラウドで容易に手に入る。Ａｍａｚｏｎは、弾力的なマップリデュースを提供しており、クラウドで実行するＨａｄｏｏｐのＭａｐＲｅｄｕｃｅの実装と同じくらい有効であると思われる。Ａｍａｚｏｎのクラウドベースのシンプルストレージサービス（Ｓ３：Ｓｉｍｐｌｅ  Ｓｔｏｒａｇｅ  Ｓｅｒｖｉｃｅ)に記憶されたデータを処理し、結果をＳ３に出力する。
【００１７】
Ｈａｄｏｏｐエコシステムの長所は、３つある。一つ目は、システムは、非常に大きいサイズにスケールされるので、任意のデータ型を記憶できる。二つ目は、従来のウェアハウスに比較して非常にコストが安い(２０分の一ほど)。三つ目は、オープンソースなので、単一のベンダに拘束されない。ユーザは、適切なジョブに適切なツールを選ぶ能力を欲しており、システム間のデータ移動を避けて、ジョブを完了したい。Ｈａｄｏｏｐはフレキシブルではあるが、Ｈａｄｏｏｐの使用には、深い知識を持った熟練したアドミニストレータ及びプログラマが必要であり、見つけるのが難しい。さらに、Ｈａｄｏｏｐは、対話には遅すぎる。最も簡単なクエリでさえ、実行に数分から数時間かかる。
【００１８】
Ｄｒｅｍｍｅｌは、Ｇｏｏｇｌｅ内部で開発されたツールで、ネスト関係または半構造データに対するＳＱＬベースの分析クエリを提供する。元のバージョンは、ＰｒｏｔｏＢｕｆフォーマットのデータを扱っていた。Ｄｒｅｍｍｅｌでは、ユーザは、全てのレコードについて、前もってスキーマを定義することが必要である。ＢｉｇＱｕｅｒｙは、Ｄｒｅｍｍｅｌをクラウドベースに商業化したもので、ＣＳＶフォーマットやＪＳＯＮフォーマットを取り扱えるように拡張されている。Ｄｒｉｌｌは、Ｄｒｅｍｍｅｌのオープンソースバージョンである。
【００１９】
Ａｓｔｅｒｉｘは、ＪＳＯＮの一般化である抽象データモデル（ＡＤＭ）及び注釈クエリ言語（ＡＱＬ：ａｎｎｏｔａｔｉｏｎ  ｑｕｅｒｙ  ｌａｎｇｕａｇｅ）を使用する半構造データを管理、分析するためのシステムである。Ａｓｔｅｒｉｘは、標準ＳＱＬをサポートせず、本開示によってもたらされる高速アクセスも有さない。
【発明の概要】
【００２０】
データ変換システムは、スキーマ推論モジュールとエクスポートモジュールとを含む。スキーマ推論モジュールは、第１のデータソースから取り出したオブジェクトについて累積スキーマを動的に作成するように構成される。取り出した各オブジェクトは、（ｉ）データと、（ｉｉ）そのデータを記述するメタデータとを含む。累積スキーマの動的な作成は、取り出したオブジェクトの各オブジェクトについて、（ｉ）オブジェクトからスキーマを推論すること（ｉｉ）推論したスキーマに従ってオブジェクトを記述するように累積スキーマを選択的に更新すること、を含む。エクスポートモジュールは、取り出したオブジェクトのデータを、累積スキーマに従ってデータ宛先システムに出力するように構成される。
【００２１】
他の特徴としては、データ宛先システムは、データウェアハウスを含む。他の特徴としては、データウェアハウスは、関係データを記憶する。他の特徴としては、エクスポートモジュールは、累積スキーマを関係スキーマに変換し、関係スキーマに従って、取り出したオブジェクトのデータをデータウェアハウスに出力するように構成される。他の特徴としては、エクスポートモジュールは、関係スキーマに行われた変更を反映するようにデータウェアハウスのスキーマを更新するようにというデータウェアハウスへのコマンドを生成するように構成される。
【００２２】
他の特徴としては、エクスポートモジュールは、関係スキーマに従って、取り出したオブジェクトのデータから、少なくとも１つの中間ファイルを作成するように構成される。他の特徴としては、少なくとも１つの中間ファイルは、所定のデータウェアハウスフォーマットを有する。他の特徴としては、エクスポートモジュールは、少なくとも１つの中間ファイルをデータウェアハウスにバルクロードするように構成される。他の特徴としては、インデックスストアは、取り出したオブジェクトからのデータをカラム形式で記憶するように構成される。他の特徴としては、エクスポートモジュールは、インデックスストアに記憶されたデータからローベースのデータを生成するように構成される。他の特徴としては、スキーマ推論モジュールは、インデックスストア内に、取り出したオブジェクトの識別子に時間値をマップする時間インデックスを作成するように構成される。
【００２３】
他の特徴としては、取り出したオブジェクトの各オブジェクトについて、時間値は（ｉ）取り出したオブジェクトの作成に該当するトランザクション時間、または、（ｉｉ）取り出したオブジェクトに該当する有効時間の少なくとも１つを示す。他の特徴としては、書き込み最適化ストアは、（ｉ）後にインデックスストアに記憶するために追加のオブジェクトをキャッシュし、（ｉｉ）キャッシュサイズが閾値に達したことに応答して、インデックスストアにバルクロードするために、追加のオブジェクトをパッケージ化するように、構成される。他の特徴としては、スキーマ推論モジュールは、取り出したオブジェクトのメタデータに関する統計を収集するように構成される。他の特徴としては、スキーマ推論モジュールは、取り出したオブジェクトのデータ型に関する統計を収集するように構成される。他の特徴としては、スキーマ推論モジュールは、データ型に関する統計に応答して、取り出したオブジェクトの一部のデータを型変換するように構成される。
【００２４】
他の特徴としては、スキーマ推論モジュールは、データ型の統計に応答して、取り出したオブジェクトの一部のデータを不正確に型付けされている可能性があるとしてユーザに報告するように構成される。他の特徴としては、スキーマ推論モジュールは、取り出したオブジェクトのデータに関する統計を収集するように構成される。他の特徴としては、統計は、最小、最大、平均、及び、標準偏差の少なくとも１つを含む。他の特徴としては、データコレクタモジュールは、第１のデータソースから関係データを受信し、スキーマ推論モジュールが使用するオブジェクトを生成するように構成される。他の特徴としては、データコレクタモジュールは、（ｉ）関係データの各項目を取り出すためのテーブルを示す第１のカラムと、（ｉｉ）関係データの各項目に関連付けられたタイムスタンプを示す第２のカラムとを作成することによって、関係データをイベント化するように構成される。
【００２５】
他の特徴としては、スケジューリングモジュールは、所定の依存情報に従って、ジョブの処理をスキーマ推論モジュールとエクスポートモジュールに割り当てるように構成される。他の特徴としては、エクスポートモジュールは、累積スキーマを複数のテーブルにパーティション化するように構成される。他の特徴としては、複数のテーブルの各テーブルは、取り出したオブジェクト内に一緒に現れるカラムを含む。他の特徴としては、エクスポートモジュールは、識別子要素について異なる値を有する、取り出したオブジェクトのグループに該当するカラムに従って、累積スキーマをパーティション化するように構成される。他の特徴としては、スキーマ推論モジュールは、取り出した各オブジェクトのソース識別子を記録する。他の特徴としては、取り出したオブジェクトの各オブジェクトについて、ソース識別子は、第１のデータソースの固有の識別子と、第１のデータソース内のオブジェクトの位置とを含む。
【００２６】
データ変換システム操作方法は、第１のデータソースから取り出したオブジェクトについて動的に累積スキーマを作成することを含む。取り出した各オブジェクトは、（ｉ）データと（ｉｉ）そのデータを記述するメタデータとを含む。累積スキーマの動的な作成は、取り出したオブジェクトの各オブジェクトについて、（ｉ）オブジェクトからスキーマを推論することと（ｉｉ）推論したスキーマに従ってオブジェクトを記述するように累積スキーマを選択的に更新すること、を含む。方法は、累積スキーマに従って、取り出したオブジェクトのデータをデータ宛先システムに出力することをさらに含む。
【００２７】
他の特徴としては、データ宛先システムは、データウェアハウスを含む。他の特徴としては、データウェアハウスは、関係データを記憶する。方法は、累積スキーマを関係スキーマに変換することと、関係スキーマに従って、取り出したオブジェクトのデータをデータウェアハウスに出力することと、をさらに含む。方法は、関係スキーマに行われた変更を反映するようにデータウェアハウスのスキーマを更新するようにというデータウェアハウスへのコマンドを生成することをさらに含む。
【００２８】
方法は、関係スキーマに従って、取り出したオブジェクトのデータから少なくとも１つの中間ファイルを作成することをさらに含む。他の特徴としては、少なくとも１つの中間ファイルは、所定のデータウェアハウスフォーマットを有する。方法は、少なくとも１つの中間ファイルをデータウェアハウスにバルクロードすることをさらに含む。方法は、取り出したオブジェクトからのデータを、カラム形式でインデックスストアに記憶することをさらに含む。方法は、インデックスストアに記憶されたデータからローベースのデータを生成することをさらに含む。
【００２９】
方法は、インデックスストアに、取り出したオブジェクトの識別子に時間値をマップする時間インデックスを作成することをさらに含む。他の特徴としては、取り出したオブジェクトの各オブジェクトについて、時間値は、（ｉ）取り出したオブジェクトの作成に該当するトランザクション時間、または、（ｉｉ）取り出したオブジェクトに該当する有効時間の少なくとも１つを示す。
【００３０】
方法は、後にインデックスストアに記憶するために追加のオブジェクトをキャッシュすることと、キャッシュサイズが閾値に達したことに応答して、インデックスストアへのバルクロードのために追加のオブジェクトをパッケージ化すること、とをさらに含む。方法は、取り出したオブジェクトのメタデータに関する統計を収集することをさらに含む。方法は、取り出したオブジェクトのデータ型に関する統計を収集することをさらに含む。
【００３１】
方法は、データ型に関する統計に応答して、取り出したオブジェクトの一部のデータを型変換することをさらに含む。方法は、データ型に関する統計に応答して、取り出したオブジェクトの一部のデータを不正確に型付けされている可能性があるとしてユーザに報告することをさらに含む。方法は、取り出したオブジェクトのデータに関する統計を収集することをさらに含む。他の特徴としては、統計は、最小、最大、平均、及び、標準偏差の少なくとも１つを含む。
【００３２】
方法は、第１のデータソースから関係データを受信することと、動的作成によって、使用するオブジェクトを生成することとを、さらに含む。方法は、（ｉ）関係データの各項目を取り出すためのテーブルを示す第１のカラムと、（ｉｉ）関係データの各項目に関連付けられたタイムスタンプを示す第２のカラムとを作成することによって、関係データをイベント化することをさらに含む。方法は、所定の依存情報に従って、動的な作成及びエクスポートに該当するジョブの処理を割り当てることをさらに含む。
【００３３】
方法は、累積スキーマを複数のテーブルにパーティション化することをさらに含む。他の特徴としては、複数のテーブルの各テーブルは、取り出したオブジェクトに一緒に現れるカラムを含む。方法は、識別子要素について、それぞれ、異なる値を有する取り出したオブジェクトの対応するグループで見つけられるカラムに従って、累積スキーマをパーティション化することをさらに含む。方法は、取り出した各オブジェクトのソース識別子を記憶することをさらに含む。他の特徴としては、取り出したオブジェクトの各オブジェクトについて、ソース識別子は、第１のデータソースの固有の識別子と、第１のデータソース内のオブジェクトの位置とを含む。
【００３４】
データ分析システム操作方法は、データソースからオブジェクトを取り出すことを含む。取り出した各オブジェクトは、（ｉ）データと、（ｉｉ）そのデータを記述するメタデータとを含む。方法は、取り出したオブジェクトの各オブジェクトについて、（ｉ）オブジェクトのメタデータとオブジェクトのデータの要素の推論されたデータ型とに基づいて、オブジェクトからスキーマを推論することと、（ｉｉ）（ａ）推論されたスキーマによって記述されたオブジェクトと、（ｂ）累積スキーマによって記述された累積したオブジェクトのセットと、の両方を記述する統合スキーマを作成することと、（ｉｉｉ）統合スキーマを累積スキーマとして記憶することとによって、累積スキーマを動的に作成することをさらに含む。方法は、取り出した各オブジェクトのデータをデータウェアハウスにエクスポートすることをさらに含む。
【００３５】
他の特徴としては、方法は、累積スキーマを関係スキーマに変換することをさらに含み、エクスポートは、関係スキーマに従って行われる。他の特徴としては、動的な作成は、取り出したオブジェクトを通る第１のパス中に行われ、エクスポートは、取り出したオブジェクトを通る第２のパス中に行われる。他の特徴としては、方法は、取り出した各オブジェクトのデータをインデックスストレージサービスに記憶することをさらに含み、取り出した各オブジェクトのデータは、インデックスストレージサービスからデータウェアハウスにエクスポートされる。
【００３６】
他の特徴としては、エクスポートは、インデックスストレージサービスから、所定のデータウェアハウスフォーマットを有する中間ファイルを少なくとも１つ作成することと、少なくとも１つの中間ファイルをデータウェアハウスにバルクロードすることと、を含む。他の特徴としては、方法は、累積スキーマを関係スキーマに変換することをさらに含み、少なくとも１つの中間ファイルは、関係スキーマに従って作成される。他の特徴としては、方法は、グラフィカルユーザインタフェースを介してユーザからクエリを受信することと、（ｉ）インデックスストレージサービスに記憶されたデータと、（ｉｉ）データウェアハウスから返信された結果、の少なくとも１つに基づいて、クエリに応答することと、をさらに含む。
【００３７】
他の特徴としては、方法は、結果を取得するために、クエリをデータウェアハウスに渡すことをさらに含む。他の特徴としては、方法は、グラフィカルユーザインタフェースを介して最初の結果をユーザに表示することと、クエリの実行が続いている間、グラフィカルユーザインタフェースの結果を反復的に更新することと、をさらに含む。他の特徴としては、方法は、グラフィカルユーザインタフェースを介してユーザからクエリを受信することと、データウェアハウスから返信された結果に基づいてクエリに応答することと、をさらに含む。他の特徴としては、方法は、グラフィカルユーザインターフェースを介してユーザからクエリを受信することと、グラフィカルユーザインタフェースでユーザに最初の結果を表示することと、クエリの実行が続く間、グラフィカルユーザインタフェースで結果を反復的に更新することと、をさらに含む。他の特徴としては、グラフィカルユーザインタフェースで結果を更新することは、少なくとも１つのデータチャートの少なくとも１つの軸のスケーリングを更新することを含む。
【００３８】
他の特徴としては、方法は、グラフィカルユーザインタフェースを介して累積スキーマをユーザに表示することと、追加データがデータソースから取り出されると、累積スキーマを更新することと、更新された累積スキーマを反映するようにグラフィカルユーザインタフェースを選択的に更新することと、をさらに含む。他の特徴としては、方法は、ユーザインタフェースにおいて、更新された累積スキーマの変更された項目を視覚的に区別することをさらに含む。他の特徴としては、方法は、新しいオブジェクトがデータソースから取得可能になるのに応答して、取り出し、動的な作成、及び、エクスポートを繰り返すことをさらに含む。他の特徴としては、方法は、エクスポートを繰り返す前に、前回のエクスポートの後、累積スキーマが変更されたか否かを決定することと、累積スキーマが変更されたと決定したことに応答して、累積スキーマの変更を反映するようにデータウェアハウスのスキーマを更新するようにという、少なくとも１つのコマンドをデータウェアハウスに送信することとを、さらに含む。
【００３９】
本開示は、非一時的コンピュータ可読媒体に記憶された命令として具体化された、上記方法の各特徴をさらに包含する。
【図面の簡単な説明】
【００４０】
詳細な説明及び添付の図面から、より完全に本開示を理解されよう。
【図１Ａ】クラウドリソースを活用する、半構造データのためのスケーラブルな分析プラットフォームのネットワークアーキテクチャの例である。
【図１Ｂ】ユーザエンドのサーバ機器を備えた、半構造データのためのスケーラブルな分析プラットフォームのネットワークアーキテクチャの例である。
【図１Ｃ】データウェアハウスを用いた、スケーラブルな分析プラットフォームのネットワークアーキテクチャの例である。
【図１Ｄ】サーバシステムを示す機能ブロック図である。
【図２Ａ】半構造データのためのスケーラブルな分析プラットフォームの例を示す機能ブロック図である。
【図２Ｂ】データウェアハウスを実装するスケーラブルな分析プラットフォームの例を示す機能ブロック図である。
【図２Ｃ】データウェアハウスと、ハイブリッドクエリエグゼキュータとを実装するスケーラブルな分析プラットフォームの例を示す機能ブロック図である。
【図２Ｄ】ユーザインタフェースを実装する例を示す機能ブロック図である。
【図２Ｅ】半構造データのためのスケーラブルな分析プラットフォームのクエリシステムの例を示す機能ブロック図である。
【図２Ｆ】データウェアハウスを用いたクエリシステムの例を示す機能ブロック図である。
【図３】採集したデータを組み込む方法の例を示すフローチャートである。
【図４】スキーマ推論方法の例を示すフローチャートである。
【図５】２つのスキーマをマージする方法の例を示すフローチャートである。
【図６】スキーマを折り畳む方法の例を示すフローチャートである。
【図７】インデックスにデータをポピュレートする方法の例を示すフローチャートである。
【図８】マップ装飾を行う方法の例を示すフローチャートである。
【図９】ＪＳＯＮスキーマから関係スキーマを作成する方法の例を示すフローチャートである。
【図１０Ａ】データウェアハウスを用いた、データ採集プロセスの例を示すフローチャートである。
【図１０Ｂ】データウェアハウスを用いた、データ採集プロセスの例を示すフローチャートである。
【図１１】データウェアハウスを用いた場合、新しいデータに応答して更新を行う例を示すフローチャートである。
【図１２】ユーザインタフェース操作の例を示すフローチャートである。
【図１３Ａ】ユーザインタフェースの実装例を示すスクリーンショットである。
【図１３Ｂ】ユーザインタフェースの実装例を示すスクリーンショットである。
【図１３Ｃ】ユーザインタフェースの実装例を示すスクリーンショットである。
【図１３Ｄ】ユーザインタフェースの実装例を示すスクリーンショットである。
【図１３Ｅ】ユーザインタフェースの実装例を示すスクリーンショットである。
【図１４】複数のデータの宛先を提供するスケーラブルな分析プラットフォームの例を示す機能ブロック図である。
【図１５】カラム指向のレポジトリからのバルクローエクスポートを示すグラフィック図である。
【図１６Ａ】本開示の原理に係る、抽出、変換、ロードプロセスの構成要素を並列化するための依存関係図である。
【図１６Ｂ】本開示の原理に係る、抽出、変換、ロードプロセスの構成要素を並列化するための依存関係図である。    図中、参照番号は、類似及び／または同一の要素を特定するために再使用されてよい。
【発明を実施するための形態】
【００４１】
本開示は、半構造データにクエリを行うための構造化クエリ言語（ＳＱＬ）対応インタフェースを提供できる分析プラットフォームを記載する。説明目的のために、半構造データは、ＪＳＯＮ（ＪａｖａＳｃｒｉｐｔ  Ｏｂｊｅｃｔ  Ｎｏｔａｔｉｏｎ）フォーマットで表されるが、本開示の原理に従った他の自己記述的な半構造フォーマットも使用することができる。ソースデータは、自己記述的である必要はない。プロトコルバッファの場合のように、記述は、データから切り離すことができる。データにタグを付けるための、規則、ヒューリスティック、または、ラッパー関数がある限り、任意の入力データをＪＳＯＮフォーマットに類似したオブジェクトに変換することができる。
【００４２】
本開示に係る、分析プラットフォームの様々な実装において、以下の長所の一部またはすべてが実現される。
【００４３】
スピード
分析プラットフォームは、アドホックで、探索的な、対話型分析をサポートするための高速クエリ応答時間を提供する。ユーザは、クエリを発行し、その日か翌日に結果を見るために戻る必要なく、このシステムを用いて、データに隠れた洞察を素早く発見することができる。分析プラットフォームは、採集したデータを全てインデックスで記憶するインデックスストアに依存しており、高速応答時間を可能にしている。
【００４４】
ＢｉｇＩｎｄｅｘ（ＢＩ）とＡｒｒａｙＩｎｄｅｘ（ＡＩ）という２つの主インデックスを使用している。これらのインデックスに関しては、以下に詳しく記載する。これらは、経路インデックスと、カラム指向ストアの中間物である。カラム指向ストアのように、これらのインデックスによって、クエリは関連するフィールドのデータのみを取り出すことができ、Ｉ／Ｏ（入力／出力）需要を減らして、性能を改善する。しかしながら、カラムストアとは違って、これらのインデックスは、複雑なネストされたオブジェクトや、多くのフィールドを持つコレクションに適している。他のアクセスパターンに関して、分析プラットフォームエンジンは、ＶａｌｕｅＩｎｄｅｘ（ＶＩ）を含む補助インデックスを保持している。これについては、以下により詳細に記載する。従来のデータベースインデックスのように、ＶａｌｕｅＩｎｄｅｘは、特定のフィールドの値または値の範囲に、高速な対数的アクセスを提供する。これらのインデックスは、クエリを満足させるために取り出す必要のあるデータを大幅に低減して、応答時間を改善する。
【００４５】
動的スキーマ
分析プラットフォームは、データ自体からスキーマを推論するので、ユーザは、推測的に予測スキーマを知る必要はなく、データがロードされる前にスキーマを予め宣言する必要もない。半構造データは、経時的に、また、ソースが異なることによって構造が変わり得る。よって、エンジンは、データが到着すると、動的に、そのデータからスキーマ（または、構造)を計算し、更新する。この計算されたスキーマに基づいた関係スキーマがユーザに提示され、ユーザはそれを用いて、クエリを構成する。
【００４６】
クエリを行う前にプログラマがデータコレクションスキーマを指定する必要があった以前の分析エンジンとは違って、本プラットフォームは、全ての採集したオブジェクト間で基礎的スキーマを計算（または、推論）する。動的スキーマ特性のために、非常にフレキシブルである。ソースデータを生成するアプリケーションは、アプリケーションが進化するにつれて、構造を変更することができる。分析者は、スキーマが期間ごとにどのように異なるかを指定する必要なく、様々な期間からデータを集計し、クエリを行うことができる。さらに、数か月かかる場合があり、スキーマに適合しないデータを除く必要があることも多い、グローバルスキーマの設計、施行を行う必要がない。
【００４７】
「スキーマフリー」とも記載されることがあるＭａｐＲｅｄｕｃｅやＰｉｇのような他の分析システムには、２つの大きな欠点がある。一つ目は、データにクエリを行うためには、推論されたスキーマをユーザに自動的に提示するのではなく、ユーザにスキーマを知らせる必要がある。二つ目は、あらゆるクエリに関して、オブジェクト及びオブジェクトの構造を構文解析し、解釈する。一方、分析プラットフォームは、ロード時に、オブジェクトを構文解析し、インデックスを付ける。これらのインデックスによって、上述のように、その後のクエリが、はるかに高速に実行できる。以前のエンジンは、基礎的なデータから正確で簡潔なスキーマを自動的に推論しない。
【００４８】
ＳＱＬ
分析プラットフォームは、標準ＳＱＬクエリインタフェース（例えば、ＡＮＳＩ  ＳＱＬ  ２００３に対応したインタフェース）を公開するので、ユーザは、既存のＳＱＬツール（例えば、報告ツール、視覚化ツール、及び、ＢＩツール)及び専門知識を活用することができる。結果として、ＳＱＬまたはＳＱＬツールを熟知したビジネスユーザは、データウェアハウスをロードする必要なく、半構造データに直接アクセスやクエリを行うことができる。従来のＳＱＬベースツールは、ＪＳＯＮや他の半構造データフォーマットを扱わないので、分析プラットフォームは、ＪＳＯＮオブジェクトの計算されたスキーマの関係ビューを提示する。分析プラットフォームは、正規化ビューを提示し、最適化を組み込んで、ビューのサイズを管理する。関係ビューは、スキーマで幾つかのテーブルを提示してよいが、これらのテーブルは必ずしも具体化される必要はない。
【００４９】
半構造データをテーブル形式で表現することにより良く対応するために、分析プラットフォームは、「マップ」オブジェクトを自動で識別することができる。マップは、フィールド名及び値の両方を検索、クエリすることができるオブジェクト（または、ネストされたオブジェクト）である。例えば、あるオブジェクトは、フィールド名としての日付と、値に関してはページビューのような統計を含んでよい。関係ビューにおいては、マップは、別個のテーブルに抽出され、キーはキーカラムに、値は値カラムにとなるように、データは、ピボットされる。
【００５０】
スケール及び弾力性
分析プラットフォームは、大きいデータセットサイズを取り扱うためにスケーリングされる。分析プラットフォームは、内部データ構造と処理を、独立ノードに、自動的に、動的に分散させることができる。
【００５１】
分析プラットフォームは、仮想「クラウド」環境のために、設計、構築される。仮想「クラウド」環境は、Ａｍａｚｏｎウェブサービス等のパブリッククラウドや、ユーザの組織が管理、または、Ｒａｃｋｓｐａｃｅ等のサードパーティが提供する、仮想サーバ環境等のプライベートクラウドを含む。シンプルストレージサービス（Ｓ３：Ｓｉｍｐｌｅ  Ｓｔｏｒａｇｅ  Ｓｅｒｖｉｃｅ）、エラスティック計算クラウド（ＥＣ２：Ｅｌａｓｔｉｃ  Ｃｏｍｐｕｔｅ  Ｃｌｏｕｄ）、及び、エラスティックブロックストレージ（ＥＢＳ：Ｅｌａｓｔｉｃ  Ｂｌｏｃｋ  Ｓｔｏｒａｇｅ）を含む、Ａｍａｚｏｎウェブサービスの様々な構成要素を活用することができる。分析プラットフォームは、弾力的（エラスティック）である。つまり、分析プラットフォームは、需要に応じて、任意のサイズにスケールアップもスケールダウンもでき、内部のデータ構造を、Ａｍａｚｏｎ  Ｓ３等の長期のストアに記憶することによって、ハイバネートさせることができる。分析プラットフォームは、また、マルチテナンシー及びマルチユーザサポートを有する。
【００５２】
分析プラットフォームは、プロキシ、メタデータサービス、クエリエグゼキュータ、及び、ストレージサービスの４つの構成要素を有するサービスベースのアーキテクチャを用いる。分析プラットフォームエンジンをスケーリングして、より大きいデータセットをサポートし、より高速な応答を提供し、かつ、より多くのユーザをサポートするために、実行エンジンを並列化し、ストレージサービスを、独立した、低コストのサーバノード全体でパーティション化する。これらのノードは、ホスト環境において、実サーバであってもよく、仮想サーバであってもよい。エグゼキュータとストレージサービスは、分離されているので、独立してスケーリングすることができる。この分離され、スケールアウトされたアーキテクチャによって、ユーザは、ＡＷＳのようなクラウド環境が提供するストレージと計算に関するオンデマンドの弾力性を活用することができる。
【００５３】
ストレージサービスは、様々なパーティション化戦略を備えて構成可能である。さらに、基礎的データ構造(インデックス及びメタデータ)は、使用中でないシステムをハイバネートさせるためにＡｍａｚｏｎ  Ｓ３等の長期のストレージに移すことができ、コストを削減することができる。
【００５４】
同期
分析プラットフォームは、その内容を、Ｈａｄｏｏｐ分散ファイルシステム（ＨＤＦＳ）、Ａｍａｚｏｎシンプルストレージサービス（Ｓ３)、及び、ＭｏｎｇｏＤＢ等のｎｏＳＱＬストアのようなレポジトリからのソースデータと自動的に同期して、複製するように構成することができる。これらのソースについては、変更、追加、更新を絶えず監視することができるので、分析プラットフォームは、変更されたデータを採集することができる。これによって、クエリ結果を、比較的最新のものにすることができる。
【００５５】
スキーマ推論
分析プラットフォームは、データがソースに出現することに応答して、以下のアクションを行う。（１）そのデータから統合された半構造（ＪＳＯＮ等）スキーマを推論（２）そのスキーマについて関係ビューを作成（３）物理的インデックスにデータをポピュレート（４）そのインデックスを活用するクエリを実行。アクション１、２、３の一部または全ては、データソースからのデータを通るパスを一度だけにできるように、パイプライン化されてよい。
【００５６】
第１のアクションであるスキーマ推論を最初に記載する。
【００５７】
半構造データの概要
ＪＳＯＮは、ますます、普及している自己記述的な半構造データフォーマットで、インターネットでのデータ交換に広く用いられている。本明細書では、説明のためにＪＳＯＮを記載しており、以下の例も、ＪＳＯＮフォーマットを用いて記載しているが、本開示は、ＪＳＯＮに限定されない。
【００５８】
簡単に言うと、ＪＳＯＮオブジェクトは、文字列フィールド（または、カラム）と、それに対応する、数、文字列、配列、オブジェクト等の潜在的に異なる型の値と、からなる。ＪＳＯＮオブジェクトは、ネストすることができ、フィールドは、配列、ネストされた配列など、多値であってよい。仕様は、ｈｔｔｐ：／／ＪＳＯＮ.ｏｒｇ．に記載されている。追加の詳細は、ｈｔｔｐ：／／ｔｏｏｌｓ．ｉｅｔｆ．ｏｒｇ／ｈｔｍｌ／ｄｒａｆｔ−ｚｙｐ−ｊｓｏｎ−ｓｃｈｅｍａ−０３で入手可能な２０１０年１１月２２日のインターネットエンジニアリングタスクフォース（ＩＥＴＦ）ｄｒａｆｔ−ｚｙｐ−ｊｓｏｎ−ｓｃｈｅｍａ−０３、「Ａ  ＪＳＯＮ  Ｍｅｄｉａ  Ｔｙｐｅ  ｆｏｒ  Ｄｅｓｃｒｉｂｉｎｇ  ｔｈｅ  Ｓｔｒｕｃｔｕｒｅ  ａｎｄ  Ｍｅａｎｉｎｇ  ｏｆ  ＪＳＯＮ  Ｄｏｃｕｍｅｎｔｓ」に記載されており、その開示内容の全体を、援用により本明細書に組み込むものとする。バイナリＪＳＯＮ（ＢＳＯＮ）等の他のＪＳＯＮ型を含むようにＪＳＯＮは一般化されている。さらに、拡張マークアップ言語（ＸＭＬ：Ｅｘｔｅｎｓｉｂｌｅ  Ｍａｒｋｕｐ  Ｌａｎｇｕａｇｅ）、Ｐｒｏｔｏｂｕｆ、Ｔｈｒｉｆｔ等の、他の半構造フォーマットは、全て、ＪＳＯＮに変換することができる。ＸＭＬを用いる場合、クエリは、ＳＱＬではなく、ＸＱｕｅｒｙに従ってよい。
【００５９】
下記はＪＳＯＮオブジェクトの例である。
{"player": { "fname": "George", "lname": "Ruth", "nickname":
"Babe"}, "born": "February 6, 19 85",
"avg": 0.342, "HR": 714,
"teams": [ { "name": "Boston Red Sox", "years": "1914-1919"
},
{ "name": "New York Yankees", "years": "1920-1934" },
{ "name": "Boston Braves", "years": "1935" } ] }
【００６０】
半構造オブジェクトの構造は、オブジェクトごとに異なり得る。従って、同じ野球のデータにおいて、オブジェクトは、
{ "player": { "fname": "Sandy", "lname": "Koufax"}, "born": 
"December 30, 19 35",
"ERA": 2.76, "strikeouts": 2396,
"teams": [ { "name": "Brooklyn / LA Dodgers", "years": "1955-
1966" } ] }
となる。
【００６１】
スキーマは、データコレクション内に見つかり得る構造及びデータ型を記述する。スキーマは、フィールド名、それに対応する値の型、及び、ネスト関係を含む。従って、上記２つのオブジェクトのスキーマは、
{ "player": { "fname": string, "lname": string, "nickname":
string }, "born": string, "avg": number, "HR": number, "ERA":
number, "strikeouts": number,
"teams": [ { "name": string, "years": string } ] }
となる。
【００６２】
上記は、スキーマを説明するためにドキュメントを通じて用いられる表記法であるが、より完全な仕様は、ＪＳＯＮスキーマであり、ｈｔｔｐ：／／ＪＳＯＮ−ｓｃｈｅｍａ．ｏｒｇ．で入手できる。例えば、ＪＳＯＮスキーマの型は、一般的に、文字列または「整数（ｉｎｔ）」として引用符の中に含まれる。本開示では、簡潔さと読みやすさのために、引用符は省略する。
【００６３】
半構造オブジェクトは、あるいは、ノードとしてのフィールドと、アトミックな値としてのリーフを備えたツリーとして見ることができる。オブジェクトまたはスキーマにおける経路は、例えば、“ｐｌａｙｅｒ．ｆｎａｍｅ”、“ｔｅａｍｓ[]．ｎａｍｅ”等のこのツリーにおける経路である。
【００６４】
反復スキーマ推論
ユーザは、データセットの質問をする前に、スキーマを知る必要がある、すなわち、クエリを行うのにどんなフィールドまたは次元が利用可能かを知る必要がある。多くの場合、分析者は、データの生成に関わっておらず、何が記録されていて、何が入手可能か、分からない。例えば、上記の野球の例では、分析者は、打者がコレクション内で観察された場合のみ、“ＥＲＡ”フィールドが利用可能なことを知らない場合がある。従って、分析プラットフォームは、採集したデータから統合スキーマを計算（または、推論）し、スキーマの関係ビューを提示して、分析者がクエリを生成するのを支援する。
【００６５】
分析プラットフォームは、スキーマの正確さと簡潔さを最適化することを目指して、スキーマを生成することを目的としている。一般的に、正確というのは、スキーマが、観察または採集したデータ内の構造を全て表し、まだ見られない構造を許容しないこと、を意味する。簡潔というのは、スキーマが、人間が読み、解釈できるほど十分に小さいこと、を意味する。
【００６６】
スキーマを動的に作成するための一般的なアプローチは、過去のオブジェクトから推論した「現在の」スキーマを用いて開始し、新しいオブジェクトを採集しながら、スキーマを成長させる。我々は、下記のように、単純に、現在のスキーマ（Ｓ＿ｃｕｒｒ）を、新しいオブジェクト（Ｏ＿ｎｅｗ）のスキーマ（ｔｙｐｅ）とマージして、新しいスキーマ（Ｓ＿ｎｅｗ）
S_new = merge(S_curr, type(Ｏ_new))
とする。
【００６７】
大まかにいうと、マージプロセスは、２つのスキーマを結合し、共通のフィールド、サブオブジェクト、及び、配列を折り畳み、新しいものが現れると、新しいものを追加する。これについて、以下により詳しく記載する。
【００６８】
オブジェクト
以下の例の一部は、ｆｉｒｅｈｏｓｅと言うツイッター（Ｔｗｉｔｔｅｒ）からのデータストリームの出力に似たデータを使用している。ツイッターｆｉｒｅｈｏｓｅは、「ツイートされた」ツイートと、それらのツイートのメタデータ（例えば、ユーザ、場所、トピックなど）とを表すＪＳＯＮオブジェクトのストリーム（終わりのないシーケンス）を供給する。これらのツイートは、現代のウェブフレームワーク（例えば、Ｒｕｂｙ  ｏｎ  Ｒａｉｌｓ）、モバイルアプリケーション、センサ、及び、装置（電力計、サーモスタット）などで生成されるような、多くの他の型のイベントログデータと類似している。下記の例は、ツィッターデータと類似しているが、説明目的のために、実際のツイッターデータとは異なっている。
【００６９】
基本的なＪＳＯＮオブジェクトは、取り扱いが容易である。すなわち、単純にオブジェクトに見られる型を推論する。例えば、下記のオブジェクトを考える。
{ "created_at": "Thu Nov 08", "id": 266353834,
"source": "Twitter for iPhone",
"text": "@ilstavrachi: would love dinner. Cook this:
http://bit.ly/955Ffo",
"user": { "id": 29471497, "screen_name": "Mashah08" },
"favorited": false}
【００７０】
オブジェクトから推論されたスキーマは、
{ "created_at": string, "id": number, "source": string, "text":
string,
"user": { "id": number, "screen_name": string }, "favorited":
boolean }
となる。
【００７１】
新しいオブジェクトが到着すると、フィールドのセットに関して統合を行うことによって、新しいフィールドを追加することができる。時には、フィールドは繰り返されるが、その型が異なり、型多様性と呼ばれる状態になる。スキーマは、同じキーを有する複数の属性を用いて、型多様性を表す。.
【００７２】
ログフォーマットは、よく変わるので、開発者は新しいフィールドを追加、または、フィールド型の変更を行ってよい。具体例として、ツイートを識別する“ｉｄ”フィールドを考える。“ｉｄ”フィールドは、元々は、数字であった。しかしながら、ツイートの数が増えるにつれて、一部のプログラミング言語は、大きな数字を処理できなくなり、“ｉｄ”フィールドは、文字列に変更された。従って、その形式の新しいレコードは、
{ "created_at": "Thu Nov 10", "id": "266353840",
"source": "Twitter for iPhone",
"text": "@binkert: come with me to @ilstavrachi place",
"user": { "id": 29471497, "screen_name": "Mashah08" },
"retweet_count": 0 }
となる。
【００７３】
文字列“ｉｄ”が見られ、新しいフィールド“ｒｅｔｗｅｅｔ＿ｃｏｕｎｔ”が出現したので、スキーマは下記のように補強される。
{ "created_at": string, "id": number, "id": string, "source":
string, "text": string,
"user": { "id": number, "screen_name": string },
"retweet_count": number }
【００７４】
“ｉｄ”が一度は文字列として、一度は数字として、二度現れることに留意する。時には、ネストされたオブジェクトの構造が変わる。例えば、下記のように、ユーザに関するプロファイル情報をさらに追加したとしよう。
{ "created_at": "Thu Nov 10", "id": "266353875",
"source": "Twitter for iPhone",
"text": "@binkert: come with me to @ilstavrachi place",
"user": { "id": "29471755", "screen_name": "mashah08",
"location": "Saratoga, CA", "followers_count": 22 },
"retweet_count": 0 }
【００７５】
この場合、プラットフォームは、“ｕｓｅｒ”のネストされたスキーマを再帰的にマージして、下記のスキーマを得る。
{ "created_at": string, "id": number, "id": string, "source":
string, "text": string,
"user": { "id": number, "id": string, "screen_name": string,
"location": string, "followers_count": number },
"retweet_count": number }
【００７６】
ヌル（Ｎｕｌｌ）フィールドと空のオブジェクト
ＪＳＯＮレコードには空のオブジェクトまたはヌルフィールドが、存在し得る。例えば、人の座標（緯度及び経度）のレコードが、
{ "coordinates": {} }
の場合、
スキーマは、下記のように、全く同じ型になる。
{ "coordinates": {} }
厳密に言うと、｛｝は、インスタンスと呼ばれ、型は、オブジェクトである。本開示の実施例及び説明は、説明を容易にするために厳密なＪＳＯＮとは異なっている。
【００７７】
同様に、下記のオブジェクト
{ "geo": null }
は、全く同じ型
{ "geo": null }
を有する。
【００７８】
後続のレコードが、オブジェクトについて値を有する場合、空のオブジェクトは、マージを適用することによって書き込まれる。例えば、レコード
{ "coordinates": {} }
{ "coordinates": {"type": "Point"} }
から、下記のスキーマが生成される。
{ "coordinates": {"type": string} }
【００７９】
ヌル型は、同様に、観察された型によって置き換えられる。例えば、レコード
{ "geo": null }
{ "geo": true }
は、下記のスキーマを生成する。
{ "geo": boolean }
【００８０】
配列
ツイートは、ハッシュタグ（強調されるトピックの単語）、ｕｒｌ、他のツイッターユーザの記載等の項目を含むことが多い。ツイッターｆｉｒｅｈｏｓｅは、例えば、ツイートのＪＳＯＮオブジェクトに含めるために、自動的にこれらの項目を構文解析し、抽出してよい。下記の例では、ハッシュタグのメタデータを用いて、配列のスキーマをどのように推論するかを説明する。
【００８１】
最初に、下記のツイート（または、文字列)のハッシュタグの開始オフセットのリストを抽出、記録することを考える。
"#donuts #muffins #biscuits"
これらのオフセットは、下記の配列で表してよい。
{ "offsets": [0, 8, 17] }
【００８２】
ソースデータの配列は、ソース配列に見られる要素の型を含む配列として、順序は関係なく、スキーマで表される。従って、上記オブジェクトのスキーマは、
{ "offsets": [number] }
である。
【００８３】
後の処理のために、オフセットと共にハッシュタグを含めたい場合、ツイートオブジェクトは、下記のように、ハッシュタグとオフセットの両方を配列の中に列挙してよい。
{ "tags": [0, "donuts", 8, "muffins", 17, "biscuits"] }
対応するスキーマは、下記のように、配列に両方の型を含む。
{ "tags": [ number, string ] }
【００８４】
あるいは、タグ及びオフセットは、下記のように、置き換えられてもよい。
{ "tags": ["donuts", 0, "muffins", 8, "biscuits", 17] }
“ｔａｇｓ”配列は、文字列、数字のどちらも含むことができるので、結果として生じるスキーマは、
{ "tags": [ string, number ] }
となる。
【００８５】
実際に、タグテキスト及びタグオフセットは、下記のように、隣り合うオブジェクトに含めることができる。
{ "tags": ["donuts", "muffins", "biscuits"] },
{ "tags": [0, 8, 17] }
“ｔａｇｓ”に関する２つのスキーマがある。
{ "tags": [string] } and { "tags": [number] }
この場合、配列は、同じ深さにあるので、マージして、上記と同じスキーマを生成することができる。
{ "tags": [ string, number ] }
【００８６】
また、下記のスキーマは、全く同じであることに留意する。
{ "tags": [string, number] }
{ "tags": [number, string] }
これは、型のリストがセットとして扱われたからである。配列要素の型は、可能な場合、マージされ、マージは、配列内の、オブジェクト及び配列に対してさらに行われる。様々な他の実装において、（配列及びオブジェクトの両方における)型の順序、及び、型間の依存性は、保存することができる。しかしながら、これによって、スキーマの簡潔さは低下する。
【００８７】
ネストされたオブジェクト
ネストされたオブジェクトを説明するために、開始オフセットと終了オフセットの両方が下記のように記録されているとしよう。
{ "tags": [{ "text": "donuts", "begin": 0 }, { "text": "donuts",
"end": 6 }]}
結果として生じるスキーマは、
{ "tags": [{"text": string, "begin": number,
"end": number }〕 }
となる。
このように、オブジェクト型は、配列要素を別個に型付けせずに、マージされる。
【００８８】
同様に、タグ文字列及びオフセットが、ネストされた配列内にある場合、
{ "tags": [ [ "donuts", "muffins" ], [0,8] ] } ==>
{ "tags": [[string], [number]]},
スキーマは、さらに、縮小されて、
{ "tags": [[string, number]]}
となる。
これは、本開示の様々な実装において行われる、スキーマの正確さと、スキーマの簡潔さとの間のトレードオフである。
【００８９】
空のオブジェクト及び空の配列は、下記のように扱われる。空のオブジェクトは、上記のように書き込まれるので、下記の例のスキーマの縮小が可能である。
{ "parsed": { "tag": {}, "tag": { "offset": number } } }
=> { "parsed": { "tag": { "offset": number }}
同様に、配列に関するマージ規則を用いて、下記のスキーマ縮小を行う。
{ "tags": [[], [ number ]] } => { "tags": [[ number ]] }
{ "tags": [[], [[]]] } => { "tags": [[[]]] }
{ "tags": [[], [[]], [number]] } => { "tags": [[[]], [number]] }
=> { "tags": [[[], number]]] }
【００９０】
マージ手順
以前のスキーマと新しいオブジェクトから新しいスキーマを作成するために、分析プラットフォームは、最初に、新しいオブジェクトを型付け（すなわち、新しいオブジェクトのスキーマを計算）する。この手順は、型付けのための標準的意味論（canonical semantics)を特定することを意図しており、特定の実装を記載することを意図したものではない。下記の記載において、変数ｖ，ｗ，ｖ＿ｊ，ｗ＿ｊは、任意の有効なＪＳＯＮ値の範囲に亘ってよく、ｊ，ｋ，ｊ＿ｍ，ｋ＿ｎは、有効な文字列に亘ってよい。型付けの基本的規則は、下記のようになる。
type(scalar v) = scalar_type of v
type({ k_l: v_l, ..., k_n: v_n }) =
collapse({ k_l: type(v_l), ..., k_n: type(v_n) })
type([ v_1, ..., v_n ]) =
collapse([ type(v_l), type(v_n) ])
【００９１】
第１の規則は、３や“ａ”等のスカラについて、対応する型は、値自体（３という数字、または、“ａ”という文字列)から直接推論されると、単純に述べている。第２、第３の規則は、折り畳み関数を用いて、オブジェクトと配列を再帰的に型付けする。
【００９２】
折り畳み関数は、オブジェクトの同じフィールドの型を繰り返しマージし、配列内のオブジェクト、配列、及び、共通の型をマージする。マージは、スカラ型に到達するまで、再帰的に続けられる。オブジェクトについて、折り畳み関数は、下記のようになる。
collapse({ k_l: v_l, ..., k_n: v_n }):
while k_i == k_j:
if v_i, v_j are scalar types and v_i == v_j OR
v_i, v_j are objects OR v_i, v_j are arrays:
replace {..., k_i: v_i, ...,  k_j: v_j, ...}
with {..., k_i: merge(v_i, v_j), ...}
【００９３】
配列については、折り畳み関数は、下記のようになる。
collapse ( [ v_l,  ..., v_n ] ) :
while v_i, v_j are scalar types and v_i == v_j OR 
v_i, v_j are objects OR v_i, v_j are arrays:
replace [..., v_i, ..., v_j, ...]
with [..., merge(v_i, v_j), ...]
【００９４】
マージ関数は、どのようにして二つ一組に値を組み合わせて、重複しているものを除き、配列／マップを組み合わせるかを記述する。オブジェクトについては、マージは、単純に、折り畳みを再帰的に呼び出し、共通のフィールドを折り畳む。
merge(v, v) = v
merge({}, { k_l: v_l, ..., k_n: v_n }) = { k_l: v_l, ..., k_n: v_n }
merge({ j_l: v_l, ..., j_n: v_n }, { k_l: w_l, ..., k_m: w_m } )
= collapse({ j_l: v_l,_ ..., j_n: v_n, k_l: w_l, ..., k_m: w_m
} )
【００９５】
同様に、配列については、下記のようになる。
merge([], [v_l, ..., v_n]) = [v_l, ..., v_n]
merge([v_l, ..., v_n], [w_l, ..., w_m])
= collapse([v_l, ..., v_n w_l, ..., w_m])
【００９６】
ヌルは、下記のように、保存される。
merge ( { "coordinates": { } }, { "coordinates": null },
{ "coordinates": [] } )
= { "coordinates": { }, "coordinates": [],"coordinates"null }
ＪＳＯＮのヌル（ｎｕｌｌ）は、数字の９が値であるように、値である。関係では、ＮＵＬＬは、特定された値がなかったことを示す。ＳＱＬにおいては、ヌル値は、ｔａｇｓ＜ｎｕｌｌ＞：ｂｏｏｌｅａｎで表される。ここで、Ｂｏｏｌｅａｎ値は、ヌル値が存在すれば、真（Ｔｒｕｅ）であり、さもなければ、ＮＵＬＬである。ＳＱＬユーザのためのスキーマを単純化するために、ユーザが、ＪＳＯＮのヌル値とＳＱＬのヌル値とを区別する必要がない場合、ｃｏｏｒｄｉｎａｔｅｓ＜ｎｕｌｌ＞カラムは、省略することができる。
【００９７】
累積例
上記の簡単な規則を用いると、深くネストされたＪＳＯＮレコードを型付けすることが可能である。例えば、ウェブページのページビュー統計を表す複雑な仮想（hypothetical）レコードを考える。
{ "stat": [ 10, "total_pageviews", { "counts": [1, [3]],
"page_attr": 7.0 }, { "page_attr": ["internal"]} ]}
下記のスキーマが生成される。
{ "stat": [number,
string,
{ "counts": [number, [number]]
"page_attr": number,
"page_attr": [string]
}〕}
【００９８】
様々な実施において、ＪＳＯＮスキーマフォーマットを用いて、推論されたスキーマを符号化することができる。このフォーマットは、標準化されており、追加のメタデータ(例えば、オブジェクトがマップであるか否か)を組み込むために容易に拡張することができる。しかしながら、かなり冗長で、スペース効率が良くないので、本開示の実施例には用いていない。例えば、ＪＳＯＮスキーマフォーマットにおいては、上記スキーマは、下記のように表される。
{
"type": "object",
"properties": {
"stat": {
"items": {
"type": [
"number",
"string",
{
"type": "object", 
"properties": {
"counts": {
"items": {
"type": [
"number",
{
"items": {
"type": "number"
},
"type": "array"
}
〕
},
"type": "array"
},
"page_attr": {
"type": [
"                  “number",
{
"items": {
"type": "string"
},
"type"： "array"
}
〕
}
}
}
〕
},
"type": "array
}
}
}
【００９９】
マップ装飾
開発者及び分析者は、多くの異なる目的のために、ＪＳＯＮオブジェクトと配列を使用することができる。特に、ＪＳＯＮオブジェクトは、オブジェクト及び「マップ」の両方として、頻繁に用いられる。例えば、開発者は、フィールドが日付で、値がページビューのような収集された統計である、オブジェクトを作成するかもしれない。別の実施例は、フィールドがユーザｉｄで、値がプロファイルである。これらの場合、オブジェクトは、静的オブジェクトというよりもマップデータ構造に近い。フィールド名はとても多いので、ユーザは、可能なフィールド名を必ずしも知っているわけではなく、フィールド名は動的に作成される。結果として、ユーザは、値をクエリするのと同じように、フィールドをクエリしたい場合がある。
【０１００】
この使用をサポートするために、分析プラットフォームは、マップを識別することができる。分析プラットフォームは、ヒューリスティックスを組み込んで、マップを識別する、また、どのネストされたオブジェクトをマップとして扱うべきか、扱うべきでないかをユーザが指定するのを可能にする。オブジェクトをマップとしてタグ付けすることは、装飾と呼ばれる。
【０１０１】
一般に、装飾は、初期ロード後に行われる。すなわち、初期採集でマップを識別する必要はない。装飾は、後に、第２のパスで、あるいは、データがさらに採集された後に行うことができる。さらに、マップは、必要に応じて、単純にオブジェクトに戻すことができる。
【０１０２】
デフォルト設定で、ＪＳＯＮオブジェクトは、オブジェクト（または、Ｃ言語では、構造体）として扱われる。これは、オブジェクトに“ｏｂｊ＿ｔｙｐｅ”：ｏｂｊｅｃｔと注釈を付けることによって、ＪＳＯＮスキーマにおいて明示的に示すことができる。下記の例において使用される省略表記はＯ｛｝である。
【０１０３】
マップにフラグを立てるために、ヒューリスティックスは、フィールドを含有するオブジェクト（コンテナ）と比べて、グループとして比較的まれに発生するフィールドを探す。マップに対しては、省略表記Ｍ｛｝が使用される。
【０１０４】
第１のパスでスキーマを計算する間、フィールドが発生する頻度を追跡する。データセットで頻度Ｆで発生するオブジェクト（またはネストされたオブジェクト）を考える。ｖ＿ｉをオブジェクトにおけるフィールドｉの頻度とし、Ｎを（型とは無関係に）オブジェクトの固有フィールドの数とする。割合（ｓｕｍ（ｖ＿ｉ）／Ｎ）／Ｆは、コンテナの頻度に対する平均フィールド頻度の割合である。この割合が、ユーザが設定可能な０．０１等の閾値未満の場合、含有オブジェクトは、マップとして指定される。様々な実装において、ＪＳＯＮスキーマにおける空のオブジェクトは、マップとして扱われる。
【０１０５】
関係スキーマの作成
ソースデータセットにおけるＪＳＯＮオブジェクトのスキーマが推論された後、分析プラットフォームは、ＳＱＬユーザ及びＳＱＬベースのツールに公開することができる関係スキーマを生成する。目標は、ＪＳＯＮスキーマにおける包含関係を表す簡潔なスキーマを作成する一方で、ユーザに標準ＳＱＬの能力を与えることである。この関係スキーマは、装飾されたＪＳＯＮスキーマから生成され、基礎的半構造データセット上のビューである。変換を行うための一般化手順を記載する前に、どのようにＪＳＯＮスキーマが関係ビューに変換されるかについての幾つかの実施例を記載する。
【０１０６】
オブジェクト
最も単純な実施例は、下記のスキーマ等の、簡単なスカラ型を有するオブジェクトである。
{ "created_at": string, "id": number, "text": string,
"source": string, "favorited": boolean }
この場合、オブジェクトのフィールドは、関係のカラムに直接的に翻訳する。
Root(created_at: str, id: num, text: str, source: str, favorited:
bool)
【０１０７】
トップレベルのオブジェクトの関係（またはテーブル）はここでは“Ｒｏｏｔ”と呼ばれるが、例えば、ソースコレクションの名前が存在する場合には、ソースコレクションの名前で置き換えることができる。スペース及び読みやすさのために、型名の文字列、数字、及び、ブール（ｂｏｏｌｅａｎ）は、ｓｔｒ、ｎｕｍ、及び、ｂｏｏｌに短縮されている。
【０１０８】
型多様性をサポートするために、型を属性名に追加することができる。例えば、下記のスキーマを考える。
{ "created_at": string, "id": number, "id": string, "text":
string, "source": string, "favorited": boolean }
結果として生じる関係スキーマは、下記のように別個の"id"と、"id"カラムとを有することになる。
Root(created_at: str, id<num>: num, id<str>: str,
source: str, text: str, favorited: bool)
【０１０９】
ネストされたオブジェクト
ネストされたオブジェクトは、外部キー関係と新たな関係を作り出す。例えば、ＪＳＯＮスキーマを考える。
{ "created_at": string, "id": number, "source": string, "text":
string,
"user": { "id": number, "screen_name": string },
"favorited": boolean }
対応する関係スキーマは、
Root(created_at: str, id: num, source: str, text: str, favorited: 
bool, user: join_key)
Root.user(id_jk: join_key, id: num, screen_name: str)
である。
【０１１０】
ネストされたオブジェクトは、その経路、この場合は“Ｒｏｏｔ．ｕｓｅｒ”によって名付けられた別個の関係に「正規化」される。サブオブジェクトを表す新たなテーブル内のカラム“Ｒｏｏｔ．ｕｓｅｒ”．“ｉｄ＿ｊｋ”は、カラム“Ｒｏｏｔ．ｕｓｅｒ”（テーブル“Ｒｏｏｔ”における“ｕｓｅｒ”カラム）のための外部キーである。型は、それを他のカラムから区別するために“ｊｏｉｎｋｅｙ”として指定されるが、実際の実装では、ｊｏｉｎ＿ｋｅｙ型は典型的には整数である。
【０１１１】
オブジェクトは、幾つかのレベルの深さにネストすることができる。例えば、リツイートオブジェクトは、リツイートしたユーザのプロファイルを含む、リツイートされた状態オブジェクトを含んでよく、結果として、下記のスキーマになる。
{ "created_at": string, "id": number, "source": string, "text": 
string,
"user": { "id": number, "screen_name": string },
"retweeted_status": { "created_at": string, "id": number,
"user": { "id": number, "screen_name": string } },
"favorited": boolean }
対応する関係ビューは、下記のようになる。
Root(created_at: str, id: num, source: str, 
text: str, favorited: bool,
user: join_key, retweeted_status: join_key)
Root.user(id_jk: join_key, id: num, screen_name: str)
Root.retweeted_status(id_jk: join_key, created_at: str, id: num, 
user: join_key)
Root.retweeted_status.user(id_jk: join_key, id: num, screen_name: 
str)
。“Ｒｏｏｔ．ｕｓｅｒ”、“Ｒｏｏｔ．ｒｅｔｗｅｅｔｅｄ＿ｓｔａｔｕｓ”、及び“Ｒｏｏｔ．ｒｅｔｗｅｅｔｅｄ＿ｓｔａｔｕｓ．ｕｓｅｒ”は、全て異なるテーブルに分かれることに留意する。
【０１１２】
１対１関係の最適化
ネストされたオブジェクトの関係においては、メインのテーブルのローから、ネストされたオブジェクトのテーブルのローに、１対１関係があることが多い。結果として、これらは、カラム名についてドット付き表記を用いて、単一のテーブルに１対１に折り畳むことができる。
【０１１３】
例えば、上記マルチ関係例は、下記のように平坦化され、
Root(created_at: str, id: num, source: str, 
text: str, favorited: bool,
user.id: num, user.screen_name: str)
３レベルのネストされたオブジェクト例に関しては、下記のようになる。
Root(created_at: str, id: num, source: str, 
text: str, favorited: bool, 
user.id: num, user.screen_name: str,
retweeted_status.created_at: str,
retweeted_status.id: num, 
retweeted_status.user.id: num, 
retweeted_status.user.screen_name: str)
【０１１４】
関係スキーマは単純にＪＳＯＮスキーマ上のビューであるので、平坦化された、部分的に平坦化された、または別個の（平坦化されていない）関係スキーマは、基礎的データを修正すること無く、分析プラットフォームの求めに応じて、ユーザに提示できることに留意する。唯一の制限は、ユーザに、矛盾するテーブル定義を提示しないことである。
【０１１５】
マップ
フィールドのセットをマップとして指定すること無く、対応する関係スキーマは、膨大な数のカラムを含んでよい。さらに、ユーザは、フィールド名をクエリすることを望む場合がある。例えば、ユーザは、１２月の平均ページビューを見付けたいかもしれない。
【０１１６】
これらの問題を解決するために、マップとして装飾される（ネストされた）オブジェクトのテーブルは、「ピボットする」ことができる。例えば、ウェブサイト上の各ページについての様々なメトリクス（日々のページビュー、クリック、費やされた時間等）を追跡するために、下記のスキーマを考える。
Ｏ{ "page_url": string, "page_id": number,
"stat_name": string,
"metric": M{ "2012-01-01": number, "2012-01-02": number, ..., 
"2012-12-01": number, ... } }
【０１１７】
各日について、別個のカラムでテーブルを作るのではなく、フィールド及び値は、関係におけるキーと値のペアとして記憶することができる。
Root(page_url: str, page_id: num, stat_name: str, metric<map>: 
join_key)
Root,metric<map>(id_jk: join_key, key: string, val: num)
【０１１８】
この場合、ｉｄカラムは、外部キーであり、どのレコード内に各マップエントリが元々存在したかを示す。１年分のページビューの場合、テーブル“Ｒｏｏｔ．ｍｅｔｒｉｃ”において３６５個のカラムを有する代わりに、カラムは２個だけである。“ｋｅｙ”カラムはフィールド名を記憶し、“ｖａｌ”カラムは値を記憶する。例えば、上記スキーマの場合、データベースは、
”ｗｗｗ．ｎｏｕｄａｔａ．ｃｏｍ／ｊｏｂｓ”（ｐａｇｅ＿ｉｄ２８４）について、これらのレコードを含んでよい。
Root("www.noudata.com/jobs", 284, "page_views", 3),
Root.metric<map>(3, "2012-12-01", 50),
Root.metric<map>(3, "2012-12-02", 30), ...
【０１１９】
ピボットは、マップに型多様性がある場合にも機能する。例えば、メトリクスが、センチメントを表し、センチメントが、カテゴリと、カテゴリの強さを示すスコアと、の両方を含むとしよう。
{ "page_url": "www.noudata.com/blog", "page_id": 285,
"stat_name": "sentiment"
"metric": { "2012-12-01": "agreement", "2012-12-01": 5,
"2012-12-05": "anger", "2012-12-05": 2, ... } }
ＪＳＯＮスキーマは、
0{ "page_url": string, "page_id": number,
"stat_name": string,
"metric": M{ "2012-12-01": string, "2012-12-01": number, ...,
"2012-12-05": string, "2012-12-05": number, ... } }
となる。
【０１２０】
関係スキーマを作成すると、新しい“ｖａｌ”カラムを、新しい型を含むようにマップ関係に追加することができる。下記に示すように、別の“ｖａｌ”カラムを、カラム名を区別するために、その型と共に同様に追加することができる。
Root(page_url: str, page_id: num, stat_name: str, metric<map>:
join_key)
Root,metric<map>(id_jk: join_key, key: string, 
val<str>: str, val<num>: num)
【０１２１】
上記ＪＳＯＮオブジェクトから生じるエントリは、下記のようになる。
Root.metric<map>(4, "2012-12-01", "agreement", NULL),
Root.metric<map>(4, "2012-12-01", NULL, 5),
Root.metric<map>(4, "2012-12-05", "anger", NULL),
Root.metric<map>(4, "2012-12-05", NULL, 2) ...
これらのマップがピボットされると、ユーザは、キーカラムに、それらが任意の他のカラムとなるように、述語及び関数を適用することができる。
【０１２２】
ネストされたマップ
基本原理は、ネストされたマップに関しても同じである。日毎及び時間毎の統計のリストを考える。
M{"2012-12-01": M{ "12:00": number,
"01:00": number,
"02:00": number,
... },
"2012-12-02": M{ ... },
... }
結果として生じるスキーマは、
Root(id_jk: join_key, key: string, val<map>: join_key)
Root.val<map>(id_jk: join_key, key: string, val<num>: num)
となる。
【０１２３】
オブジェクトもマップ内にネストすることができる。
M{ "2012-12-01": Ｏ{ "sentiment": string,
"strength": number }
"2012-12-02": Ｏ{ ... }
... }
結果として生じる平坦化された関係スキーマは、
Root(id_jk: join_key, key: string, val<map>: join_key)
Root.val<map>(id_jk: join_key, sentiment: string, 
strength: number)
となる。
【０１２４】
空の要素
空のオブジェクトが、時々、データ内に現れる。スキーマを考える。
{ "created_at": string, "id": number, "source": string, "text": 
string,
"user": { "id": number, "screen_name": string } }
ＪＳＯＮオブジェクトは、ここに示すように、ユーザ情報を伴わずに受信され得る。
{ "created_at": "Thu Nov 08",
"id": 266353834,
"source": "Twitter for iPhone",
"text": "@ilstavrachi: would love dinner. Cook this: 
http://bit.ly/955Ffo",
"user": { } }
【０１２５】
空のユーザオブジェクトは、下記の関係タプルで表すことができる。
Root("Thu Nov 08", 266353834, "Twitter for iPhone",
"@ilstavrachi: would love dinner. Cook this:
http://bit.ly/955Ffo", join_key)
Root.user(join_key, NULL, NULL)
【０１２６】
採集されたユーザオブジェクトが全て、採集されたストリームに空のオブジェクトを有する場合、結果として生じるＪＳＯＮスキーマは、空のオブジェクトを含むことになる。例えば、このスキーマにおける最後のフィールド（“ｕｓｅｒ”）を見る。
{"id": number, "user": {}}
この場合、空のオブジェクト“ｕｓｅｒ”は、マップとして処理することができ、関係スキーマは、
Root(id: num, user<map>: join_key)
Root.user<map>(id_jk: join_key, key: string)
となる。
【０１２７】
Ｒｏｏｔ．ｕｓｅｒ＜ｍａｐ＞は、値カラムを有さず、最初は空であることに留意する。しかしながら、新しいオブジェクトが採集されて、スキーマが変わる場合、Ｒｏｏｔにおける各レコードが、結合キーを既に割り当てられていることになるので、この設計によって、カラムを後に追加するのが容易になる。
【０１２８】
配列
配列は、マップと同様に処理されるので、スキーマ翻訳はかなり類似している。主な違いは、マップの文字列“ｋｅｙ”フィールドが、配列インデックスに対応する整数型（ｉｎｔ）の“ｉｎｄｅｘ”フィールドに置き換えられることである。簡単な実施例は、下記であり、
{ "tags": [ string ] }
は、下記の関係スキーマにつながる。
Root(tags<arr>: join_key)
Root.tags<arr>(id_jk: join_key, index: int, val<str>: str)
【０１２９】
型多様性及びネストされた配列は、マップについてと同じように機能する。下記のスキーマを考える。
{ "tags": [ number, string] }
は、下記の関係スキーマにつながる。
Root(tags<arr>: join_key)
Root.tags<arr>(id_jk: join_key, index: int, 
val<num>: num, val<str>: str)
【０１３０】
オブジェクトは、下記に示すように、配列内にネストされてよい。
{ "tags": [{ "text": string, "offset": number }] }
結果として生じる関係スキーマは、下記のように作成することができる。
Root(tags<arr>: join_key)
Root.tags<arr>(id_jk: join_key, index: int, val: join_key)
Root.tags<arr>.val(id_jk: join_key, text: str, offset: num)
【０１３１】
１対１平坦化の最適化を使用すると、関係スキーマは、下記のようになる。
Root(tags<arr>: join_key)
Root.tags<arr>(id_jk: join_key, index: int,
val.text: str, val.offset: num)
【０１３２】
ネストされた空の配列
関係スキーマは、ネストされた空の配列について、マップについてと同様の方法で作成することができる。下記のスキーマに関して、
{ "tags": [string, [number]], "urls": []}
関係スキーマは、下記のようになる。
Root(tags<arr>: join_key, urls<arr>: join_key)
Root.tags<arr>(id_jk: join_key, index: int,
val<str>: str, val<arr>: join_key)
Root.tags<arr>.val<arr>(id_jk: join_key, index: int,
val<num>: num)
Root.urls<arr>(id_jk: join_key, index: int)
【０１３３】
ネストされた配列の場合、テーブルの名前に“ｖａｌ”が添えられた別個のテーブルが作成されることに留意する。空の配列の場合、別個のテーブルは、“ｖａｌ”カラム無しで、“ｉｎｄｅｘ”カラムだけで作成され、“ｖａｌ”カラムは、配列の内容が観察されて型付けされると、後で追加することができる。
【０１３４】
アトミックな値に関する型推論
上記型推論及び関係スキーマへの変換手順は、ＪＳＯＮにおいて利用可能である基本型に依存している。いかなる型システムを選択しても、同じ手順が、その型システムに等しく適用される。言い換えれば、分析プラットフォームは、アトミックなスカラ型が値から推論され得る限り、整数、浮動小数、及び、時間のようなより狭いスカラ型を推論することができる。ＢＳＯＮ及びＸＭＬは、そのような拡張された型システムを有する。さらに、様々なヒューリスティックス（正規表現など）を用いて、日付や時間などのより複雑な型を検出することができる。
【０１３５】
ＡＮＳＩ  ＳＱＬは、ＪＳＯＮと同じ型をサポートしていないので、推論された型は、これまで関係ビューについて見られた最も具体的な型に変換される。例えば、整数だけがフィールド“ｆｒｅｑ”について見られる場合には、数字型は、“ｆｒｅｑ”に関する関係スキーマにおいて整数に変換されることになる。同様に、整数と浮動小数の両方が観察されている場合には、関係スキーマは、“ｆｒｅｑ”カラムを浮動小数として示すことになる。同様に、文字列フィールドは、関係スキーマにおいて文字可変型に変換する。言い換えれば、基本ＪＳＯＮ型より具体的な型を追跡してよい。
【０１３６】
あるいは、型多様性に依存して、より具体的な型システムを使用して、データ値の型を推論する。すなわち、ＪＳＯＮプリミティブ型を使用する代わりに、ＡＮＳＩ  ＳＱＬのプリミティブ型を使用する。
【０１３７】
以下は、採集中に追跡される型のリスト（左側）と、それらがどのようにＳＱＬスキーマに関して変換されるか（右側）である。ほとんどのＳＱＬデータベースは、クライアントが求めれば、使用可能なテキストを含む追加型をサポートする。ＯｂｊｅｃｔＩｄ型はＢＳＯＮに特有であることに留意する。
int32, -> INTEGER 
int64, -> INTEGER 
double, -> DOUBLE PRECISION  
string, -> VARCHAR 
date, -> DATE 
bool, -> BOOLEAN 
object_id, (BSON) -> VARCHAR(24) 
time -> TIME
timestamp -> TIMESTAMP
【０１３８】
手順
ＪＳＯＮスキーマから関係スキーマへの変換は、ネストされたＪＳＯＮスキーマ構造の再帰的解凍を使用して達成することができる。実装例の疑似コード表現を、ここに示す。
Call for every attribute in topmost object: 
attr_schema, "Root", attr_name
create_schema(json_schema, rel_name, attr_name):
/* Creates a table (relation) if it's adorned as an object */ 
if json_schema is object:
Add join key called attr_name to relation rel_name 
new_rel = rel_name + "." + attr_name
Create relation new_rel 
add (id_jk: join_key) to new_rel
/* recursively add attributes to the table (relation) */ 
for attr, attr_schema in json_schema:
create_schema(attr_schema, new_rel, attr)
/* Creates appropriate attrs and table for (nested) map */ 
else if json_schema is map:
Add join key called 'attr_name + <map>' to relation rel_name 
new_rel = rel_name + "." + attr_name<map>
Create relation new_rel
Add (id_jk: join_key) and (key: string) to new_rel
/* recursively add attributes to the table (relation) */ 
for each distinct value type val_type in json_schema: 
create_schema(val_type, new_rel, "val")
/* Creates appropriate attrs and table for array */ 
else if json_schema is array:
Add join key called 'attr_name + <arr>' to relation rel_name 
new_rel = rel_name + "." + attr_name<arr>
Create relation new_rel
Add (id_jk: join_key) and (index: int) to new_rel
/* recursively add attributes to the table (relation) */ 
for each distinct item type item_type in json_schema: 
create_schema(item_type, new_rel, "val")
/* Primitive type, add column to the table (relation) */ 
else:
If attr_name does not exist in relation rel_name:
Add column (attr_name, attr_name's type) to relation 
rel_name 
else
Rename attribute attr_name to attr_name + "<orignal 
attr_name's type>" in relation rel_name 
Add column (attr_name + "<" + attr_name's type + ">", 
attr_name's type) to relation rel_name
【０１３９】
上記手順によって、１対１最適化を行わずに関係スキーマを作成する。第２のパスは、関係スキーマを通して行ってよく、１対１関係でオブジェクトテーブルを識別し、折り畳む。あるいは、１対１最適化はインラインで実行することができるが、これについては、明確にするために示していない。ネストされたオブジェクトを有するスキーマのサブツリーが、配列またはマップの「割り込み」を受けない場合、オブジェクトサブツリー全体は、サブツリーのルートへの経路によって名付けられた属性を有する単一のテーブルに折り畳むことができる。マップまたはオブジェクトである属性は別個のテーブル内にとどまるが、内に含まれたサブオブジェクトはいずれも、再帰的に折り畳むことができる。これらの原理は、ネストされたオブジェクトの任意の深さに当てはまる。
【０１４０】
インデックスにデータをポピュレート
ＪＳＯＮ及び関係スキーマが新しいオブジェクトに応答して更新されると、オブジェクト内に含まれるデータは、以下に記載するように、インデックスに記憶することができる。
【０１４１】
分析プラットフォームにおけるインデックスは、キーと値のペアを記憶する、順序を保持するインデックスに依存する。インデックスは、操作、すなわち、ルックアップ（接頭辞）、挿入（キー、値）、削除（キー）、更新（キー、値）、及び、範囲検索のためのｇｅｔ＿ｎｅｘｔ（）をサポートする。そのようなインターフェースをサポートする多数のデータ構造及び低レベルライブラリがある。例には、ＢｅｒｋｅｌｅｙＤＢ、ＴｏｋｙｏＣａｂｉｎｅｔ、ＫｙｏｔｏＣａｂｉｎｅｔ、ＬｅｖｅｌＤＢなどが含まれる。これらは、Ｂ木、ＬＳＭ（ｌｏｇ‐ｓｔｒｕｃｔｕｒｅｄ  ｍｅｒｇｅ）ツリー、及び、Ｆｒａｃｔａｌツリーのような順序を保持する二次記憶データ構造を内部で使用する。オブジェクトＩＤについて等、順序を保持しないインデックス（ハッシュテーブル等）が使用される特殊な場合があってよい。順序を保持しないインデックスを用いると、ｇｅｔ＿ｎｅｘｔ（）及び範囲検索を行う能力が犠牲になる場合がある。
【０１４２】
様々な実装において、分析フレームワークは、ＬｅｖｅｌＤＢを使用する。ＬｅｖｅｌＤＢは、ＬＳＭツリーを実装し、圧縮を行い、高挿入速度でデータセットに良好な性能を提供する。ＬｅｖｅｌＤＢは、また、分析フレームワークの共用モデルと調和し得る性能のトレードオフを行う。例えば、ログデータ等のデータを分析するとき、データは頻繁に追加されることになるが、既存のデータは、希に変更されるか、あるいは、全く変更されない。ＬｅｖｅｌＤＢは、データ削除及びデータ修正を遅くして、高速データ挿入のために最適化されると、有利である。
【０１４３】
順序を保持するインデックスは、キー順序でキーと値のペアを併置する特性を有する。従って、あるキーの近くのキーと値のペアについて検索するとき、あるいは、順番に項目を取り出すとき、応答は、順不同で項目を取り出すときよりもはるかに速く、返される。
【０１４４】
分析プラットフォームは、各ソースコレクションについて多数のキーと値のインデックスを、また、一部の実装では、各ソースコレクションについて２つ〜６つのインデックスを維持することができる。分析プラットフォームは、関係スキーマ（ＳＱＬスキーマは具体化される必要はない）に対してＳＱＬクエリを評価するためにこれらのインデックスを使用する。各オブジェクトは、ｔｉｄで示される固有ｉｄを割り当てられる。ＢｉｇＩｎｄｅｘ（ＢＩ）及びＡｒｒａｙＩｎｄｅｘ（ＡＩ）は、そのインデックスから他のインデックス及びスキーマを再構築することができる２つのインデックスである。
【０１４５】
ビッグインデックス（ＢＩ：ＢｉｇＩｎｄｅｘ）
ＢｉｇＩｎｄｅｘ（ＢＩ）は、配列内に埋め込まれていないデータの全フィールドを記憶するベースデータストアである。値（ｖａｌ）は、ｃｏｌ＿ｐａｔｈ及びｔｉｄに基づいたキーによってＢＩから取り出すことができる。
(col_path, tid) -> val
【０１４６】
ｃｏｌ＿ｐａｔｈは、フィールドの型が添えられたルートオブジェクトからのフィールドへの経路である。例えば、下記のレコードの場合、
1: { "text": "Tweet this", "user": { "id": 29471497,
"screen_name": "Mashah08" } }
2: { "text": "Tweet that", "user": { "id": 27438992,
"screen_name": "binkert" } }
下記のキーと値のペアがＢＩに追加される。
(root.text<str>, 1) --> "Tweet this"
(root.text<str>, 2) --> "Tweet that"
(root.user.id<num>, 1) --> 29471497 
(root.user.id<num>, 2) --> 27438992 
(root.user.screen_name<str>, 1) -> "Mashah08"
(root.user.screen_name<str>, 2) -> "binkert"
【０１４７】
様々な実装において、基礎的インデックスストア（ＬｅｖｅｌＤＢ等）は、キーのセグメントの意味を認識していない。言い換えれば、“ｒｏｏｔ．ｔｅｘｔ＜ｓｔｒ＞，１”は、ルートテーブル内の文字列テキストフィールドの第１の要素を意味するが、インデックスストアは、区別されていない複数文字キーを単純に見ている。簡単な実施例として、キーは、ｃｏｌ＿ｐａｔｈ及びｔｉｄを（重要なことは、その順序で）単に連結することによって作成することができる。例えば、上記に示した第１のキーは、“ｒｏｏｔ．ｔｅｘｔ＜ｓｔｒ＞１”としてインデックスストアに渡されてよい。インデックスストアは、経路の類似性を理解してではなく、単に最初の１４文字が同じであるという理由で、第２のキー（“ｒｏｏｔ．ｔｅｘｔ＜ｓｔｒ＞２”）を第１のキーと併置する。カラム名及びカラム型は、ソート順により、あらゆるキーの一部として記憶されるが、圧縮（接頭辞ベースに圧縮など）を用いて、ストレージ費用を削減することができる。
【０１４８】
ＢＩにおいては、あらゆる新しいカラムについて別個のカラムファイルを作成する従来のカラムストアとは異なり、ソースデータの全てのカラムが単一構造に組み合わされる。ＢＩアプローチは、単一インデックスインスタンスを可能にし、また、マップ検出の遅延を可能にする。新たなフィールドは、単純にＢＩ内にエントリとして現れるので、マップのピボットを怠っても、後にマップに戻される各フィールドについて多数の物理ファイルを作成する物理的費用が発生しない。
【０１４９】
ＢＩにおいては、各属性または「カラム」についてのキーと値のペアが併置される。従って、カラムファイル同様、ＢＩは、クエリエグゼキュータにクエリにおいて参照されないフィールドを含むデータ全体を通らせるのではなく、クエリエグゼキュータにクエリの関心フィールドに焦点を当てさせることができる。
【０１５０】
配列インデックス（ＡＩ：ＡｒｒａｙＩｎｄｅｘ)
配列についての正規化テーブルからフィールドがＢＩに追加できるが、配列インデックスは、対応する値からとなる。代わりに、配列フィールドは、インデックス情報を保持する個別のＡｒｒａｙｉｎｄｅｘ（ＡＩ）に追加することができ、同じ配列内のエントリが、インデックスストアによって併置されることを可能にし、それによって、多くのクエリに良好な性能を提供する。配列値は、下記の署名を用いてＡＩに記憶することができる。
(col_path, tid, join_key, index) -> val
【０１５１】
ｃｏｌ＿ｐａｔｈは、配列フィールドの経路、例えば、タグ配列の要素についての“ｒｏｏｔ．ｔａｇｓ”、または、タグ配列内のオブジェクトの“ｔｅｘｔ”フィールドについての“ｒｏｏｔ．ｔａｇｓ．ｔｅｘｔ”である。ｊｏｉｎ＿ｋｅｙ及びインデックスは、配列の外部キー及び値のインデックスである。各配列についてＢＩに別個のエントリを記憶する必要がないように、ｔｉｄも記憶される。ｔｉｄを用いて、同じオブジェクト内の対応するカラムについて値をルックアップすることができる。別々のツイートにおいて、ハッシュタグを表すオブジェクトを考える。
1: { "id": 3465345, "tags": [ "muffins" "cupcakes" ] }
2: { "id": 3465376, "tags": [ "curry" "sauces" ] }
これらに関して、タグテーブルは、下記のスキーマを有する。
Root.tags<arr>(id_jk: join_key, index: int, val: string)
このテーブルについて、ＡＩ内のエントリは下記のようになる。
(root.tags<arr>, 1, 1, 0) --> "muffins"
(root.tags<arr>, 1, 1, 1) --> "cupcakes"
(root.tags<arr>, 2, 2, 0) --> "curry"
(root.tags<arr>, 2, 2, 1) --> "sauces"
【０１５２】
配列インデックスは、配列フィールドの値を迅速に反復処理することを可能にする。これは、例えば、これらのフィールド全体に統計（例えば、合計、平均、分散等）を実行する場合、特定の値を見付ける場合などに有用である。
【０１５３】
ネストされた配列例
ルートオブジェクト内の配列（トップレベルの配列）については、ｔｉｄ及びｊｏｉｎ＿ｋｅｙフィールドは冗長であり（上記を参照）、最適化により除去できることに留意する。しかしながら、ネストされた配列については、別個のｊｏｉｎ＿ｋｅｙが必要であり、余分ではない。例えば、下記のＪＳＯＮオブジェクトを考える。
1: {"id": 3598574, "tags": [[8,25,75], ["muffins", "donuts", 
"pastries"〕〕}
対応する関係スキーマは、
Root.tags<arr>(id_jk: join_key, index: int, val<arr>: join_key)
Root.tags<arr>.val<arr>(id_jk: join_key, index: int, val<num>: 
num, val<str>: str)
である。
ＡＩは、下記のキーと値のペアを使用することを思い起こそう。
col_path, tid, join_key, index -> val
下記のＡＩエントリが生じる。
tags<arr>.val<arr>, 1, 1, 0 -> 1 
tags<arr>.val<arr>, 1, 1, 1 -> 2 
(numbers array)
tags<arr>.val<arr>.val<num>, 1, 1, 0 -> 8 
tags<arr>.val<arr>.val<num>, 1, 1, 1 -> 25 
tags<arr>.val<arr>.val<num>, 1, 1, 2 -> 75 
(string array)
tags<arr>.val<arr>.val<str>, 1, 2, 0 -> "muffins"
tags<arr>.val<arr>.val<str>, 1, 2, 1 -> "donuts"
tags<arr>.val<arr>.val<str>, 1, 2, 2 -> "pastries"
【０１５４】
結合キーが、ネストされた配列キーと値のペアから取り除かれた場合、マフィン（ｍｕｆｆｉｎｓ）が第１のネストされた配列の一部であったか、第２のネストされた配列の一部であったかが分からなくなることに留意する。従って、結合キーは、トップレベルの配列には冗長であるが、ネストされた配列の場合には冗長ではない。
【０１５５】
配列インデックス（ＡＩ２：Ａｒｒａｙ  Ｉｎｄｅｘ  ２）
上記２つのインデックス（ＢＩ及びＡＩ）は、採集されたデータ全てを再構築するには十分であるが、この２つのインデックスが効率的にサポートしないアクセスパターンがある。そのアクセスパターンのために、下記のインデックスを導入する。下記のインデックスは、追加スペースを犠牲にして性能改善のためにオプションで作成することができる。
【０１５６】
これは、署名
(col_path, index, tid, join_key) -> val
を有し、この署名によって、配列の特定のインデックス要素を迅速に見付けることが可能になる。例えば、インデックス１０（タグ［１０］）で全てのタグの戻すことは、ＡＩ２を用いると、簡単で高速である。
【０１５７】
マップインデックス（ＭＩ：Ｍａｐ  Ｉｎｄｅｘ）
マップインデックスは、その機能及び署名、すなわち、
(col_path, tid, join_key, map_key) -> val
において配列インデックスに類似する。
【０１５８】
主な違いは、マップインデックスは、初期採集中に構築されず、非同期的に構築されることである。初期ロード中、マップは、オブジェクトとして扱われ、通常通り、ＢＩに挿入される。一旦、両方がポピュレートされると、より効率的なクエリ処理のためにＢＩとＭＩの両方のエントリが利用可能になる。ＢＩエントリは、ユーザまたはアドミニストレータがマップを装飾しないように要求する場合には、関連したままである。関係スキーマだけが、変更を必要とされ、マップされないデータに対応する元のＢＩエントリは、その後、クエリにおいて使用される。
【０１５９】
ＡＩ同様、ＭＩは、統計関数の適用、特定のフィールド名への制限などのために、マップ要素を反復処理するときに有用である。ページビュー統計を維持するオブジェクトを再度考える。
1: { "url": "noudata.com/blog",
"page_views": { "2012-12-01": 10, "2012-12-02": 12, ...
"2012-12-15": 10 }
2: { "url": "noudata.com/jobs",
"page_views": { "2012-12-01": 2, "2012-12-02": 4, ... "2012-
12-15": 7 }
マップとしてフラグを立てられる場合、ｐａｇｅ＿ｖｉｅｗｓテーブルについての関係スキーマは、
Root.page_views<map>(id_jk: join_key, key: string, val: num) 
where key is the map's key and val is the associated value. For 
the above objects, the entries in the MI would be:
(root.page_views<map>, 1, 1, "2012-12-01") --> 10 
(root.page_views<map>, 1, 1, "2012-12-02") --> 12
…
(root.page_views<map>, 1, 1, "2012-12-15") --> 10
(root.page_views<map>, 2, 2, "2012-12-01") --> 2 
(root.page_views<map>, 2, 2, "2012-12-02") --> 4
…
(root.page_views<map>, 2, 2, "2012-12-05") --> 7
である。
この順序付けは、ｐａｇｅ＿ｖｉｅｗｓマップ内の値が各ページについて併置されることを可能にする一方、ＢＩでは、値が日付によって併置されることになる。
【０１６０】
マップインデックス２（ＭＩ２：Ｍａｐ  Ｉｎｄｅｘ  ２）
さらに、補助マップインデックスを実装してよい。補助マップインデックスは、その機能及び署名、すなわち、
(col_path, map_key, tid, join_key) -> val
において配列インデックスに類似する。
これによって、“ａｌｌ  ｔｈｅ  ｄｉｆｆｅｒｅｎｔ  ｖａｌｕｅｓ  ｃｏｒｅｓｐｏｎｄｉｎｇ  ｔｏ  ｍａｐ  ｋｅｙ  ２０１２‐１２‐０５”などの、特定のマップ要素についての効率的な検索が可能になる。ＡＩ２とＭＩ２の両方の包括的表現は、以下のように書くことができる。
(col_path, key, tid, join_key) -> val
ここで、キーは、配列のインデックスまたはマップのｍａｐ＿ｋｅｙに対応する。
【０１６１】
値インデックス（ＶＩ：Ｖａｌｕｅ  Ｉｎｄｅｘ）
上記インデックスは、特定のフィールドの値をルックアップし、それらの値を反復処理するのに有用であるが、クエリが特定の値または特定の値の範囲だけを探している場合、高速アクセスを可能にしない。例えば、クエリが、“ｍａｓｈａｈ０８”によって書かれたツイートのテキストを返すこと求めるとする。そのようなクエリを支援するために、スキーマ内のフィールドの一部または全てについてＶａｌｕｅＩｎｄｅｘを構築することができる。ＶａｌｕｅＩｎｄｅｘは、データが採集される際に構築されてもよく、後に非同期的に構築されてもよい。値インデックスのキーは、
(col_path, val)
であり、ここで、ｖａｌは、ソースデータにおける属性の値である。ＶＩにおいてそのキーに対応する値は、どこでその値についてのフィールドが発生するかに応じて決まる。上記各インデックスについて、その値は下記のように変わる。
BI: (col_path, val) -> tid
AI: (col_path, val) -> tid, join_key, index 
MI: (col_path, val) -> tid, join_key, key
【０１６２】
例えば、ツイート
1: { "text": "Tweet this", "user": { "id": 29471497, 
"screen_name": "mashah08" } }
2: { "text": "Tweet that", "user": { "id": 27438992, 
"screen_name": "binkert" } }
は、
(root.text<string>, "Tweet this")   --> 1
(root.text<string>, "Tweet that")   --> 2
(root.user.id<num>, 29471497)   --> 1
(root.user.id<num>, 27438992)   --> 2 
(root.user.screen_name<string>, "Mashah08") --> 1 
(root.user.screen_name<string>, "binkert") --> 2
として記憶される。
ＶＩを用いると、キー：（ｒｏｏｔ．ｕｓｅｒ．ｓｃｒｅｅｎ＿ｎａｍｅ，“ｍａｓｈａｈ０８”）を探し、全ての関連ｔｉｄを取り出すことにより、“ｍａｓｈａｈ０８”によって書かれた全てのツイートについて検索することができる。そして、各ツイートの対応するテキストを返すために、取り出したｔｉｄを使用してＢＩを検索することができる。インデックス、特に、値インデックスによって犠牲になるのは、追加のストレージスペースであり、新しいオブジェクトとしてインデックスの更新に必要な実行時間がシステムに追加される。スペースまたは更新オーバーヘッドが原因で、ユーザは、全ての可能な経路にインデックスを付けることを望まない場合がある。従って、ユーザは、ＶＩにおいてどの経路にインデックスを付けるかを指定することができる。
【０１６３】
ローインデックス（ＲＩ：ＲａｗＩｎｄｅｘ）
（従来のローベースのストアにおけるレコードの要求に類似して）採集したオブジェクト全体の再作成を容易にするために、ＲｏｗＩｎｄｅｘ（ＲＩ）を実装することができる。ＲｏｗＩｎｄｅｘは、キーと値のペア、
tid --> ＪＳＯＮ object
として記憶される。
【０１６４】
ＪＳＯＮオブジェクトは、文字列表現として、ＢＳＯＮとして、または、ＪＳＯＮオブジェクトの内部表現のために使用されるツリー構造などの任意の他の直列化フォーマットとして、記憶されてよい。ＶＩに関して上述した２つのツイートについては、対応するＲＩエントリは、
1 --> { "text": "Tweet this", "user": { "id": 29471497,
"screen_name": "mashah08" } }
2 --> { "text": "Tweet that", "user": { "id": 27438992,
"screen_name": "binkert" } }
である。
【０１６５】
実施例
ＢＩ、ＡＩ、ＭＩ、ＶＩに関する実施例。上記に類似したツイートを考える。ここで、ツイートが一日に何回リツイートされたかを追跡する“ｒｅｔｗｅｅｔ＿ｆｒｅｑ”属性が追加される。
1: { "text": "Love #muffins and #cupcakes: bit.ly/955Ffo",
"user": { "id": 29471497, "screen_name": "mashah08" },
"tags": [ "muffins", "cupcakes" ],
"retweet_freq": { "2012-12-01": 10, "2012-12-02": 13, 
"2012-12-03": 1 } }
2: { "text": "Love #sushi and #umami: bit.ly/955Ffo",
"user": { "id": 28492838, "screen_name": "binkert" }, 
"tags": [ "sushi", "umami" ],
"retweet_freq": { "2012-12-04": 20, "2012-12-05": 1 } }
【０１６６】
これらのレコードのスキーマは、
Ｏ{ "text": string, "user": 0{ "id": number,
"screen_name": string }, "tags": [ string ],
"retweet_freq": M{ "2012-12-01": number ... "2012-12-05":
number } }
である。
【０１６７】
これらのレコードのＪＳＯＮスキーマは、
{
"type": "object",
"obj_type": "object",
"properties" : {
"text" : {
"type": "string"
},
"user": {
"type": "object",
"obj_type": "object",
"properties": {
"id": {
"type": "number",
}
"screen_name": {
"type": "string",
}
}
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"retweet_freq" : {
"type": "object",
"obj_type": "map",
"properties": {
"2012-12-01": { 
"type": "number"
},
…
"2012-12-05": {
"type": "number"
}
}
}
}
}
となる。
【０１６８】
ｒｅｔｗｅｅｔ＿ｆｒｅｑがマップとして扱われない場合、関係スキーマは、
Root (text: str,
user.id: num, user.screen_name: str, 
tags<arr>: join_key,
retweet_freq.2012-12-01: num,
retweet_freq.2012-12-02: num, 
retweet_freq.2012-12-03: num, 
retweet_freq.2012-12-04: num, 
retweet_freq.2012-12-05: num)
Root.tags<arr> (id_jk: join_key,
index: int, 
val: str)
である。
【０１６９】
この場合、上記レコード例は、これらの関係を下記のようにポピュレートすることになる。
Root:
("Love #muffins ...", 29471497, mashah08, 1, 10, 13, 1, NULL, 
NULL)
("Love #sushi ...", 28492838, binkert, 2, NULL, NULL, NULL, 
20, 1)
Root.tags<arr>:
(1, 0, "muffins")
(1, 1, "cupcakes")
(2, 0, "sushi")
(2, 1, "umami")
【０１７０】
これらは、“ｓｅｌｅｃｔ*”クエリがこれらのテーブル上で実行される場合にクエリが戻すタプルであることに留意する。これらのタプルは、ストレージエンジンにおいて必ずしもそのように具体化されない。すなわち、これは、基礎的データ上での単なる仮想ビューであってよく、示したように物理的に記憶されなくてもよい。
【０１７１】
ｒｅｔｗｅｅｔ＿ｆｒｅｑがマップとして識別される場合、関係スキーマは、以下のように、より簡潔（及び追加データに更に協調的(accommodating)）になる。
Root (text: str,
user.id: num, user.screen_name: str, 
tags<arr>: join_key, 
retweet_freq<map>: join_key)
Root.tags<arr> (id_jk: join_key, 
index: int, 
val: str)
Root.retweet_freq<map> (id_jk: join_key,
key: str, 
val: num)
【０１７２】
対応するタプルは、
Root:
("Love #muffins ...", 29471497, mashah08, 1, 1) 
("Love #sushi ...", 28492838, binkert, 2, 2) 
Root.tags<arr>:
(1, 0, "muffins")
(1, 1, "cupcakes")
(2, 0, "sushi")
(2, 1, "umami")
Root.retweet_freq<map>:
(1, "2012-12-01", 10)
(1, "2012-12-02", 13)
(1, "2012-12-03", 1)
(2, "2012-12-04", 20)
(2, "2012-12-05", 1)
である。
【０１７３】
ＢＩに追加されるキーと値のペアは、
(root.retweet_freq.2012-12-01, 1) --> 10
(root.retweet_freq.2012-12-02, 1) --> 13
(root.retweet_freq.2012-12-03, 1) --> 1
(root.retweet_freq.2012-12-04, 2) --> 20
(root.retweet_freq.2012-12-05, 2) --> 1
(root.text, 1) --> "Love #muffins and #cupcakes"
(root.text, 2) --> "Love #sushi and #umami"
(root.uer.id, 1) --> 29471497
(root.user.id, 2) --> 28492838
(root.user.screenname, 1) --> mashah08 
(root.user.screen_name, 2) --> binkert
である。
【０１７４】
ＡＩに追加されるキーと値のペアは下記のようになる。この場合、ネストされた配列が無いので、結合キーは（ｔｉｄと同様に）冗長であることに留意する。
(root.tags<arr>, 1, 1, 0) --> "muffins"
(root.tags<arr>, 1, 1, 1) --> "cupcakes"
(root.tags<arr>, 2, 2, 0) --> "sushi"
(root.tags<arr>, 2, 2, 1) --> "umami"
【０１７５】
ＲＩは、次の２つのエントリを有することになる。
1--> { "text": "Love #muffins and #cupcakes: bit.ly/955Ffo",
"user": { "id": 29471497, "screen_name": "mashah08" },
"tags": [ "muffins", "cupcakes" ], "retweet_freq": { "2012-
12-01": 10, "2012-12-02": 13, "2012-12-03": 1 } }
2--> { "text": "Love #sushi and #umami: bit.ly/955Ffo", "user":
{ "id": 28492838, "screen_name": "binkert" }, "tags": [
"sushi", "umami" 〕, "retweet_freq": { "2012-12-04": 20,
"2012-12-05": 1 } }
【０１７６】
もしＭＩが構築される場合には、ＭＩは、下記のエントリを有することになる。
(root.retweet_freq<map>, 1, 1, "2012-12-01") --> 10
(root.retweet_freq<map>, 1, 1, "2012-12-02") --> 13
(root.retweet_freq<map>, 1, 1, "2012-12-03") --> 1
(root.retweet_freq<map>, 2, 2, "2012-12-04") --> 20
(root.retweet_freq<map>, 2, 2, "2012-12-05") --> 1
【０１７７】
同様に、ＶＩは、（全経路がインデックス付けされ、マップがマップのように扱われる場合）下記のエントリを有することになる。
root. retweet_freq<map>, 1) - -> 2, 2, "2012-12-05
root. retweet_freq<map>, 1) - -> 1, 1, "2012-12-03
root. retweet_freq<map>, 10) - -> 1, 1, "2012-12-01
root. retweet_freq<map>, 13) - -> 1, 1, "2012-12-02
root. retweet_freq<map>, 20) - -> 2, 2, "2012-12-04
root. tags<arr>, "cupcakes") - -> 1, 1, 1
root. tags<arr>, "muffins ") - -> 1, 1, 0
root. tags<arr>, "sushi")  - -> 2, 2, 0
root. tags<arr>, "umami")  - -> 2, 2, 1
(root.text<str>, "Love #muffins and #cupcakes")- -> 1
(root.text<str>, "Love #sushi and #umami") - -> 2
(root.user.id, 29471497) - -> 1
(root.user.id, 28492838) - -> 2
(root.user.screen_name, "mashah08") - -> 1
(root.user.screen_name, "binkert") - -> 2 
【０１７８】
上記アクションは、段階的に記載するが、単一パスでの採集を可能にするためにパイプライン化することができ、ＢＩ、ＡＩ、ＲＩをロードし、ＪＳＯＮスキーマを計算する。他のインデックスは、非同期的に構築することができ、また、求めに応じて有効または無効にすることができる。
【０１７９】
システムアーキテクチャ
分析プラットフォームは、サービス指向であるように設計される。様々な実装において、５つの主なサービス、すなわち、プロキシ、メタデータサービス、クエリエクゼキュータ、ストレージサービス、及び、採集サービスがある。
【０１８０】
この分離アプローチは、幾つかの長所を有し得る。これらのサービスは、外部ＡＰＩ（遠隔手順呼び出し）だけを介して通信するので、サービスを多重化することができ、各サービスを独立して共有することができる。例えば、複数のプロキシが、エクゼキュータ毎に使用されてよく、また、複数のエクゼキュータが、ストレージサービス毎に使用されてよい。メタデータサービスも、エクゼキュータ及びストレージサービスの複数のインスタンス間で共有することができる。
【０１８１】
エクゼキュータ、ストレージ及び採集サービスは、並列化され、プライベートまたはパブリックインフラストラクチャにおいて、仮想マシンインスタンスの個々の部分を実行することができる。これは、これらのサービスを独立的に中断、スケーリングすることを可能にする。これは、需要の変動に基づいてサービス容量を調整することによって費用を削減するのに有用である。例えば、パブリッククラウドの弾力性を用いて、高速の夜通しのロードのための採集サービスを高度に並列化することができる一方、日々のクエリ作業負荷については、実行及びストレージサービスのサイズを削減したままにする。
【０１８２】
プロキシは、クライアントへのゲートウェイであり、ＯＤＢＣ（Ｏｐｅｎ  Ｄａｔａｂａｓｅ  Ｃｏｎｎｅｃｔｉｖｉｔｙ）、ｌｉｂｐｑ、ＪＤＢＣ（Ｊａｖａ（登録商標）  Ｄａｔａｂａｓｅ  Ｃｏｎｎｅｃｔｉｖｉｔｙ）、ＳＳＬ（ｓｅｃｕｒｅ  ｓｏｃｋｅｔｓ  ｌａｙｅｒ）等の、１つまたは複数の標準プロトコルをサポートする。ゲートウェイは、ファイアウォール、認証サービス、及び、内部サービスのための制御の場所として機能する。例えば、実行のサポート及びストレージサービスを費用節約のために中断している間、クライアント接続（ネットワークソケット等）は、プロキシでオープンに保つことができる。クライアント接続が再びアクティブになると、必要なサービスは、比較的短い始動待ち時間でオンデマンドに呼び起こすことができる。
【０１８３】
メタデータサービスは、他のサービスの多くのインスタンスによって典型的に共有される。メタデータサービスは、スキーマ、ソース情報、パーティション化情報、クライアントユーザ名、キー、統計（ヒストグラム、値分布等）、及び、各サービスの現在の状態に関する情報（インスタンスの数、ＩＰアドレス等）を含むメタデータを記憶する。
【０１８４】
ストレージサービスは、インデックスを管理し、読み出し及び書き込み要求を満たす。さらに、クエリエクゼキュータは、多くの関数をストレージサービスにプッシュダウンすることができる。様々な実装において、ストレージサービスは、結果をフィルタにかけるために述語及びＵＤＦ（ユーザが定義した関数）を評価し、（例えば、オブジェクトを再構築するために）ローカル結合を評価し、プッシュダウンされた結合（例えば、ブロードキャスト結合）を評価し、ローカル集計を評価することができる。
【０１８５】
ストレージサービスは、パーティション並列処理と呼ばれる技術を用いて並列化することができる。このアプローチでは、ストレージサービスの非常に多くのインスタンスまたはパーティションが作成され、採集されたオブジェクトはパーティション間で分けられる。各パーティションは、インデックスの各型を、単一のインスタンス全体であるかのように記憶するが、各パーティションは、採集されたデータのサブセットにインデックスを付けるだけである。
【０１８６】
分析エンジンは、１つまたは複数のパーティション化戦略をサポートする。簡単で有効な戦略は、ｔｉｄによってオブジェクトをパーティション化し、ローカルインデックス内に各オブジェクトのエントリを記憶することである。このように、採集されたオブジェクトは、異なるインスタンス間で分割されない。異なるインスタンス間で分割されると、クエリがオブジェクトの複数の部分に依存する場合、かなりのネットワーク帯域幅を消費し得る。ｔｉｄは、ハッシュ割り当て、ラウンドロビン、または、範囲ベースの割り当てを含む、多くの手法で割り当てることができる。これらの個々の割り当ては、全てのインスタンス間に直近のデータを分散することによって、負荷を分散させる。
【０１８７】
別の戦略は、ユーザｉｄまたはセッションｉｄなどの別のフィールド値（またはフィールド値の組み合わせ）によってパーティション化することである。代替のフィールド（カラム）のパーティション化によって、他のテーブルまたはコレクション、例えば、ユーザプロファイル、とローカル結合を行うのが便利になる。パーティション化戦略は、ハッシュパーティション化であってもよく、サンプリング及び範囲パーティション化を用いてもよい。前者は、効率的なポイントルックアップのために使用され、後者は、効率的な範囲検索をサポートするために使用される。
【０１８８】
パーティション化戦略に関わらず、オブジェクトまたはオブジェクトの任意のサブセットは、ローカルに再構築できるべきである。従って、ストレージサービスパーティションは、クエリ処理中、クロストークがなく、ＡＰＩを介した実行サービスとの通信だけを必要とする。
【０１８９】
ストレージサービスはキャッシュを有する。各パーティションにおけるキャッシュサイズを増やすことができ、あるいは、ストレージサービスの性能を改善するためにパーティションの数を増やすことができる。ストレージサービスは、メモリ内、または、ローカルディスク上にインデックスをキャッシュすることができ、インデックスは、Ａｍａｚｏｎ  Ｓ３のような外部ストレージ上で存続することができる。この特徴によって、ストレージサービスノードの停止や破壊が可能になり、また、必要な場合はいつでも、それらを再配置することができる。さらに、この特徴は、高度の弾力性、すなわち、低コストでＳ３にストレージサービスをハイバネートし、かつ、需要変動に合わせてストレージサービス容量を変える能力、を可能にする。
【０１９０】
クエリ実行サービスは、クエリ計画段階によって生成されたクエリ計画を実行する。クエリ実行サービスは、クエリ演算子、例えば、結合（ｊｏｉｎ）、統合（ｕｎｉｏｎ）、ソート（ｓｏｒｔ）、集計（ａｇｇｒｅｇａｔｉｏｎ）などを実装する。これらの演算の多くは、ストレージサービスにプッシュダウンすることができ、可能であればプッシュダウンされる。これらは、述語、射影、射影された属性を再構築するためのカラム型結合、並びに、ＧＲＯＵＰ  ＢＹステートメントを用いる分散的及び代数的集計関数のための部分集計、を含む。
【０１９１】
クエリ実行サービスは、ストレージサービスからデータを取り込み、非ローカル演算、すなわち、非ローカル結合、再パーティション化を必要とするＧＲＯＵＰ  ＢＹステートメント、ソートなど、を計算する。エクゼキュータは、パーティション並列処理エクゼキュータに類似する。エグゼキュータは、交換演算子を使用して、クエリ実行ステップ間で再パーティション化を行い、中間結果を流出させるためのローカルストレージを採用する。多くのクエリについては、ストレージサービス内でクエリのほとんどを実行し、結果収集、及び、任意の小さな非ローカル演算のために単一のエクゼキュータノードだけを必要とすることが可能である。
【０１９２】
採集サービス
採集サービスは、半構造データをクエリできるストレージサービスに半構造データをロードすることを担当する。ユーザは、様々なプラットフォーム（例えば、ＭｏｎｇｏＤＢ、Ａｍａｚｏｎ  Ｓ３、ＨＤＦＳ）から様々なフォーマット（例えば、ＪＳＯＮ、ＢＳＯＮ、ＣＳＶ）でデータを供給する。オプションとしてデータは圧縮機構（例えば、ＧＺＩＰ、ＢＺＩＰ２、Ｓｎａｐｐｙ）を用いて圧縮される。基本手順は、使用されるフォーマットに関わらず、適用できる。
【０１９３】
採集タスクは、２つの部分、すなわち、大量の新しいユーザデータをロードする初期採集タスクと、新しいデータが得られたときに定期的に発生する増分採集と、に大まかに分けることができる。
【０１９４】
初期採集
初期採集プロセスは、幾つかのステップに分けることができる。最初に、入力データをチャンクにパーティション化する。ユーザは、ファイルのコレクションとして、あるいは、データソースに直接接続することによって初期データを供給する。これらのファイルの位置やフォーマットは、メタデータサービス内に記録される。ユーザは、例えばログファイルローテーションのせいで既にパーティション化されデータを供給してよいが、そうではない場合、ファイルは、並列ロードをサポートするためにチャンクにパーティション化することができる。これらのチャンクは、典型的には約数百メガバイトであり、独立して処理される。
【０１９５】
入力ファイルをパーティション化するための正確な機構は、データフォーマットに応じて決まる。レコードが復帰改行によって分離される非圧縮フォーマット（例えば、ＪＳＯＮまたはＣＳＶ）の場合、単一ファイルは、チャンクの目標数に等しい数のプロセスを用いて、並列に処理することができる。処理は、ファイル（ｆｉｌｅ＿ｓｉｚｅ／ｔｏｔａｌ＿ｎｕｍ＿ｃｈｕｎｋｓ）*ｃｈｕｎｋ＿ｎｕｍ内の適切なオフセットで開始し、復帰改行が見付けられるまで検索する。圧縮されたデータまたはＢＳＯＮのようなバイナリフォーマットのデータの場合、各入力ファイルは、連続的スキャンが必要な場合がある。各チャンク（ファイル、オフセット、サイズ）の位置は、メタデータサービス内に記憶される。
【０１９６】
データがチャンクに分けられると、実際のスキーマ推論及び採集が行われる。このプロセスの一部として、２つのサービス、すなわち、採集サービス及びストレージサービスが起動される。この２つのサービスは、作業をするために複数のサーバを採用することができる。２つのサービスはまた、任意の所与のマシン上に併置することができる。採集サービスは、一時的であり、採集プロセス中だけ使用される一方、ストレージサービスは、実際のデータを保持し、持続的でなければならない。採集に関わるサーバは、ストレージサービスサーバにデータを送信し、採集サーバの数は、ストレージサーバの数とは無関係であり、ここでは、その数は、各サービスのスループット間の不均衡を最小にするように選択される。チャンクは、採集サーバ間でパーティション化される。各採集サーバは、自身に割り当てられた各チャンクについて以下のステップ、すなわち、（ｉ）構文解析と型推論、（ｉｉ）ストレージサービスとの通信、（ｉｉｉ）ローカルスキーマ及び統計の計算、を担当する。
【０１９７】
最初に、データレコードが、内部ツリー表現に構文解析される。一貫した内部表現を全てのソースフォーマット（ＪＳＯＮ、ＢＳＯＮ等）について使用してよい。入力フォーマットに応じて、型推論も行われてよい。例えば、ＪＳＯＮは日付表現を持たないので、文字列として日付を記憶するのが一般的である。日付はよく見られるので、ユーザが日付を使用してクエリを発行できるように採集中に検出される型の一実施例である。ＣＳＶ入力ファイルの場合、カラムは型付けされないので、整数などの基本型もまた、検出する必要がある。
【０１９８】
レコードが構文解析され、型が推論されると、構文解析ツリーの圧縮された表現が、ストレージサービスに送信される。これは、ツリーの前順走査の形を取る。ストレージサービスは、各インデックス（ＢＩ、ＡＩ等）に記憶する値を決定することと、タプルｉｄ及び結合キーを生成することと、を担当する。キー生成はストレージサービスに任されて、キーが順次、生成され、それによって、基礎的インデックスストアに対する採集性能を改善する。
【０１９９】
レコードが採集される際、ローカルＪＳＯＮスキーマは、上記規則を使用して更新される。スキーマは、単一採集マシンによって見られるレコードを反映し、異なるマシンは、異なるスキーマを有してよい。
【０２００】
スキーマの計算に加えて、統計が維持される。それは、クエリ処理及びマップ識別に有用である。統計は、各属性が現れる回数、及び、その属性の平均バイトサイズなどのメトリクスを含む。例えば、下記レコード
{ id: 3546732984 }
{ id: "3487234234" }
{ id: 73242342343 }
{ id: 458527434332 }
{ id: "2342342343" }
は、スキーマ｛ｉｄ：ｉｎｔ，ｉｄ：ｓｔｒｉｎｇ｝を生成し、ｉｄ：ｉｎｔには、３のカウントを付記し、ｉｄ：ｓｔｒｉｎｇには、２のカウントを付記することができる。各採集マシンは、自身が計算したスキーマ及び統計をメタデータサービスに記憶する。
【０２０１】
チャンクの全てが採集されると、全体スキーマが計算される。全体スキーマは、クエリエンジンによって使用され、ユーザに提示される。これは、メタデータサービスから部分的スキーマを読み取り、その部分的スキーマを上記方法を使用してマージし、その結果をメタデータサービスに戻して記憶するという、単一プロセスを用いて達成することができる。スキーマの数は、採集マシンの数に限られるので、このプロセスは、パフォーマンスクリティカルではない。
【０２０２】
マップ決定はオプションである。前述のように、どの属性をＭＩ内にマップとして記憶すべきかを決定するために、メタデータサービスに記憶された統計と共にヒューリスティックスを使用することができる。これはクエリ処理に必要ではないが、一部のクエリの表現をより自然にし、効率を改善することを、思い起されたい。マップが識別されると、各ストレージサーバは、どの属性がマップであるべきかを識別するメッセージを受信する。ストレージサーバは、これらのカラムをスキャンし、ＭＩに挿入する。
【０２０３】
増分更新
自身のデータの大半を前もってロードする一部のユーザもいるが、大抵のユーザは、時間をかけて新しいデータを周期的に、多くの場合、定期的（例えば、毎時または毎日）プロセスの一部として、ロードする。このデータの採集は、初期採集に概ね類似する。新しいデータは、チャンクに分割され、スキーマはチャンク毎に計算され、ローカルスキーマは、メタデータサービス内に維持されたグローバルスキーマとマージされる。
【０２０４】
新しいデータが追加されると、システムは自動的にそのデータを検出する。方法はソースデータプラットフォームに応じて決まる。例えば、Ｓ３ファイルの場合、最も簡単なケースは、Ｓ３バケットの変化を検出することである。特殊なプロセスは、新しいキーと値のペア（すなわち、新しいファイル）を探してバケットを定期的にスキャンし、見付けたものをメタデータサービスに追加する。一定数の新しいファイルが見付けられた後、または、一定期間が経過した後、プロセスは、データをロードするための新しい採集プロセスを起動する。
【０２０５】
ＭｏｎｇｏＤＢで行われる操作は、オペレーションログ（またはｏｐｌｏｇ）と呼ばれる特殊コレクションに記憶することができる。ｏｐｌｏｇは、そのレコードは複製のために内部でＭｏｎｇｏＤＢによって使用される、書き込み操作の一貫したレコードを提供する。ｏｐｌｏｇを読み取り、使用して、新しいレコードを記憶するＳ３内にフラットファイルのセットを作成する。次に、上記方法を用いて、新しいデータを採集することができる。
【０２０６】
増分採集プロセスは、新しいデータ（例えば、新しいＪＳＯＮドキュメント）と、既存のドキュメントへの更新（例えば、既存のＪＳＯＮドキュメントにおける新しい属性または既存の属性についての新しい値）の両方を取り扱うことができる。各データソースプラットフォームの能力は、ソースファイルにおける更新の公開という点で異なる。この情報の種類を“ｄｅｌｔａ”と呼び、フラットファイルまたはログファイル（例えば、ＭｏｎｇｏＤＢ）の形を取り得る。増分採集プロセスは、“ｄｅｌｔａ”ファイルからの情報を処理し、それを既存のスキーマ情報と組み合わせて、新しいデータを生成し、そのデータは、ストレージサービスに送信される。
【０２０７】
データのサブセット化
データ採集と増分更新を行うための、ここに記載のシステムは、ソースから全データを採集することができる一方、採集したいデータのＪＳＯＮスキーマ（または関係スキーマ）を前もって指定することによって、比較的簡単にサブセットだけを採集することができる。これは、ＪＳＯＮスキーマ自体の提供、あるいは、サブセットを指定するクエリの提供によって行われる。このように、分析プラットフォームは、ソースデータを具体化したビューとして考えることができる。
【０２０８】
また、ユーザが採集されたくないデータを指定することも可能である。採集されるべきでないデータの一部を記述するＪＳＯＮスキーマまたは関係スキーマを提供することができる。そうすると、単に、全てのその後のローの、採集されるべきでない要素を単純にスキップするように採集処理に告げる情報の、メタデータサービスへの記録の問題に過ぎない。これをデータ採集後に行う場合、既に採集されたデータは、単純に入手不能になり、バックグラウンドタスクによってガベージコレクションにかけることができる。このガベージコレクションは、インデックスストア（例えば、ＬｅｖｅｌＤＢ）の圧縮プロセスに組み込まれることになる。
【０２０９】
耐障害性
初期採集中にロードプロセスを再起動することが可能である一方、増分採集プロセスは、ユーザが全データをゼロからリロードする必要がないように、システムの既存データを破損してはいけない。ファイル採集は冪等演算ではないので、ｉｄ生成に起因して、基礎的ストレージシステムのスナップショットを撮ることに基づいて簡単な耐障害性スキームを実装することができる。
【０２１０】
基礎的ストレージシステムが、ＬｅｖｅｌＤＢが行うように、ある時点で一貫性のあるスナップショットを撮ることをサポートする場合、スナップショットを撮ることは、簡単であろう。このプリミティブを用いると、増分ロードのステップは、以下のようになる。単一プロセスは、各ストレージサーバに、ローカルにスナップショットを撮るように指示し、ロード期間中、全クエリをこのスナップショットに導く。各チャンクは、前述のようににロードされる。完了すると、チャンクのロードを担当する採集サーバは、メタデータサービスにおいて終了したものとしてマークを付ける。
【０２１１】
プロセスは、メタデータサービスを監視する。全チャンクがロードされている場合、プロセスは、状態の更新済みバージョンにクエリをアトミックにリダイレクトする。そして、第１のステップで撮られたスナップショットは捨ててよい。失敗した場合、スナップショットは、状態の正準バージョンになり、状態の部分的に更新された（及び破損の可能性のある）元のバージョンは捨てられる。そして、採集処理が再開される。さらに、サーバが故障の場合には、ストレージシステムディスク量のスナップショットを、回復のために使用することができる。
【０２１２】
クエリ実行
クエリ例
実行例を示すために、簡単なクエリ
select count(*) from table as t where t.a > 10;
を考える。
最初に、プロキシは、クエリを受信し、計画立案のためにそれをエクゼキュータノードに発行する。次に、エクゼキュータノードは、どのコレクション及びストレージノードが使用可能であるかを決定するためにメタデータサービスを呼び出すクエリ計画を生成する。エクゼキュータノードは、典型的には、その計画を他のエクゼキュータノードに分散させるが、ここでは、単一のエクゼキュータノードだけを必要とする。
【０２１３】
そして、実行ノードは、ＲＰＣ呼び出しをストレージサービスノードに行い、ｔ．ａ＞１０述語及びカウント関数をプッシュダウンする。次に、ストレージノードは、サブカウントを計算し、それらをエクゼキュータノードに返す。そして、エクゼキュータノードは、プロキシが次の結果値をフェッチするときに結果をプロキシに返す。
【０２１４】
動的型付け
データベースシステム（例えば、ＰｏｓｔｇｒｅＳＱＬ）のストレージエンジンは、強く型付けされる。それは、カラム（または属性）の値の全てが、全く同じ型（例えば、整数、文字列、タイムスタンプ等）を有する必要があることを意味する。ビッグデータ分析の文脈において、これは、かなりの制約である。なぜなら、かなり多くのアプリケーションが個々の情報（属性）の表現を変える必要があり、その結果として、アプリケーションがその情報の記憶に使用するデータ型の変更が必要となるからである。例えば、アプリケーションは、最初に、整数を使用して、ある属性の値を記憶し、その後、浮動小数の使用に切り替える場合がある。データベースシステムは、そのような操作をサポートするように設計されていない。
【０２１５】
この問題に対処する１つの方法は、各属性について複数の関係カラムを使用すること、すなわち、各異なるデータ型について１つの関係カラムを使用することである。例えば、値３１４３２及び“３１４３３”（すなわち、整数及び文字列）を有する属性“ｕｓｅｒ．ｉｄ”を見た場合、別個のカラムとして“ｕｓｅｒ．ｉｄ＜ｉｎｔ＞”及び“ｕｓｅｒ．ｉｄ＜ｓｔｒｉｎｇ＞”を記憶することができる。単一のレコードは、これらのカラムのうち、そのレコードの“ｕｓｅｒ．ｉｄ“の型に対応する１つのカラムにのみ値を有することになる。そのレコードに関する他のカラムの値はＮＵＬＬとなる。
【０２１６】
同じ属性について複数のカラムを提示することは、ユーザが使用するには複雑すぎることが多い。ユーザ体験を簡単にするために、分析プラットフォームは、ユーザが用いようとする型を、クエリ時に動的に推論することができる。この目的のために、ストレージサービスは、複数の型を追跡している。例えば、ストレージサービスは、ＮＵＭＢＥＲと呼ばれる数字に関する包括的データ型を使用する。ＮＵＭＢＥＲは、整数と浮動小数の両方をカバーする。ＮＵＭＢＥＲ型を使用する場合、更に具体的なデータ型が、値の一部として記憶される。例えば、属性“Ｃｕｓｔｏｍｅｒ．ｍｅｔｒｉｃ”の整数値１０は、キーと値のペアとしてＢＩ内に記憶される。ここで、（Ｃｕｓｔｏｍｅｒ．ｍｅｔｒｉｃ，＜ＮＵＭＢＥＲ＞，ｔｉｄ）がキーであり、（１０，ＩＮＴＥＧＥＲ）が値である。同じ属性の浮動小数点値１０．５は、キー：（Ｃｕｓｔｏｍｅｒ．ｍｅｔｒｉｃ，＜ＮＵＭＢＥＲ＞，ＴＩＤ）、値：（１０．５，ＦＬＯＡＴ）として記憶されることになる。
【０２１７】
最終的に、クエリ時に、分析プラットフォームは、クエリの特性（述語、型変換操作等）に従ってデータ型間の動的型変換を、これらの操作が情報損失をもたらさない限り、実行できる。“ｎｕｍｂｅｒ”はＡＮＳＩ  ＳＱＬ型ではないが、柔軟な型付けシステムによって、クライアントは、クエリコンテキストから“ｎｕｍｂｅｒ”を、標準ＡＮＳＩ  ＳＱＬ浮動小数、整数、または、数値型として扱うことができる。例えば、クエリ
select user.lang from tweets where user.id = '31432'
を考える。
“ｕｓｅｒ．ｉｄ＜ｉｎｔ＞”及び“ｕｓｅｒ．ｉｄ＜ｓｔｒｉｎｇ＞”の両方を有する場合、システムは、オプションとして、クエリ時に、整数（例えば、３１４３２）を単一文字列表現（例えば、“３１４３２”）に変換して、ユーザが、ＡＮＳＩ  ＳＱＬ型ＶＡＲＣＨＡＲで単一カラム“ｕｓｅｒ．ｉｄ”を処理することを可能にする。
【０２１８】
米国規格協会（ＡＮＳＩ：Ａｍｅｒｉｃａｎ  Ｎａｔｉｏｎａｌ  Ｓｔａｎｄａｒｄｓ  Ｉｎｓｔｉｔｕｔｅ）／国際標準化機構（ＩＳＯ：Ｉｎｔｅｒｎａｔｉｏｎａｌ  Ｏｒｇａｎｉｚａｔｉｏｎ  ｆｏｒ  Ｓｔａｎｄａｒｄｉｚａｔｉｏｎ）ＳＱＬ：２００３に例として言及するが、他の実装では、他の規格、ＳＱＬまたはそれ以外のものに準拠してよい。ほんの一例として、公開したインターフェースは、ＡＮＳＩ／ＩＳＯ  ＳＱＬ：２０１１に準拠する。
【０２１９】
図面
図１Ａは、分析プラットフォームのクラウドベースの実装例を示す。分析フレームワークを使用する組織のローカルエリアネットワーク（ＬＡＮ）またはワイドエリアネットワーク（ＷＡＮ）１００が、インターネット１０４に接続する。この実装における計算ニーズ及びストレージニーズは、いずれも、クラウドベースのサービスによって提供される。図に示す特定の実装では、計算サーバは、ストレージサーバとは別個である。詳細には、計算クラウド１０８は、分析フレームワークに処理能力を与える複数のサーバ１１２を含む。サーバ１１２は、個別のハードウェアインスタンスであってもよいし、あるいは、仮想サーバであってもよい。
【０２２０】
サーバ１１２は、処理機能が動作する、それ自体のストレージも有してよい。例えば、サーバ１１２は、クエリエクゼキュータとストレージサービスの両方を実装してよい。従来のカラム型ストレージシステムは、ディスク上にカラムとしてデータを記憶し、そのデータはメモリに読み込まれるとき、そのカラム型データからローが再構築される。しかしながら、本開示のインデックスは、ディスク上とメモリ内の両方でカラム型ストレージとして機能する。インデックスが固有に構成されているので、高速カラム型アクセスという利点を、比較的小さな犠牲で達成することができる。
【０２２１】
本開示によれば、データはインデックスに格納され、具体化されたテーブルには格納されないので、ストレージクラウド１１６は、インデックスデータに使用するストレージ配列１２０を含む。サーバ１１２のストレージリソースが使用されるとき、ストレージ配列１２０は、各クエリに応答するためではなく、バックアップ及びニアラインストレージのために使用されてよい。
【０２２２】
様々な実装において、ストレージ配列１２４は、分析フレームワークが処理するデータを含んでよい。ほんの一例として、ストレージ配列１２４は、ログデータなどの関連データを保持してよく、ユーザは、分析フレームワークを使用してそのデータにクエリすることを望んでよい。
ストレージ配列１２０及びストレージ配列１２４は、同じストレージクラウド１１６内に示されているが、外部にホストされたプライベートクラウド、パブリッククラウド、及び、組織に固有の内部にホストされた仮想環境を含む、別々のクラウド内に配置されてよい。
【０２２３】
ほんの一例として、ストレージクラウド１１６は、Ａｍａｚｏｎウェブサービス（ＡＷＳ）Ｓ３クラウドであってよい。Ａｍａｚｏｎウェブサービス（ＡＷＳ）Ｓ３クラウドは、企業がストレージ配列１２４にデータを記憶するために既に使用している。結果的に、データをストレージ配列１２０に移すことは、高スループット及び低費用で実現され得る。計算クラウド１０８は、ＡＷＳ  ＥＣ２によって提供されてよく、その場合、計算クラウド１０８及びストレージクラウド１１６は、共通のプロバイダによってホストされる。ユーザ１３０は、標準ＳＱＬツールを使用してクエリを構築し、そのクエリは計算クラウド１０８で実行され、応答はユーザ１３０に返される。ＳＱＬツールは、ユーザ１３０のコンピュータ１３４に既にインストールされたツールであってよく、本分析フレームワークと共に動作するために修正する必要は無い。
【０２２４】
図１Ｂでは、別のデプロイメントアプローチ例が示される。この場合、物理サーバ機器１８０は企業のＬＡＮ／ＷＡＮ１００に接続される。サーバ機器１８０は、オンサイトでホストされてもオフサイトでホストされてもよく、仮想プライベートネットワーク等を用いて、ＬＡＮ／ＷＡＮ１００に接続されてよい。サーバ機器１８０は、計算機能及びストレージを含み、ソースから入力データを受信する。ソースは、ＬＡＮ／ＷＡＮ１００に対してローカルであってよい。ほんの一例として、コンピュータもしくはサーバ１８４は、ウェブトラフィックログまたは侵入検出ログなどのログを記憶してよい。
【０２２５】
サーバ機器１８０は、ユーザ１３０のクエリに応答するためにインデックスデータを取り出し、記憶する。ストレージクラウド１１６は、追加データソース１８８を含んでよく、追加データソース１８８は、更に他のデータを保持してよく、及び／または、古いデータのためのニアラインデータストレージ設備であってよい。サーバ機器１８０は、ユーザクエリを満足させるために、追加データソース１８８から追加データを取り出してよい。サーバ機器１８０はまた、バックアップ目的などのために、ストレージクラウド１１６にデータを記憶してよい。様々な他の実装においては、追加データソース１８８は、クラウドにおけるＨａｄｏｏｐ実装の一部であってよい。
【０２２６】
本開示の分析フレームワークは柔軟で、多くの他のデプロイメントシナリオが可能である。ほんの一例として、ソフトウェアが企業に提供されてよく、そのソフトウェアは、所有のサーバまたはホストされたサーバにインストールできる。別の実装では、仮想マシンインスタンスが提供されてよく、仮想マシンインスタンスは、仮想化環境を通してインスタンス化することができる。さらに、ユーザは、ブラウザにおいてユーザインタフェースを提供されてよく、ＳＱＬ部分は、Ｎｏｕ  Ｄａｔａ等のサービスプロバイダによってホストされてよく、それらのシステム上またはクラウドで実装されてよい。
【０２２７】
データウェアハウス
図１Ｃは、本開示の原理によるデプロイメントアプローチ例を示す。採集したデータは、インデックスストレージ１２０内に加えて、または、その代わりに、データウェアハウス１９２に記憶することができる。様々な実装において、データウェアハウス１９２は、カスタマーサイトに配置してもよく、あるいは、図１Ｃに示すように、クラウド１９６に配置してもよい。
【０２２８】
データウェアハウス１９２を用いることによって様々な利点がある。ほんの一例として、データウェアハウス１９２は、一般的に、成熟したフル機能を備えたクエリ処理層及びＯＤＢＣインタフェースを有する。さらに、データウェアハウス１９２は、本開示によるシステムが採集する以外の他のデータのためのセントラルレポジトリであってよい。さらに、データウェアハウス１９２は、データのスナップショット及びリビジョン制御を実装してよく、また、確立されたバックアップ戦略の一部であってよい。
【０２２９】
様々な実装において、データウェアハウス１９２は、ＰｏｓｔｇｒｅＳＱＬ、ＭｙＳＱＬ、Ｍｉｃｒｏｓｏｆｔ  ＳＱＬ  サーバ、Ｏｒａｃｌｅなどを含む、ＳＱＬコマンドのサブセットまたはフルセットをサポートする関係データベース等、単に関係データベースであってよい。採集したデータのスキーマは経時的に変わり得るので、カラム型ストレージを用いたデータウェアハウス１９２の実装によって、追加のカラム（新しい属性または既存の属性の新たな型など)が効率的に追加できるようになる。
【０２３０】
ロー指向の従来のデータベースシステムにおいては、カラムの追加は、時間的、及び／または、空間的に非効率な場合がある。データウェアハウス１９２の様々な実装は、Ｖｅｒｔｉｃａ、Ｇｒｅｅｎｐｌｕｍ、Ａｓｔｅｒ／Ｔｅｒａｄａｔａ、及び、Ａｍａｚｏｎ（ＲｅｄＳｈｉｆｔ)の製品を含む、カラム型の特徴を有してよい。Ｖｅｒｔｉｃａ及びＡｍａｚｏｎ  ＲｅｄＳｈｉｆｔ等のデータウェアハウス１９２の実装の一部は、並列ロードをサポートするので、適切にフォーマットされたデータを幾つかのソースから同時に採集できる。複数の中間ファイルにデータをパッケージ化することによって、データのデータウェアハウス１９２へのロードに必要な時間を大幅に減らし得る。
【０２３１】
データウェアハウス１９２をクラウド１９６で実装することによって、データウェアハウス１９２用のハードウェア及びソフトウェアの購入に関連する初期費用を減らせる等、様々な利益が得られる。さらに、データウェアハウス１９２を提供するクラウド１９６は、インターネット１０４の公共部分を介して入手可能なより大きいスループットで、インデックスストレージ１２０またはデータソース１２４からデータを採取することが可能になり得る。データウェアハウス１９２がＡｍａｚｏｎ  ＲｅｄＳｈｉｆｔであり、インデックスストレージ１２０がＡｍａｚｏｎ  Ｓ３に記憶される場合などの、様々な実装において、データは、インデックスストレージ１２０とデータウェアハウス１９２間を、Ａｍａｚｏｎのネットワークを離れることなく転送されてよい。これによって、待ち時間を減らすことができ、スループットを向上させることができる。
【０２３２】
図１Ｄは、サーバ２００のハードウェア構成要素を示す。プロセッサ２０４は、メモリ２０８からの命令を実行し、メモリ２０８内に記憶された（読み取り及び書き込み）データを処理してよい。一般に、スピードを求めて、メモリ２０８は揮発性メモリである。プロセッサ２０４は、潜在的にチップセット２１２経由で、不揮発性ストレージ２１６と通信する。様々な実装において、不揮発性ストレージ２１６は、キャッシュとして機能するフラッシュメモリを含んでよい。より大容量及び低費用のストレージを二次不揮発性ストレージ２２０のために使用してよい。例えば、ハードドライブなどの磁気ストレージ媒体を用いて、二次不揮発性ストレージ２２０に基礎的データを記憶してよく、基礎的データのアクティブな部分は、不揮発性ストレージ２１６にキャッシュされる。
【０２３３】
入出力機能２２４は、キーボードやマウスなどの入力と、グラフィックディスプレイや音声出力などの出力とを含んでよい。サーバ２００は、ネットワーキングカード２２８を使用して他のコンピュータデバイスと通信する。様々な実装において、または、様々な時間に、入出力機能２２４が休止し、サーバ２００と外部アクターとの間の全ての対話がネットワーキングカード２２８経由で行われてもよい。図を簡単にするために、一例として、不揮発性ストレージ２１６とメモリ２０８との間またはネットワーキングカード２２８とメモリ２０８との間のダイレクトメモリアクセス（ＤＭＡ）機能などの、追加のよく知られた特徴及び変形形態は、示していない。
【０２３４】
データフロー
図２Ａにおいて、プロセス図は、ユーザ１３０がデータにクエリできるように当該データがどのように分析フレームワークに採集されるかの一実施例を示している。データソース３００は、分析フレームワークが処理するデータを提供する。生データが自己記述的でない場合、オプションであるユーザ定義のラッパー関数３０４によって、その生データをＪＳＯＮオブジェクト等の自己記述的な半構造データに変換してよい。
【０２３５】
アドミニストレータ３０８は、異なる容量で動作しているユーザ１３０であってもよく、ラッパー関数を実装するガイドラインを指定することができる。アドミニストレータ３０８は、また、データソース３００のうちのどのデータソースを使用するかと、そのデータソースからどのデータを取り出すかと、を指定することができる。様々な実装において、データの取り出しは、サブセット化操作及び／または他の計算を含み得る。ほんの一例として、データソース３００の１つがＨａｄｏｏｐである場合、分析フレームワークのためのデータ取り出しに先立って、ＭａｐＲｅｄｕｃｅジョブが要求されてよい。
【０２３６】
取り出したデータは、スキーマ推論モジュール３１２によって処理される。スキーマ推論モジュール３１２は、受信したデータの観察された構造に基づいてスキーマを動的に構築する。アドミニストレータ３０８は、様々な実装において、スキーマ推論モジュール３１２に型付けのヒントを提供する能力を有してよい。例えば、型付けのヒントは、日付、時間、または、他のアドミニストレータが定義した型など、個々のフォーマットを認識するための要求を含んでよく、それらは、例えば、正規表現によって指定されてよい。
【０２３７】
データオブジェクトと、スキーマ推論モジュール３１２が生成したスキーマとは、装飾モジュール３１６及びインデックス作成モジュール３２０に供給される。入力オブジェクトは、ソースデータと、そのソースデータを記述するメタデータと、を含む。ソースデータは、インデックス作成モジュール３２０によって、インデックスストレージ３２４に記憶される。
【０２３８】
装飾モジュール３１６は、スキーマモジュール３１２が生成したスキーマ内のマップを識別する。マップの識別を求めない実装においては、装飾モジュール３１６は、省略されてよい。アドミニストレータ３０８は、マップ識別に用いられる装飾モジュール３１６が行うヒューリスティックスを調整するマップ基準を指定することができてよい。
【０２３９】
マップが識別された後、関係スキーマ作成モジュール３２８は、ＳＱＬ対応スキーマ等の関係スキーマを生成する。さらに、識別されたマップは、補助インデックス作成モジュール３３２に供給される。補助インデックス作成モジュール３３２は、ＭａｐＩｎｄｅｘ等の追加のインデックス、及び、上記のように、ＶａｌｕｅＩｎｄｅｘ内にマップエントリを作成することができる。補助インデックスも、インデックスストレージ３２４に記憶されてよい。
【０２４０】
アドミニストレータ３０８は、マップインデックスの作成を要求する能力を有してよく、値インデックスにどのカラムを追加すべきかを指定してよい。さらに、アドミニストレータは、どのオブジェクトをマップとして扱うべきかを指定することができてよく、あるオブジェクトをマップとして扱うか否かを動的に変更することができる。このような変更によって、関係スキーマも変更されることになる。
【０２４１】
関係最適化モジュール３３６は、関係スキーマを最適化して、より簡潔なスキーマをユーザ１３０に提示する。例えば、関係最適化モジュール３３６は、上記のように、テーブルとテーブルの間の１対１の関係を識別し、それらのテーブルを平坦化して単一のテーブルにしてよい。結果として生じる関係スキーマは、メタデータサービス３４０に供給される。
【０２４２】
クエリエグゼキュータ３４４は、メタデータサービス３４０とインタフェースして、プロキシ３４８からのクエリを実行する。プロキシ３４８は、ＯＤＢＣクライアント３５２等のＳＱＬ対応のクライアントと対話する。ＳＱＬ対応のクライアントは、特別な構成なしにプロキシ３４８と対話することができる。ユーザ１３０は、ＯＤＢＣクライアント３５２を用いて、クエリエグゼキュータ３４４にクエリを送り、そのクエリに対する応答を受信する。
【０２４３】
ＯＤＢＣクライアント３５２を介して、ユーザ１３０は、メタデータサービス３４０に記憶された関係スキーマを見ることもでき、関係スキーマに対するクエリを構築することができる。ユーザ１３０もアドミニストレータ３０８も予測スキーマを知る必要はなく、スキーマ作成を支援する必要もない。代わりに、スキーマは、取り出されたデータに基づいて動的に作成され、提示される。ＯＤＢＣクライアント３５２を図に示したが、ＪＤＢＣ及び直接的なｐｏｓｔｇｒｅｓクエリを含む、ＯＤＢＣ以外の機構も利用可能である。様々な実装において、グラフィカルユーザインタフェースアプリケーションによって、ユーザがＯＤＢＣクライアント３５２を使用するのを容易にし得る。
【０２４４】
クエリエグゼキュータ３４４は、インデックスストレージ３２４を含むストレージサービス３５６からのデータを処理する。ストレージサービス３５６は、それ自体のローカルストレージ処理モジュール３６０を含んでよく、クエリエグゼキュータ３４４は、ローカルストレージ処理モジュール３６０に様々な処理タスクを任せることができる。処理されたデータは、次に、ストレージ処理モジュール３６０によって、クエリエグゼキュータ３４４に供給され、受信したクエリに対する応答を構築する。クラウドベースの実装においては、ストレージサービス３５６及びクエリエグゼキュータ３４４は両方とも、計算クラウドで実装してよく、インデックスストレージ３２４は、計算インスタンスに記憶することができる。インデックスストレージ３２４は、図１Ａに示したストレージクラウド１１６内などの、ニアラインストレージにミラーされてよい。
【０２４５】
図２Ｂにおいて、データロードモジュール３７０は、データウェアハウス１９２が理解するフォーマットで、データファイルを生成する。例えば、データウェアハウス１９２は、大量のデータをロードするためのＳＱＬ  Ｃｏｐｙ  Ｆｒｏｍコマンドをサポートしてよい。このコマンドによって処理されるデータファイルは、所定の型を有してよく、その型は、ＣＳＶ（ｃｏｍｍａ−ｓｅｐａｒａｔｅｄ  ｖａｒｉａｂｌｅ）の変形であってよい。関係スキーマの各関係について、データウェアハウス１９２にロードするための中間ファイルが作成される。データウェアハウス１９２が並列ロードをサポートする場合、大きいファイルの一部または全てを、並列ロード用に複数のファイルに分割してよい。これらの中間ファイルのためのデータは、インデックスストレージ１２４から取り出してもよく、及び／または、データソース３００を通る第２のパスから取り出してもよい。ユーザインタフェース３７４は、データウェアハウス１９２へのアクセスをユーザ１３０に提供する。ほんの一例として、ユーザインタフェース３７４は、データウェアハウス１９２の一部として備えられてよい。他の実装においては、ユーザインタフェース３７４は、コマンドをデータウェアハウス１９２に渡してよく、及び／または、データウェアハウス１９２が実行するＳＱＬコマンドを作成してよい。
【０２４６】
図２Ｃにおいて、ユーザインタフェース３７６は、プロキシ３４８を介してクエリエグゼキュータ３４４と通信する。クエリエグゼキュータ３４４は、一部のクエリをデータウェアハウス１９２に渡してよい。様々なクエリについて、クエリエグゼキュータ３４４は、ストレージ処理モジュール３６０とメタデータサービス３４０からのデータに基づいて、クエリの一部を行ってよく、クエリの他の部分をデータウェアハウス１９２に渡してよい。クエリエグゼキュータ３４４は、結果を組み合わせ、組み合わせた出力をプロキシ３４８に渡してよい。様々な実装において、ユーザインタフェース３７６は一部の関係またはデータがデータウェアハウス１９２またはインデックスストレージ３２４に記憶されているか否かを、ユーザ１３０に対して透明にしてよい。この特徴は、何らかのデータを既にデータウェアハウス１９２に記憶しており、かつ、インデックスストレージ３２４に新しいデータをロード中またはその逆を行っている、カスタマーに関係してよい。
【０２４７】
図２Ｄは、ユーザインタフェース３７６の実装例の高レベル機能ブロック図である。スキーマ表現モジュール３７８は、スキーマ監視モジュール３８０からスキーマデータを受信する。スキーマ監視モジュール３８０は、メタデータサービス３４０から関係スキーマに関する情報を受信する。表示モジュール３８２は、１つまたは様々なフォーマットで、ユーザ１３０にスキーマを表示する。例えば、ネストされた属性の階層は、リスト形式においてインデントのレベルで示してよい。あるいは、視覚的なツリーフォーマットを用いてよい。
【０２４８】
メタデータサービス３４０がスキーマ監視モジュール３８０にスキーマの変更を知らせると、スキーマ表現モジュール３７８は、新しい属性、新たなサブ属性等を挿入することによって、スキーマを更新してよい。例えば、新たな中間ノード及び新たなリーフノードを含む、新たなノードをツリーに追加してよい。スキーマが変わるにつれて、リーフノードは中間ノードに変換されてよく、属性の型の変化は、色、ラベル、または、二次的な印で視覚的に表されてよい。ほんの一例として、二次的な印は、（例えば、マウスまたはトラックパッドを用いて）属性の上にカーソルをホバリングした時に現れてよい。
【０２４９】
スキーマに変更が加えられるとき、表示モジュール３８２は、表示領域の中心に現在表示されているスキーマに焦点を当て続けようとしてよい。ほんの一例として、多くの新しい属性が、リストされたスキーマの最初に追加される場合、前からリストされている属性は、画面上で下に移動し得る、または、画面上から見えなくなる場合がある。この視覚的に破壊的な変更に対処するために、表示モジュール３８２は、適切に一定の中央位置を維持するように属性のリストをスクロールしてよい。スキーマに追加された要素は、輪郭で囲む、シャドーイング、色、フォント（大文字、イタリック体、サイズ）などで、視覚的に表してよい。
【０２５０】
ほんの一例として、色のグラデーションで、スキーマ要素が、どのくらい最近、変化したのかを示してよい。ほんの一例として、非常に鮮やかな青は、最近変更されたスキーマ要素を示してよく、青が薄くなって最終的には白になることは、長い間、存在したスキーマ要素であることを示す。
【０２５１】
様々な実装において、表示モジュール３８２は、表示モジュール３８２の要素にユーザがフォーカスしている時を決定するために、マウスの動き、キーボードの使用、オペレーティングシステムのどのウィンドウにフォーカスしているか、及び、節電のために表示をブランクにしているか否かを追跡してよい。例えば、ユーザが、この一時間、表示モジュール３８２と対話しなかったと、表示モジュール３８２が決定する場合、表示モジュール３８２は、この一時間に追加された全てのスキーマ要素を鮮やかな青のままにしてよい。ユーザが、もう一度、表示モジュール３８２と対話を開始した時点で、鮮やかな青は、薄くなり始めてよい。このように、積極的に表示モジュール３８２を監視していたか否かに関わらず、ユーザが最後に表示モジュール３８２と対話した後のメタデータへの変化に注意を向けさせるようになっている。
【０２５２】
ユーザインタフェース３７６は、１つまたは複数のクエリの結果を表示する結果表現モジュール３８４も含む。結果は、テーブル、チャート、及び、グラフを含む、テキスト形式及びグラフィック形式の組み合わせで表示されてよい。視覚的表現の種類は、アクセスラベル、線形または対数スケーリング、及び、チャートタイプを選択することができ、ユーザによって選択されてよい。クエリエグゼキュータ３４４は、クエリ完了前に、結果の提供を始めてよい。
【０２５３】
結果監視モジュール３８６は、結果がさらに入手可能な時、クエリエグゼキュータ３４４によって通知される。そうすると、結果表現モジュール３８４は、結果のビューを更新し、表示モジュール３８２に提示する。様々な他の実装において、結果監視モジュール３８６は、追加の結果が入手可能な時を決定するためにクエリエグゼキュータ３４４にポーリングしてよい。クエリエグゼキュータ３４４は、タイムスケジュールで、または、処理されたレコードの数などの別のメトリクスに基づいて、これらの増分結果を提供してよい。結果監視モジュール３８６が追加の結果を検出すると、結果表現モジュール３８４は、その追加データを収容するために軸のスケーリングの調整が必要な場合があり、バーチャートやパイチャートに追加のバーやスライス（項目）を追加してよく、及び、チャートの要素に割り当てられた値を調整してよい。
【０２５４】
単純化した実施例として、データセットの各学年レベルに関する平均ＧＰＡを要求するクエリを考える。クエリエグゼキュータ３４４がデータを処理すると、最初の結果は、初期のレコードの平均ＧＰＡを表示する。追加のレコードが構文解析されると、ＧＰＡは更新されてよい。さらに、クエリでまだ観察されていない学年レベルが、結果表現モジュール３８４によって結果に追加されることになる。
【０２５５】
様々なアプリケーションにおいて、また、様々なデータセットについて、かなりの数のレコードがまた構文解析されていない間に、平均等の様々なメトリクスが収束し始めてよい。これによって、データ傾向の高速な視覚化が可能になり、また、クエリの完了を待たずに、ユーザによるクエリの調整もしくはクエリの再編成が可能になり得る。これは、分単位または時間単位など、実行に時間がかかるクエリについて、特に価値があると思われる。一部のクエリに関しては、最初の結果を見て、ユーザに関連する結果を返すためにクエリの再形成が必要であることを、ユーザに示してよい。
【０２５６】
単純化した実施例に戻ると、ＳＱＬクエリは、“ＳＥＬＥＣＴｓｔｕｄｅｎｔ＿iｄ，ａｖｇ（ｇｐａ）ＦＲＯＭ  ｓｔｕｄｅｎｔｓ  ＧＲＯＵＰ  ＢＹ  ｃｌａｓｓ  ＯＲＤＥＲ  ＢＹ  ２  ＤＥＳＣＥＮＤＩＮＧ；”の形をとってよい。
【０２５７】
クエリ管理モジュール３８８は、表示モジュール３８２でユーザが入力したクエリをクエリエグゼキュータ３４４に供給する。クエリ管理モジュール３８８は、以前実行したクエリを記憶し、それらのクエリの再実行を可能にしてよい。さらに、クエリ管理モジュール３８８は、ユーザによる複合クエリの構築、及び／または、前のクエリの結果の組み合わせを支援してよい。
【０２５８】
図２Ｅにおいては、高レベル機能図が、複数ノード４０２‐１、４０２‐２、及び、４０２‐３（集合的に、ノード４０２）を有するストレージサービス３５６を示す。３つのノード４０２を示すが、使用するノードの数は３つより多くても少なくてもよく、分析フレームワークのニーズに基づいて動的に変更されてよい。ノード４０２の数は、記憶する必要のあるデータが多くなるにつれて、また、クエリ実行、及び／または、冗長性提供のために追加処理が要求されるのに応答して、増やされてよい。クエリエクゼキュータ３４４を、ノード４０６‐１、４０６‐２、及び、４０６‐３（集合的に、ノード４０６）と共に示す。ノード４０６の数も、クエリ負荷に基づいて動的に変更することができ、ノード４０２の数と無関係である。
【０２５９】
図２Ｆにおいて、ストレージサービス３５６は、データウェアハウス１９２にロードするデータを供給してよい。メタデータサービス３４０は、関係スキーマをデータウェアハウス１９２に供給してよく、データウェアハウス１９２は、その関係スキーマからテーブルを定義できる。データウェアハウス１９２は、単なるストレージを超えて、複数の機能構成要素を備えてよい。備える機能構成要素には、クエリエグゼキュータ４２０及びＯＤＢＣインターフェース４２４が含まれるが、それらに限定されない。ユーザインタフェース３７６は、データウェアハウス１９２と通信する。様々な実装において、ユーザインタフェース３７６は、図２Ｅのクエリエグゼキュータ３４４とも通信してよい。
【０２６０】
プロキシ３４８は、ＯＤＢＣクライアント３５２とクエリエクゼキュータ３４４との間のインターフェースを提供する。クエリエクゼキュータ３４４は、メタデータサービス３４０と対話する。メタデータサービス３４０は、ストレージサービス３５６内にあるデータのスキーマを記憶する。
【０２６１】
プロセス
図３は、データ採集プロセスの例を示す。制御は５０４で始まり、ここで、ユーザまたはアドミニストレータなどによって、データソースを指定することができる。さらに、データソースから一定のデータセットを選択してよく、一定のサブセッティング操作及び低減操作をデータソースに要求してよい。制御は５０８に続き、ここで、指定されたデータソースは、新しいデータを求めて監視される。
【０２６２】
５１２において、新しいデータオブジェクトがデータソースに追加されている場合、制御は５１６に移る。追加されていない場合、制御は５０４に戻って、必要に応じてデータソースの修正が可能なようにする。５１６において、新しいオブジェクトのスキーマが推論される。推論は、図４に示すような型関数に従って行われてよい。５２０において、５１６で推論されたスキーマが、既に存在しているスキーマとマージされる。マージは、図５に示すようなマージ関数に従って行われてよい。
【０２６３】
５２４において、装飾が求められる場合、制御は５２８に移り、そうではない場合、制御は５３２に移る。５２８において、マップが、図８に示されるように、データ内で識別される。５３６において、新たなマップが識別されない場合、制御は５３２に続き、新たなマップが識別された場合、制御は５４０に移る。５４０において、マップインデックスが求められる場合、制御は５４４に移り、そうではない場合、制御は５３２に続く。５４４において、新たなマップ属性と関連付けられたＢｉｇＩｎｄｅｘまたはＡｒｒａｙＩｎｄｅｘの各値について、その値は、マップインデックスに追加される。さらに、ユーザ及び／またはアドミニストレータが求める場合、特定の属性について、値が値インデックスに追加される。制御は次に５３２に続く。
【０２６４】
様々な実装において、５２４における装飾は、オブジェクトの第１のラウンドが処理されるまで待機してよい。例えば、初期採集時、装飾は、初期オブジェクトの全てが採集されるまで遅延されてよい。このようにして、マップのヒューリスティックスが使用するための十分な統計が収集される。追加オブジェクトの増分採集については、装飾は、追加オブジェクトの各新しいグループの後に実行されてよい。
【０２６５】
５３２において、ＪＳＯＮスキーマが新しいオブジェクトの結果として変更された場合、制御は５４８に移り、ここで、スキーマは関係スキーマに変換される。制御は５５２に続き、ここで、１対１関係を平坦化することなどによって、関係ビューが最適化される。制御は次に５５６に続く。スキーマが５３２で変更されていない場合、制御は直接、５５６に移る。５５６において、インデックスは、新しいオブジェクトのデータをポピュレートされる。これは図７に示すように行われてよい。制御は次に５０４に戻る。
【０２６６】
インデックスのポピュレーションは、５４８で推論されたスキーマを関係スキーマに変換した後に実行されるとして、５５６に示しているが、様々な実装において、関係スキーマが要求されないので、インデックスは、関係スキーマの生成前にポピュレートされてよい。手順は、推論されたＪＳＯＮスキーマを用いて、経路及び結合キーを生成することができる。関係スキーマは、基礎的半構造データの関係ビューとして機能する。
【０２６７】
図４は、再帰に依存する型関数の実装例を示す。制御は６０４で始まり、ここで、型付けするオブジェクトがスカラである場合、制御は６０８に移る。６０８において、スカラの型が決定され、そのスカラ型は、６１２で関数の出力として戻される。スカラ型は、受信されたオブジェクトにおける自己記述に基づいて決定されてよい。さらに、一定の文字列が日付または時間などのデータを表すことを認識し得る更なる型付け規則が、使用されてよい。
【０２６８】
６０４において、オブジェクトがスカラではない場合、制御は６１６に移る。６１６において、オブジェクトが配列である場合、制御は６２０に移り、ここで、型関数（図４）は、配列の各要素に対して再帰的に呼び出される。これらの型関数の結果が受信されると、制御は６２４に続き、ここで、図６に示すような折り畳み関数が、６２０で決定された要素型の配列に対して呼び出される。折り畳まれた配列が折り畳み関数によって返されると、その折り畳まれた配列が、６２８で型関数によって返される。
【０２６９】
６１６において、オブジェクトが配列ではない場合、制御は６３２に移る。６３２において、型関数（図４）は、オブジェクトの各フィールドに対して再帰的に呼び出される。制御は６３６に続き、ここで、折り畳み関数は、６３２で決定されたフィールド型の連結に対して呼び出される。折り畳み関数によって返された折り畳まれたオブジェクトは、次に、６４０において型関数によって返される。
【０２７０】
図５は、２つのスキーマ要素を単一のスキーマ要素にマージするマージ関数の実装例を示す。マージ関数も再帰的であり、最初に呼び出されるとき、２つのスキーマ要素は、既存のスキーマと、新たに受信されたオブジェクトから推論された新しいスキーマと、である。マージ関数の更なる再帰的呼び出しでは、スキーマ要素は、これらのスキーマのサブ要素である。制御は７０４で始まり、ここで、マージしようとするスキーマ要素が等価である場合、制御は７０８に移り、等価なスキーマ要素のいずれか１つを返す。そうではない場合、制御は７１２に移り、ここで、マージしようとするスキーマ要素が両方とも配列である場合、制御は７１６に移り、そうではない場合、制御は７２０に移る。
【０２７１】
７１６において、マージしようとする配列の一方が空である場合、他方の配列は７２４で返される。そうではない場合、制御は７２８に続き、ここで、図６に示すような折り畳み関数が、マージしようとする両方の配列の要素を含む配列に対して呼び出される。折り畳み関数によって返された折り畳まれた配列は、次に、７３２でマージ関数によって返される。
【０２７２】
７２０において、マージしようとするスキーマ要素の一方が空である場合、他方のスキーマ要素は、７３６でマージ関数によって返される。マージしようとする両方のスキーマ要素が空でない場合、制御は７４０に続き、ここで、折り畳み関数が、マージしようとする両方のスキーマ要素のキーと値のペアを含むオブジェクトに対して呼び出される。折り畳み関数によって返された折り畳まれたオブジェクトは、次に、７４４でマージ関数によって返される。
【０２７３】
図６は、折り畳み関数の実装例を示す。制御は８０４で始まり、ここで、折り畳もうとするオブジェクトが配列である場合、制御は８０８に移り、そうではない場合、制御は８１２に移る。８０８において、配列が、両方とも配列である値のペアを含む場合、制御は８１６に移り、そうではない場合、制御は８２０に続く。８２０において、配列が、両方ともオブジェクトである値のペアを含む場合、制御は８１６に移り、そうではない場合、制御は８２４に続く。８２４において、配列が、等しいスカラ型である値のペアを含む場合、制御は８１６に移り、そうではない場合、折り畳みが完了し、配列が折り畳み関数から返される。８１６において、図５に示すようなマージ関数が、８０８、８２０、または８２４によって識別された値のペアに対して呼び出される。制御は８２８に続き、ここで、値のペアは、マージ関数によって返された単一の値で置き換えられる。
【０２７４】
８１２において、オブジェクト内のキーのいずれかが同じである場合、制御は８３２に移り、そうではない場合、折り畳みが完了し、オブジェクトは返される。８３２において、制御は、同じキーのペアを選択し、８３６に続く。キーのペアについての値が両方とも配列であるか、両方ともオブジェクトである場合、制御は８４０に移り、そうではない場合、制御は８４４に移る。８４０において、キーのペアの値に対してマージ関数が呼び出される。制御は８４８に続き、ここで、キーのペアが、マージ関数によって返された値を有する単一キーで置き換えられる。制御は、次に８５２に続き、ここで、いずれかのキー同士がさらに同じである場合、制御は８３２に移り、そうではない場合、折り畳みは完了し、修正されたオブジェクトが返される。８４４において、キーのペアの値が両方ともスカラである場合、制御は８５６に移り、そうではない場合、制御は８５２に移る。８５６において、キーのペアの値のスカラ型が等しい場合、制御は、それらのキーのペアをマージするために８４０に移り、そうではない場合、制御は８５２に移る。
【０２７５】
図７は、新たに取り出したオブジェクトからのデータをインデックスにポピュレートするプロセスの例を示す。制御は９０４で始まり、ここで、ＲｏｗＩｎｄｅｘが求められる場合、制御は９０８に移り、そうではない場合、制御は９１２に移る。９０８において、オブジェクトが、上記のようにＲｏｗＩｎｄｅｘに追加され、制御は９１２に続く。９１２において、オブジェクトは、現在の関係スキーマについて関係タプルに平坦化され、結合キーが必要に応じて作成される。制御は９１６に続き、ここで、制御は、インデックスに追加する更なるタプルが存在するか否かを決定する。存在する場合、制御は９２０に移り、存在しない場合、インデックスはポピュレート済みであり、制御は終了する。
【０２７６】
９２０において、制御は、タプルが配列表についてのものであるか否かを決定する。そうである場合、制御は９２４に移り、そうではない場合、制御は９２８に移る。９２４において、配列表内に更なる値カラムがある場合、制御は９３２に移る。９３２において、カラム値が元の取り出したオブジェクト内に存在する場合、９３６において、その値はＡｒｒａｙＩｎｄｅｘに追加される。制御は、次に９４０に続く。ＶａｌｕｅＩｎｄｅｘがカラムについて求められる場合、制御は９４４に移り、そうではない場合、制御は９２４に戻る。カラム値が、９３２で元の取り出したオブジェクト内に存在しない場合、制御は９２４に戻る。
【０２７７】
９２８において、タプルがマップテーブルについてのものである場合、制御は９４８に移り、そうではない場合、制御は９５２に移る。９４８において、制御は、更なる値カラムがマップテーブル内に残っているか否かを決定する。残っている場合、制御は９５６に移り、残っていない場合、制御は９１６に戻る。９５６において、制御は、カラム値が元の取り出したオブジェクト内に存在するか否かを決定する。存在する場合、制御は９６０に移り、存在しない場合、制御は９４８に戻る。９６０において、値は、ＭａｐＩｎｄｅｘに追加され、制御は９６４に移る。９６４において、ＶａｌｕｅＩｎｄｅｘがカラムについて求められる場合、値は、９６８においてＶａｌｕｅＩｎｄｅｘに追加される。いずれの場合においても、制御は次に９４８に戻る。
【０２７８】
９５２において、制御は、テーブル内に存在する更なるカラムがあるか否かを決定する。存在する場合、制御は９７２に移り、存在しない場合、制御は９１６に戻る。９７２において、制御は、カラム値が元の取り出したオブジェクト内に存在するか否かを決定する。存在する場合、制御は９７６に移り、存在しない場合、制御は９５２に戻る。９７６では、値がＢｉｇＩｎｄｅｘに追加され、制御は９８０に続く。９８０では、ＶａｌｕｅＩｎｄｅｘがカラムについて求められる場合、制御は９８４に移り、ここで、値がＶａｌｕｅＩｎｄｅｘに追加される。いずれの場合においても、制御は次に９５２に戻る。
【０２７９】
図８は、マップを識別するプロセスの例を示す。制御は、１００４で始まり、ここで、第１のオブジェクトが選択される。制御は１００８に続き、ここで、オブジェクトが空である場合、１０１２において、含有オブジェクトがマップとして指定され、空でない場合、制御は１０１６に移る。１０１６において、制御は、上記のような含有オブジェクトの頻度に対する平均フィールド頻度の比率を決定する。制御は１０２０に続き、ここで、比率が閾値未満である場合、制御は１０１２に移って、マップとして含有オブジェクトを指定する。閾値以上の場合、制御は１０２４に移る。ほんの一例として、閾値は、ユーザが調整可能であってよく、及び／または、観察データに基づいて動的であってよい。様々な実装において、関係スキーマとしてのマップが多くなるにつれて、ヒューリスティックスは、フィールドをより容易に識別するように調整されてよい。１０１２において、含有オブジェクトがマップとして指定され、制御は１０２４に続く。評価すべきオブジェクトが更にある場合、制御は１０２８に移り、ここで、次のオブジェクトが選択され、制御は１００８に続き、ない場合、制御は終了する。
【０２８０】
図９は、関係スキーマの作成を再帰に依存するｃｒｅａｔｅ＿ｓｃｈｅｍａ関数の実装例を示す。ｃｒｅａｔｅ＿ｓｃｈｅｍａ関数が呼び出されると、制御は、スキーマ要素（Ｓｃｈｅｍａ＿Ｅｌｅｍｅｎｔ）をテーブル（Ｃｕｒｒｅｎｔ＿Ｔａｂｌｅ）に組み込む。この目的のために、制御は１１０４で始まり、ここで、Ｓｃｈｅｍａ＿Ｅｌｅｍｅｎｔがオブジェクトである場合、制御は１１０８に移り、そうではない場合、制御は１１１２に移る。１１０８では、オブジェクトが空のオブジェクトである場合、オブジェクトはマップとして扱われ、制御は１１１６に移り、そうではない場合、制御は１１２０に続く。１１２０では、新しいテーブル（Ｎｅｗ＿Ｔａｂｌｅ）がネストされたオブジェクトのために作成される。１１２４において、結合キー（Ｊｏｉｎ＿Ｋｅｙ）が、Ｃｕｒｒｅｎｔ＿Ｔａｂｌｅに追加され、１１２８において、対応するＪｏｉｎ＿Ｋｅｙが、Ｎｅｗ＿Ｔａｂｌｅに追加される。制御は次に１１３２に続き、ここで、ネストされたオブジェクトの各フィールドについて、ｃｒｅａｔｅ＿ｓｃｈｅｍａ関数が、フィールドをテーブルに追加するために再帰的に呼び出される。制御は、次に１１３６においてｃｒｅａｔｅ＿ｓｃｈｅｍａ関数の現在の呼び出しから戻る。
【０２８１】
１１１２において、Ｓｃｈｅｍａ＿Ｅｌｅｍｅｎｔがマップである場合、制御は１１１６に移り、そうではない場合、制御は１１３８に移る。１１１６において、新しいテーブル（Ｎｅｗ＿Ｔａｂｌｅ）がマップのために作成される。制御は１１４０に続き、ここで、Ｊｏｉｎ＿Ｋｅｙが、Ｃｕｒｒｅｎｔ＿Ｔａｂｌｅに追加され、１１４４において、対応するＪｏｉｎ＿Ｋｅｙが、Ｎｅｗ＿Ｔａｂｌｅに追加される。１１４８において、文字列型を有するキーフィールドが、Ｎｅｗ＿Ｔａｂｌｅに追加される。制御は１１５２に続き、ここで、マップの各値型について、ｃｒｅａｔｅ＿ｓｃｈｅｍａ関数が、値型をＮｅｗ＿Ｔａｂｌｅに追加するために再帰的に呼び出される。制御は次に１１３６に戻る。
【０２８２】
１１３８において、制御は、Ｓｃｈｅｍａ＿Ｅｌｅｍｅｎｔが配列であるか否かを決定する。配列である場合、制御は１１５６に移り、配列でない場合、制御は１１６０に移る。１１５６において、新しいテーブル（Ｎｅｗ＿Ｔａｂｌｅ）が配列のために作成され、１１６４において、Ｊｏｉｎ＿ＫｅｙがＣｕｒｒｅｎｔ＿Ｔａｂｌｅに追加され、１１６８において、対応するＪｏｉｎ＿ＫｅｙがＮｅｗ＿Ｔａｂｌｅに追加される。１１７２において、整数型を有するインデックスフィールドが、Ｎｅｗ＿Ｔａｂｌｅに追加される。制御は１１７６に続き、ここで、配列の各アイテム型について、アイテム型をＮｅｗ＿Ｔａｂｌｅに追加するためにｃｒｅａｔｅ＿ｓｃｈｅｍａ関数が呼び出される。制御は次に１１３６に戻る。
【０２８３】
１１６０において、消去プロセスによって、Ｓｃｈｅｍａ＿Ｅｌｅｍｅｎｔは、プリミティブである。プリミティブと同じ名前を有するＣｕｒｒｅｎｔ＿Ｔａｂｌｅに既にフィールドがある場合、制御は１１８０に移り、そうではない場合、制御は１１８４に移る。１１８４において、名前フィールドがＣｕｒｒｅｎｔ＿Ｔａｂｌｅに単純に加えられ、制御は１１３６に戻る。１１８０において、型多様性が存在するので、プリミティブと同じ名前を有するＣｕｒｒｅｎｔ＿Ｔａｂｌｅの既存のフィールドが、名前を変更されて、それらの型をフィールド名に追加する。制御は１１８８に続き、ここで、新しいフィールドが現在のプリミティブに基づいて追加され、型はフィールド名に添えられる。制御は次に１１３６に戻る。
【０２８４】
図１０Ａにおいて、制御は、１２０４で開始し、ここで、ユーザまたはアドミニストレータは、データのソースを指定及び／または修正する。１２０８において、制御は、そのデータからスキーマを推論し、上記に詳述したように、推論中のスキーマをインデックスにポピュレートする。１２１２において、制御は、装飾が求められているか否かを決定する。装飾を求めるか否かは、ユーザまたはアドミニストレータによって設定されてよい。求めている場合、制御は、１２１６に移り、求めていない場合、制御は１２２０に移る。１２１６において、制御は、スキーマ内のマップを識別し、識別したマップを反映するようにスキーマを更新する。ユーザ及び／またはアドミニストレータからの設定に基づいて、一定の識別されたマップは、ユーザ及び／またはアドミニストレータによって、別個のカラムに手動で戻すことができる。これは、採集時、または、データ使用時のいつでも、行ってよい。マップが識別され、マップインデックスが作成されると、データは、マップインデックス内にとどまってよく、その結果、スキーマは、マップを反映することができる、または、カラムを個別に反映することができる、また、ユーザまたはアドミニストレータは、データをリロードすることなしに、これらの構成の間を切り替えることができる。制御は１２２０に続く。１２２０においては、制御は、推論されたスキーマを関係スキーマに変換する。１２２４において、制御は、使用中の特定のデータウェアハウスが認識可能なフォーマットにデータをパッケージ化する。１２２８において、関係スキーマに従ったテーブルが、データウェアハウス内に作成される。ほんの一例として、ＳＱＬ  ｃｒｅａｔｅ  ｔａｂｌｅコマンドを用いてよい。１２３２において、パッケージ化されたデータは、データウェアハウスにバルクロードされる。データウェアハウスが、並列にバルクロードできる場合、１２２４におけるデータのパッケージ化は、１２３２のバルクロードを速めるために、各データベース関係について複数のファイルを作成してよい。
【０２８５】
図１０Ｂにおいて、インデックスストアが現在この特定の時に、利用できない、満杯、または、求められない場合、修正されたプロセスが用いられてよい。１２０４の後、１２５０において、データのスキーマを推論する。図１０Ａと異なり、データは、インデックスのポピュレートに使用されない。１２２０の後、１２２８において、関係スキーマに従ったテーブルがデータウェアハウス内に作成される。制御は、１２５４に続き、ここで、第２のパスがデータに対して実行され、データウェアハウスにローカルロードするための中間ファイルが作成される。制御は、次に１２３２に続き、ここで、バルクロードがデータウェアハウスに再形成される
【０２８６】
図１１は、データウェアハウスがサポートする分析プラットフォームに新しいデータを統一するプロセスの例を示す。１３０４において、制御は、新しいデータが、指定されたデータソースから受信されたか否かを決定する。そうである場合、制御は、１３０８に移る。そうでない場合、制御は、１３０４にとどまる。１３０８において、制御は、新しいデータのスキーマを推論し、新しいデータをインデックスにポピュレートする。制御は１３１２に続き、ここで、制御は、新しいデータのスキーマが既に存在するスキーマのサブセットであるか否かを決定する。そうである場合、制御は１３１６に続き、そうでない場合、制御は、１３２０に移る。１３２０において、新しいスキーマは、既存のスキーマとマージされ、制御は１３２４に続く。１３２４において、制御は、装飾が求められているか否かを決定し、求められている場合、制御は１３２８に移り、求められていない場合、制御は１３３２に移る。１３２８において、制御は、新しいデータに基づいてマップを識別する。これらの識別されたマップは、新しいデータが、マップ基準に従ったマップとしてみなされる属性を生じる場合には、新しいデータと以前のデータとを含んでよい。追加のマップが識別される場合、スキーマは更新される。そして、制御は１３３２に続く。１３３２において、マージされたスキーマは、関係スキーマに変換される。１３３６において、テーブルは、データウェアハウス内で修正され、及び／または、新しいテーブルが作成される。１３４０において、ユーザインタフェースは、スキーマが更新されたことと、従って、ユーザインタフェースは、更新されたスキーマをユーザに表示すべきであることとを、知らされる。そして、制御は、１３１６に続く。１３１６において、制御は、インデックスからバルクロードのために新しいデータをパッケージ化する。制御は１３４４に続き、ここで、新たにパッケージ化されたデータのデータウェアハウスへのバルクロードを行う。制御は次に１３０４に続く。
【０２８７】
図１２は、ユーザインタフェース操作の高レベルの概略図の例である。制御は１４０４で開始し、ここで、推論された関係スキーマがユーザに提示される。制御は１４０８に続き、ここで、スキーマが変更されている場合、制御は１４１２に移り、そうでない場合、制御は１４１６に移る。１４１２において、制御は、ユーザインタフェースで、表示されたスキーマを更新し、１４２０に続く。１４２０において、制御は、オプションで、スキーマへの変更をグラフィカルに識別する。ほんの一例として、最近変更されたスキーマ要素は、視覚的にハイライト表示されてよい。様々な実装において、ユーザインタフェースは、最後のクエリがいつ実行されたかに基づいて、スキーマ要素が最近変更されたか否かを決定してよい。ほんの一例として、最後のクエリが実行されてから変更されたスキーマ要素は、特に、ハイライト表示されてよい。制御は次に１４１６に続く。１４１６において、新たなクエリがユーザによって要求されている場合、制御は１４２４に移り、要求されていない場合、制御は１４２８に移る。１４２４において、制御は、実行されたクエリからのクエリ結果の表示を開始する。これらの結果は、一定のローもしくはカラムが抜けている、及び／または、不正確もしくは部分的に不正確なデータを有するなど、不完全な場合がある。制御は１４２８に続く。１４２８において、進行中のクエリから追加のクエリ結果がある場合、制御は１４３２に移る。ない場合、制御は１４０８に戻る。１４３２において、制御は、追加の結果を用いてインターフェースを更新する。制御は１４３６に続き、ここで、データのプロットが表示されている場合、軸の再スケーリングや再ラベル付けを行うなど、チャートの様々な態様を修正してよい。制御は１４４０に続き、ここで、制御は、クエリ結果への変更をグラフィカルに識別する。ほんの一例として、繰り返し変更されたクエリ結果はハイライト表示される。様々な実装において、大きな割合で、または、大量に変更されたクエリ結果は、より顕著にハイライト表示されてよい。さらに、新しいカラム及び／または新しいローを一意的に識別してよい。さらに、クエリ結果の傾向を視覚的に表すために、ゴースト及び／または色付けによって、現在の値と、以前表示した値とを示してよい。制御は次に１４０８に戻る。
【０２８８】
グラフィカルユーザインタフェース
図１３Ａにおいて、グラフィカルユーザインタフェースは、左側のウィンドウ枠に推論したスキーマを表示し、右側のウィンドウ枠に、クエリとクエリ結果を示す。これらの例においては、ツイッター属性の表現の例を提示している。
【０２８９】
図１３Ｂにおいては、図１３Ａの後、追加された関係スキーマ属性が現れていることに留意する。詳細には、ｉｎ＿ｒｅｐｌｙ＿ｔｏで始まる属性が、これらの属性を含んだ追加のデータが構文解析されていることに基づいて、ユーザインタフェースに動的に追加された。図１３Ｃは、ネストされたオブジェクトの表現を１つ示している。詳細には、ユーザというノードの下に、属性が示されている。
【０２９０】
図１３Ｄは、データのテーブルによる表現を提示している。この表示においては、クエリによって１０の言語が見つかった。図１３Ｅにおいては、２４の言語が見つかった。この特定の例においては、元の１０の言語のカウントは変わらず、図１３Ｄの表示と図１３Ｅの表示との間に構文解析されたレコードは、図１３Ｄの最初の１０で示されていない追加の言語であることを示している。
【０２９１】
図１３Ｂにおいて、追加の属性は、図１３Ａで示された表示の次の表示に動的に追加された。図１３Ｅにおいて、追加のクエリ結果は、図１３Ｄに示す表示の次の表示に動的に追加された。
【０２９２】
自動化された抽出、変換、ロード（ＥＴＬ）
上記に、スキーマ推論を紹介した。スキーマ推論は、半構造オブジェクト（一定の実装においては、ＪＳＯＮドキュメント）のコレクションから累積（または、グローバル）スキーマ（一定の実装においては、ＪＳＯＮスキーマとも呼ばれる)を抽出する。この累積スキーマは、さらなる入力が入手されると、増分的に更新される。累積スキーマは、マップまたは配列に属するエンティティのセットを指定するように装飾されてよい。このような累積スキーマの作成、及び、累積スキーマに基づいたデータの処理は、従来の抽出、変換、ロード、（ＥＴＬ）プロセスの一部として、または、そのプロセスに替えて有利に使用することができる。結果として生じるＥＴＬプロセスは、スピード、忠実度、ユーザビリティのうちの１つまたは複数において改善が見られる。
【０２９３】
一般論として、ＥＴＬは、選択されたデータセットに一定の変換が行われるオプションとしての変換段階を備えた、１つまたは複数のソース位置から１つまたは複数の宛先位置へのデータの移動を管理するプロセスを指す。変換は宛先の１つの入力フォーマットに従うために必要な場合もある。ソース及び宛先は、関係データベース、オブジェクトストア（例えば、ＮｏＳＱＬまたはキーと値のストア）、または、それらのデータベースもしくはストアのフォーマットに従うデータのレポジトリ（例えば、ＣＳＶもしくはＪＳＯＮデータを含むファイルもしくはドキュメントを記憶する、ローカルもしくは分散ファイルシステム、または、クラウドストア)であってよい。
【０２９４】
ＥＴＬの忠実度は、データ項目がどれくらい正確にソースから宛先にマップされるかで定義することができる。例えば、データ項目ａ、ｂ、ｃをソースから宛先にロードすることを課され、結果として項目ｂ、ｃが宛先に存在するＥＴＬプロセスは、結果として項目ＣだけがロードされたＥＴＬプロセスより忠実である。
【０２９５】
ＥＴＬのユーザビリティは、ロードされたデータの一部を入力として用いるタスクを宛先コンピュータシステムで行う際に、ユーザ及びコンピュータシステムの両方が行うステップの（削減された）数で測ることができる。例えば、ソースから宛先に結果的にデータ項目ｂ、ｃをロードする２つの異なるＥＴＬプロセスについては、その２つの項目の最大のものを宛先システムで計算するステップの数が一方のプロセスの方が少なければ、ユーザビリティが異なると言える。
【０２９６】
上記のように、半構造データは、関係形式に変換して、インデックス付きカラム型ストレージをサポートするシステムにロードすることができる。カラム型ストレージに加えて、または、その代わりに、データは、複数のターゲットにロードすることができる。これは、１つまたは複数の（可能であれば、半構造)ソースからデータを取得し、オプションで、１つまたは複数の変換を行い、そのデータを１つまたは複数の（可能であれば、関係）ターゲットにロードするフレキシブルなＥＴＬプロセスを記述するように一般化することができる。様々な実装において、ＥＴＬプロセスは、中間ストレージのためのインデックスストアを用いてもよく、中間ストアを省略してもよい。
【０２９７】
図１４は、ＥＴＬプロセスの概略を示し、図２Ｂより高いレベルの、より一般化されたバージョンを示す。図１４の左側で、データが１つまたは複数のデータソース（例えば、データソース１５０４、１５０８）からスタートし、データコレクタモジュール１５１２によって、未変換レコードの形で抽出される。データコレクタモジュール１５１２は、その未変換レコードをＪＳＯＮ等の半構造フォーマットで生成してよい。データソース１５０４、１５０８が、ＪＳＯＮオブジェクトを記憶するテキストファイル等の所定のフォーマットのデータを含む場合、データコレクタモジュール１５１２は、ＪＳＯＮオブジェクトは変更しないで渡してよい。様々な実装において、１つまたは複数の追加データコレクタモジュール（図示せず）は、同一のデータソース、または、複数のデータソースからのデータを並列に処理するように実装してよい。さらに、データコレクタモジュールは、スキーマ推論及び統計収集モジュール１５１６とメタデータストア１５４０とが利用可能な形式にデータを徐々に変換するチェーンとして実装してよい。
【０２９８】
収集されたレコードは、スキーマ推論及び統計収集モジュール１５１６に渡される。スキーマ推論及び統計収集モジュール１５１６が決定した累積スキーマに基づいて、データは、１つまたは複数の宛先システム（図１４に示すような、データ宛先システム１５２４、１５２８）に後にロードするために、インデックスストア１５２０にロードすることができる。追加で、あるいは、その代わりに、データは、インデックスストア３２４を迂回して、エクスポートモジュール１５３４経由で、データ宛先システム１５２４または１５２８の１つまたは複数に直接送られてよい。
【０２９９】
変換モジュール１５３６は、データ宛先システム１５２４または１５２８の１つまたは両方にエクスポートモジュール１５３４経由でデータを記憶する前に、インデックスストア１５２０からのデータに１つまたは複数の変換を行うように実装してよい。あるいは、変換モジュール１５３６は、インデックスストアを迂回して、スキーマ推論及び統計収集モジュール１５１６から直接受信したデータを変換してよい。
【０３００】
エクスポートモジュール１５３４は、採集コマンドに対応しているフォーマットで、データをデータ宛先システム１５２４、１５２８に供給する。ほんの一例として、エクスポートモジュール１５３４は、ＳＱＬベースのデータウェアハウスまたはデータベースのために、テーブルのロー形式でデータを供給してよい。エクスポートモジュール１５３４は、ＪＳＯＮオブジェクトを受け入れるデータ宛先システム１５２４に応答して、ＪＳＯＮオブジェクト等のオブジェクトをデータ宛先システム１５２４に供給してよい。様々な実装において、オブジェクトは、データコレクタモジュール１５１２から、変更されずに渡されてよい。カラムデータを受け入れるデータ宛先システム１５２４に応答して、エクスポートモジュール１５３４は、インデックスストア１５２０からのカラムベースのデータを変更せずに渡してよい。
【０３０１】
メタデータストア１５４０は、データコレクタモジュール１５１２、スキーマ推論及び統計収集モジュール１５１６、インデックスストア１５２０のそれぞれの状態を記録する。スケジューリングモジュール１５４４は、ジョブを、データコレクタモジュール１５１２、スキーマ推論及び統計収集モジュール１５１６、インデックスストア１５２０、エクスポートモジュール１５３４に割り当てる。スケジューリングモジュール１５４４は、図１６Ａ及び１６Ｂに関して以下により詳細に述べる依存性に基づいて、ジョブをスケジュールしてよい。監視システム１５４８は、以下に記載するように、データコレクタモジュール１５１２、スキーマ推論及び統計収集モジュール１５１６、インデックスストア１５２０、変換モジュール１５３６、メタデータストア１５４０、並びに、データ宛先システムの１つまたは複数（図１４の例では、データ宛先システム１５２４)の操作に関する性能及びエラーのデータを記録する。
【０３０２】
複数のソースからデータを抽出
データソース
オブジェクトソース
入力ソースの定義をＥＴＬプロセスに広げてオブジェクトソースを取り扱う。これらのソースは、ＮｏＳＱＬストア、ＭｏｎｇｏＤＢやＣｏｕｃｈｂａｓｅ等のドキュメントストア、Ｒｅｄｉｓ等のデータ構造ストア、Ｃａｓｓａｎｄｒａ、ＨＢａｓｅ、ＤｙｎａｍｏＤＢ等のキー／多値ストアを含むことができる。ファイルストアのファイル内に記憶されたオブジェクトは、追加のオブジェクトソースとして扱うことができる。ファイルに記憶されたオブジェクトは、ＪＳＯＮ、ＢＳＯＮ、Ｐｒｏｔｏｂｕｆ、Ａｖｒｏ、Ｔｈｒｉｆｔ及びＸＭＬを含むことができる。
【０３０３】
様々な実装において、データ抽出のために選択された入力ソースの一部または全ての性質は、自動検出されてよい。異なる種類の入力ソースに対して専用コレクタを用いてよい。簡単にするために、今後の記載では、オブジェクトソースの実施例としてＪＳＯＮドキュメントを用いる。本開示は、ＪＳＯＮドキュメントの代わりに、別のタイプのオブジェクトソースを用いることができ、他のオブジェクトソースとＪＳＯＮ間の１対１マッピングがあってよい。言い換えると、本開示は、それら他のタイプのオブジェクトソースに直接、適用することができる。
【０３０４】
関係ソース
データベース等の関係ソースもソースとして用いてよい。関係ソースからデータを抽出するプロセスは、ある意味では、ＪＳＯＮスキーマから関係スキーマを生成するプロセスを逆に実行すると考えることができる。プロセスは、各ローをオブジェクトに変換するルートテーブルを識別することで始まる。ルートテーブルは、ユーザが指定してもよく、データコレクタプロセスによって自動的に選択されてもよく、以前のヒューリスティックス、または、ユーザもしくはアドミニストレータが提供した規則セットに基づいて、データコレクタプロセスによって選択されてもよい。データコレクタは、ユーザが後に手動で変更を行うことを前提として、ルートテーブルを選択してよい。
【０３０５】
そのルートテーブルのローを、他のテーブルのローと結合して、完全なオブジェクトを作成する。例えば、他のテーブルのローは、外部キー関係、統計的ペアリング、または、ユーザ指示を用いて選択してよい。統計的ペアリングは、統計を用いて、２つのカラム間の値の分布の類似性を検出することによって、実装することができる。タイムスタンプとキーカラムは、特に、関係を予測し得るカラムの候補にふさわしい。親テーブルと子テーブルのロー間に１対１の関係がある場合、子テーブルのローは、単純に、主オブジェクトのネストされたオブジェクトになる。１対多の関係がある場合、ローは、ネストされたオブジェクトの配列の一部になる。このプロセスによって、ＪＳＯＮドキュメントにマップすることができるオブジェクトを作成してよく、その時に、本開示におけるＪＳＯＮ処理の記述が直接適用される。
【０３０６】
実施例として、次のテーブルを考える。
Table: user
Userid, name, age
1, "Nate", 27
2, "Stavros", 87
Table: address
Userid, start, end, city
1, 1995, 2006, Ann Arbor
1, 2006, NULL, Redwood City 
2, 2005, 2007, Cambridge
2, 2007, NULL, San Francisco
【０３０７】
ＪＳＯＮスキーマは、それらのテーブルから次のように推論されてよい。
user : { "userid" : "integer",
"name" : "string",
"age" : "integer",
"address" : [ {
"start" : "integer",
"end" : "integer",
"city" : "string" } 〕
}
【０３０８】
ＪＳＯＮスキーマを用いて、入力テーブルからオブジェクトを作成すると、次のオブジェクトになる。
{ "userid" : 1, "name" : "Nate", "age" : 27,
"address" : [ { "start" : 1995, "end" : 2006",
"city" : "Ann Arbor" },
{ "start" : 2006, "end" : null,
"city" : "Redwood City" } 〕 }
{ "userid" : 2, "name" : "Stavros", "age" : 87,
"address" : [ { "start" : 2005, "end" : 2007",
"city" : "Cambridge" },
{ "start" : 2007, "end" : null,
"city" : "San Francisco" } 〕 } 
【０３０９】
イベント化を通して関係ソースをサポート
一部のケースでは、関係ソースは、単一のルートテーブルに関連付けられていない複数のテーブルを含み得る、または、異なるテーブルの結合方法は、自明でない場合がある。各テーブル（または、テーブルのセット）がタイムスタンプデータを有する少なくとも１つのカラムを含む状況では、コレクタプロセスは、テーブルのセットを次のように、「イベントにする」ことができる（「イベント化」と称する)。カラムとして入力テーブルからの全てのカラムの統合（複数のテーブルに現れる同じカラム名は、新しいテーブルでは、その名前を有する単一のカラムになり得る）と、”ｅｖｅｎｔ”と”ｔｉｍｅ”という少なくとも２つのカラムと、を有する新たな論理的または物理的なイベントテーブルを作成する。これらの名前は、既存のテーブルのカラム名との競合を避けるために、イベント化時に、プログラム的に(所定の接頭辞及び／または接尾辞を有するなど)変更することができる。
【０３１０】
新しいテーブルに、入力テーブルのセットの各テーブルからローをポピュレートする。インポートされたローに存在しない新しいテーブルのカラムについては、ヌル値を用いることができる。”ｅｖｅｎｔ”カラムは、ローのインポート元の入力テーブルの名前を値として用いる。”ｔｉｍｅ”カラムは、イベント化されたテーブルのソート順を特定する。”ｔｉｍｅ”カラムに入力テーブルの対応するローからタイムスタンプ情報をポピュレートする。
【０３１１】
ソーステーブルにタイムスタンプデータを有する複数のカラムがある場合、“ｔｉｍｅ１”、“ｔｉｍｅ２”等、複数の”ｔｉｍｅ”カラムを追加することができる。各“ｔｉｍｅ”カラムは、入力テーブルの対応するタイムスタンプカラムによってポピュレートされる。あるいは、タイムスタンプデータを有する入力テーブルのカラムの１つを支配カラム（governing column）として選択し、テーブルのイベント化に用いてよい。入力テーブルのタイムスタンプカラムの選択は、自動規則（例えば、常に、最小の値を選ぶ、または、常に、一番左のカラムを選ぶ）によって、ユーザ入力に基づいて、または、ローが表すイベントが最も起こりそうな時間の導出を支援可能な統計的規則を通して、行われてよい。
【０３１２】
イベント化の実施例として、３つのソーステーブル例の下記のスキーマを考える。
table:user_log {"id": "number", "session_start" :
"timestamp", "session_end" : "timestamp"}
table:query_log {"id": "number", "query_text" : "string",
"query_start" : "timestamp", "duration" : "number"}
table:cpu_load {"time":"timestamp", "load" : "float"}
【０３１３】
イベント化されたテーブルについてのスキーマ例を示す。
table:events { "event" : "string",
"_time" : "timestamp",
"_time2" : "timestamp",
"id": "number",
"session_start" : "timestamp",
"session_end" : "timestamp",
"query_text" : "string",
"query_start" : "timestamp",
"duration" : "number",
"time" : "timestamp",
"load" : "float" }
【０３１４】
各ソーステーブルからの１つのローの例を考える。
user_log : (15213, "01/01/2014 12:15:00",
"01/01/2014 12:15:30")
query_log : (79004525, "select * from T;",
"01/01/2014 10:10:00", 53)
cpu_load : ("01/01/2014 11:20:30", 74.5)
【０３１５】
下記は、イベント化されたテーブルにどのようにポピュレートするかの実施例である。
("user_log", "01/01/2014 12:15:00", "01/01/2014 12:15:30",
15213, "01/01/2014 12:15:00", "01/01/2014 12:15:30",
NULL, NULL, NULL, NULL, NULL),
("query_log", "01/01/2014 10:10:00", NULL, 79004525, NULL,
NULL, "select * from T;", "01/01/2014 10:10:00", 53, 
NULL, NULL),
("cpu_load", "01/01/2014 11:20:30", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "01/01/2014 11:20:30", 74.5)
【０３１６】
イベント化されたテーブルは、スキーマ内の元の位置に従ってタイムスタンプ値を維持するが、１つまたは複数の（この場合は、２つまで）のタイムスタンプを特別な“ｔｉｍｅ”カラムにコピーして、ローをイベント化することに留意する。このようにして、入力の別個のローは、単一の参照“ｔｉｍｅ”カラムを作成しながらも、保存された互いに排他的なタイムスタンプカラムを含んでよい。
【０３１７】
ソース入力での入力テーブルのセットのイベント化は、物理的テーブル(テーブルは具体化される)または論理テーブルとして、存在してよい。論理テーブルについては、イベント化プロセスは、イベント化されたテーブルに属するローのストリームを作成することができ、このストリーム化された入力はＥＴＬプロセスに向けられる。イベント化されたテーブルの各ローは、一定の時間に起こったイベントに関する情報を含むオブジェクトストア内のオブジェクトに類似するので、イベント化によって、関係ソースをオブジェクトソースとして扱うことができる。
【０３１８】
特に、ユーザが、宛先地点でデータにクエリを行って、別々のイベントにわたって情報を抽出したい場合、イベント化によってユーザビリティを向上させることができる。例えば、関係ソースにクエリを行って、一定のタイムスタンプ値（または、値の範囲）を有するローに関する情報を見つけることは、イベント化されたテーブルにクエリを行うよりも複雑で時間がかかり得る。
【０３１９】
データコレクタ
コレクタは、上記データソースの１つまたは複数から個々のレコードを抽出するのに使用可能なソフトウェア構成要素である。標準フォーマット（圧縮可能であってよい、または圧縮不能であってよい、ＪＳＯＮ、ＢＳＯＮ等)の受信ファイルの処理について前述したが、他の機構を用いて、新しいデータを求めてデータソースを監視し、このデータを採集プロセスに送るために抽出することができる。
【０３２０】
ファイルシステムの監視
データが、ファイルシステムにおいて１つまたは複数のディレクトリで提供される場合、コレクタプロセスは、変更を探してファイルシステムを定期的に監視することができる。ファイルシステムは、従来のローカルファイルシステム（例えば、ｅｘｔ４）であってもよく、ファイルシステムのようなインタフェースを有する分散ストア（例えば、ＨＤＦＳ、ＡｍａｚｏｎＳ３）であってもよい。ファイルシステムの正確なインタフェースに応じて、コレクタは、ファイルシステムを定期的にスキャンして、既存のファイルのリストと比べることによって、または、インタフェースに組み込まれた通知機構（例えば、Ｓ３バケットロギング）を用いることによって、新たなファイルを検出することができる。
【０３２１】
定期的なスナップショット
ソースデータが、関係データベース（例えば、ＭｙＳＱＬ、ＰｏｓｔｇｒｅＳＱＬ、Ｏｒａｃｌｅ等）またはＮｏＳＱＬストア（例えば、ＭｏｎｇｏＤＢ、ＣｏｕｃｈＤＢ等）など、ファイルシステム以外の既存のデータストアに記憶されている場合、コレクタは、内蔵スナップショット機構を利用することができる。大抵のデータストアは、データを、ファイルシステムまたは他のプロセスにエクスポートする機構をサポートしている。例えば、ＰｏｓｔｇｒｅＳＱＬは、ＳＱＬ  ＣＯＰＹコマンドをサポートしており、ｐｇ＿ｄｕｍｐという名の外部ユーティリティを利用可能である。この機構を用いると、新たなレコードを採集するために、ソースデータのダンプを定期的に行うことができる。スナップショットは、リモートプロシージャコールを介してコレクタによって、または、ユーザによって開始することができる。全てそろったスナップショットを撮ると、個々のレコードは、複数のスナップショットに現れ得る。このような重複レコードは、ソース固有の主キーを用いるなどして、または、全てそろったレコードが別々であることが確かな場合、比較の目的で、そのレコード全体に対してハッシュ関数を用いることによって、識別、無視してよい、
複製ログ
【０３２２】
複製をサポートする多くのデータストアは、複製されたものが同期されたままであることを保証するのに用いられる操作ログを維持する。このログに外部からアクセスできる場合、コレクタは、ログを用いて新しいデータを直接見つけてよい。例えば、ＭｏｎｇｏＤＢは、ｏｐｌｏｇ（操作ログ）を公開している。ｏｐｌｏｇには、標準ＭｏｎｇｏＤＢ  ＡＰＩを用いてクエリすることができ、データベースにおける、あらゆる挿入、更新、及び、削除操作についてのエントリを含む。このログを読み取ることによって、監視プロセスは、採集が必要な新しいレコードを識別することができる。
データ抽出
【０３２３】
新しいソースデータを検出した時点で、そのデータを採集プロセスに送る方法が幾つかある。データが既にファイル内にある場合、採集プロセスは、単に、ファイルを開いて、データを直接読み取ることができる。ファイルがネットワークにある場合、ＨＤＦＳ（Ｈａｄｏｏｐ分散ファイルシステム)のようなネットワークファイルシステムを用いて、ネットワークを通して遠隔で開いてよい。
【０３２４】
データがまだファイルシステム内にない（例えば、データが複製ログに由来している）場合、コレクタは、新しいレコードを含む１つまたは複数の中間ファイルを作成することができる。これらのファイルは、従来のファイルシステム、または、ＨＤＦＳもしくはＡｍａｚｏｎ  Ｓ３等の分散ストアに記憶してよい。ファイルは、作成されると、上記のようにロードすることができる。
【０３２５】
コレクタは、プロセス間通信（ＩＰＣ：ｉｎｔｅｒ−ｐｒｏｃｅｓｓ  ｃｏｍｍｕｎｉｃａｔｉｏｎ）またはリモートプロシージャコール（ＲＰＣ)機構を用いて、採集プロセスに直接、データを送ることも可能である。こうすると、採集プロセスは、新しいデータの処理を、そのデータのファイルへの書き込みを待つことなく、開始することができ、データの別個のコピーを維持する必要もなくなる。データのバックアップがあることが望ましい状況（例えば、ソースに一度しかアクセスできない場合など）においては、データを採集プロセスに直接送って、非同期で、バックアップファイルに書き込むことができる。このバックアップは、採集プロセス中にエラーが起きた場合、回復に用いることができる。
【０３２６】
統計
スキーマ推論ステップは、ソースデータを全て処理することが必要なので、データをさらにパスすることなく、このプロセス中、統計を計算することができる。統計は、ＥＴＬの忠実度の強化を含む、多くの利益を提供し得る。
スキーマ属性に関する統計
【０３２７】
統計の第１のクラスは、ソースデータ内の累積スキーマの個々の属性から計算できる。最初に、各属性及び型がデータ内に現れる頻度を追跡することができる。これは、多くの理由で有用であると思われる。例えば、上記のように、マップ装飾のヒューリスティックスは、ある属性が、その属性を含むオブジェクトの頻度に対して、現れる頻度に基づいている。
【０３２８】
頻度は、また、型に基づいた決定を行うために、そして、型の競合の解決に用いることができる。型情報を用いて、物理的なストレージの決定を最適化することができる。例えば、３２ビット及び６４ビットの整数と、浮動小数点の型と、を区別するために、数値型を追跡し、使用することができる。これらの各型は、異なる量のストレージスペースを必要とし得るので、どの型が適用可能かを決定することによって、最小の必要空間を割り当てることが可能になる。
【０３２９】
別々の型を有するソースデータ内に同じ属性が複数回、現れるとき、型多様性が生じる。上記のスキーマ推論機構及びインデックスストアは、型多様性を完全にサポートするが、一部のケースでは、あるフィールドの多様性が望まれない場合がある。例えば、単一の属性が、レコードの９９．９％に整数として現れ、他の０．１％に文字列として現れる場合、文字列型のレコードは、誤っているかもしれない。例えば、文字列型のレコードは、データエントリもしくは検証時のエラーを示すかもしれず、ソースデータの破損を示すかもしれない。これらの外れ値のレコードは、ユーザの注意をひくようにしてよく、及び／または、ヒューリスティックスに基づいて自動的に型変換してよい。例えば、レコードの１％未満が、異なる型である場合、それらのレコードは、優勢な型に変換してよく、このイベントを記し、オプションで、型変換されたソースデータを表すＥＴＬプロセスのためのログエントリを作成してよい。
【０３３０】
下記のＪＳＯＮレコードの例を考える。
{"id": 12345678, "location": "Saratoga, CA", "tags":
["urgent", "direct"]} 
{"id": "12345678", "location": "San Francisco, CA", "source" 
"iPhone"}
【０３３１】
これらのレコードから推論された累積スキーマは、下記のようになり得る。
{
"id" : "string",
"id" : "number",
"location" : "string",
"source" : "string",
"tags" : ["string"]
}
【０３３２】
累積スキーマは、累積スキーマの各属性と型をカウントに関連付けるＪＳＯＮスキーマで、ラップしてよい。例えば:
{
"type": "object",
"count" : 2,
"properties" : {
"id" : {
"type" : [
{"type": "string", "count": 1},
{"type": "int32", "count": 1},
〕
}"
location" : {
"type": "string",
"count": 2
},
"source" : {
"type": "string"
"count": 1
},
"tags" : {
"type": "array"
"count": 1
"items" : {
"type": "string", 
"count": 2
}
}
}
} 
【０３３３】
ｉｄは、一度は文字列として現れ、一度は３２ビット整数として現れるので、各型は、カウント１でリストされるが、ルートオブジェクトのカウントは２であることに留意する。さらに、ｔａｇｓ配列は、一度現れるので、カウントは１であるが、２つの文字列項目を含むので、項目フィールドは、カウント２である。レコードの各属性の頻度は、型付けプロセス中、計算することができ、複数の属性のカウントは、単純に追加することができる。追加は、結合的で可換的なので、このプロセスは、並列で行うことができる。カウントは、別々のデータストリームに関して、独立して維持することができ、マージしてグローバル統計を計算することができる。
【０３３４】
他の統計は、結合的及び可換的な方法で計算され得る限り、同じように各属性と関連付けることができる。例えば、文字列属性の平均的長さなどの統計や、別の型（日付など）を表す文字列値がどれくらいの頻度で現れるかなどを追跡することができる。平均に関しては、合計とカウントは、別に維持され、全てのデータが集計された時点で割り算が行われる(割り算は、結合的でも可換的でもないからである)。
【０３３５】
値に関する統計
例えば、各キーが現れる頻度など、ソースデータのスキーマに関する統計の収集に加えて、特定の属性に関連付けられた値の統計をとることができる。これらの統計は、クエリ最適化、データ発見、及び、異常検出を含む、様々なアプリケーションに用いることができる。関心のある統計は、属性の型に応じて決まる。数値属性については、これらのメトリクスは、最低値及び最大値などの基本的な統計的尺度と、分散の平均や標準偏差と、を含んでよい。並列処理を可能にするために、統計は、可換的かつ結合的な操作を用いて収集することができるように、選択してよい。
【０３３６】
分散のヒストグラムを含む、スカラ値に関するより高度な統計を、必要に応じて維持することができる。ある程度の量のエラーは容認できるというシナリオにおいては、計算より安価な近似アルゴリズムを用いることができる。例えば、ＨｙｐｅｒＬｏｇＬｏｇアルゴリズムを用いて、カラムの近似濃度(異なった値の数)を計算することができ、Ｑ−Ｄｉｇｅｓｔアルゴリズムを用いて、近似量を計算すことができる。値に関する統計は、プロパティに関する統計と同じように計算することができる。型推論中は、型を決定するために各値を分析し、同時に、統計をまとめることができる。ローカル統計は、メモリに保持することができ、グローバル統計とマージして、メタデータストアにスキーマと共に記憶することができる。大量の状態を保持する統計は、アクセス性能向上のために、オプションで、インデックスストアもしくは専用の統計ストアなどの別のストアに記憶してもよい。
【０３３７】
レコード全体に関する統計
一部の統計は、単一の属性または値ではなく、複数の属性に基づいている。よくある例の１つは、どのカラムが頻繁に一緒に発生するかを識別することである。例えば、ログデータに基づいたソースは、同じストリームの別々の型のレコードを組み合わせてよい。下記のＪＳＯＮレコードが一実施例である。
{"user": "mashah", "err_num": 4,
"err_msg": "Connection error."}
{"user": "lstavrachi", "session_time": 23,
"OS": "Mac OS X"}
{"user": "mashah", "session_time": 17,
"OS": "Windows 7"}
{"operation": "update", "duration": 10, 
"frequency": 3600}
【０３３８】
一番目ののレコードが、ユーザのエラーを表し、次の２つが、ユーザのセッションを表し、４番目がシステム操作を表す。これらのレコードから累積スキーマを決定し、その累積スキーマを関係スキーマに変換することは、これらのレコードを同じ関係テーブルに組み合わせることである一方、レコードは、異なるイベントを記述しているので、論理的に分けることができる。
【０３３９】
レコードのグループ間の相違を分析する１つの方法は、隣接行列を記憶することである。ここで、各エントリは、カラム対を表し、その２つのカラムが同じレコードに現れる回数を含む。隣接行列は、カラムの順は関係ないので、上三角行列または下三角行列であってよい。上の実施例では、ユーザローのエントリ、ｓｅｓｓｉｏｎ＿ｔｉｍｅカラム（同等に、ユーザカラム、ｓｅｓｓｉｏｎ＿ｔｉｍｅ  ｒｏｗ）は、それらの属性が両方とも、２つのレコードに現れるので、２を含むことになり、ユーザローのエントリ及び操作カラムは、それらの属性がデータセットに一緒に現れないので、０を含むことになる。
【０３４０】
隣接行列は、隣接リスト等の様々なフォーマットで記憶されてよく、構文解析されたレコードがメモリにあるとき、更新されてよい。複数の行列は、対応するエントリを合計することによってマージすることができ、よって、並列で計算することができる。行列は、カラムの数の二乗として成長するが、疎らな場合、あまりスペースを使わずに圧縮フォーマットで記憶してよい。他の統計同様、行列は、メタデータストアまたはインデックスストアに記憶することができる。
【０３４１】
隣接行列は、一旦、計算されると、幾つかの方法で関連カラムの識別に用いることができる。行列は、重み付けグラフに対応し、そこでは、ノードは属性であり、そのエンドポイントに対応するカラムが一緒にｉ回現れる場合、辺は、重みｉを有する。このグラフのクリークは、あらゆるカラムが他のあらゆるカラムと共に現れるカラムのセットを表す。上記の実施例は、下記のクリークを含む。
("user", "err_num", "err_msg")
("user", "session_time", "OS")
("operation", "duration", "frequency")
【０３４２】
これらは、役に立つことには、３つの別個のイベント型に対応し、ユーザに提示することができ、または、自動データ変換に用いることができる。これらのクリークは、標準グラフアルゴリズムを用いて計算することができ、そのアルゴリズムは、クリークの各辺が少なくとも最小の重みを有するように構成することができる。
【０３４３】
関連カラムをより広いビューでとらえるために、上記グラフ内の全ての接続された構成要素をグループ化することができる。言い換えれば、間に経路のある２つの属性はいずれも、組み合わせて単一のグループにすることができる。上記実施例では、下記の２つのグループが作られる。
("user", "err_num", "err_msg", "session_time", "OS")
("operation", "duration", "frequency")
【０３４４】
ｅｒｒ＿ｎｕｍとＯＳは、エラーレコードとセッションレコードの両方が、ｕｓｅｒフィールドを有するので、同じ接続された構成要素内に現れるが、同じクリーク内には現れないことに留意する。関連カラムのこのゆるい概念は、大きな無関連のデータのセットを大まかに分けるために有用であると思われる。
【０３４５】
上記の隣接行列は、各レコードのスキーマのみに基づいているが、一定の値をカラムの有無と相関させることが望ましい場合がある。無関連のレコードが、異なるスキーマを有する１つの状況は、例えば、各レコードがレコードの型を識別する明示的な属性（例えば、ｅｖｅｎｔ＿ｉｄ）を含む場合である。上記実施例においては、ユーザエラーは、１のｅｖｅｎｔ＿ｉｄ、ユーザセッションは、２のｅｖｅｎｔ＿ｉｄ、システム操作は、３のｅｖｅｎｔ＿ｉｄを有し得る。ｅｖｅｎｔ＿ｉｄの意味を決定（または、ユーザが示す)ことができる場合、ｅｖｅｎｔ＿ｉｄを用いて、イベント型によって属性を分離することができる。この場合、各ｅｖｅｎｔ＿ｉｄ値について、全てのレコードのスキーマを、そのｅｖｅｎｔ＿ｉｄ値とマージすることによって、別個の累積スキーマを維持することができる。ｅｖｅｎｔ＿ｉｄによってデータソースを分割するプロセスは、「シュレッディング（ｓｈｒｅｄｄｉｎｇ）」と呼ばれ、以下に記載する。
【０３４６】
インデックスストアを用いた非同期統計
上記統計は、一般的に並列で計算することができる一方、一部の統計は、一旦、全てのデータを準備しなければ、計算するのは難しい（例えば、メジアンやモード）。これらの統計は、インデックスストアのクエリ機能を用いてデータのロード完了した後、計算してよい。これには、大量のデータのスキャンが必要になり得るので、インデックスストアがアイドル状態のときに、非同期で行ってよい。
【０３４７】
エラー統計
レコードにとって有益であり得る統計の別のクラスは、エラー統計である。採集中、データ自体またはシステム操作で遭遇し得る多くの異なる種類のエラーがある。例えば、これらは、入力データ解凍に関するエラー、入力ファイルフォーマットのエラー、特定のレコードの構文解析エラー、文字列符号化のエラー（例えば、ＵＴＦ−８）、ロックされたファイルを開こうとしてのエラー、及び、ネットワークを介したソースデータへのアクセスのエラーを含んでよい。これらの統計に関する情報は、メタデータストアに保持することができ、必要に応じて、ユーザ及び／またはアドミニストレータに送ることができる。
【０３４８】
インデックスストア内の中間ストレージ
採集したデータは、記憶及びクエリを容易にする、上記のＢｉｇＩｎｄｅｘ（ＢＩ）、ＡｒｒａｙＩｎｄｅｘ（ＡＩ）及びＲｏｗＩｎｄｅｘ（ＲＩ）を含み得るインデックスのコレクションに記憶することができる。インデックスストアに、ユーザは直接クエリを行うことができるが、インデックスストアは、別のシステムをロードするプロセス中に、中間ストアとして用いることもできる。この欄は、ＥＴＬプロセスのための中間ストアとしてのインデックスストアの使用を記述する。
【０３４９】
バルクエクスポート
インデックスストアをＥＴＬの中間ストレージ領域として用いる際、インデックスストアからのバルクデータの効率の良いエクスポートが重要である。例えば、ハードディスクドライブ（特に、磁気ドライブ）を用いるとき、データの大きいチャンクを連続して読み取ることによって、シーク待ち時間を避けて、最大帯域幅を達成するのが、より効率的である。
【０３５０】
ハードディスクドライブのように連続的にアクセスされる媒体について、所与のピーク性能比（ｆ）を決定してよい。ディスクのシーク待ち時間を（Ｌ）、持続的な連続帯域幅（sustained sequential bandwidth）を（Ｂ）とすると、求められるピーク性能比を達成するためにシーク毎に読み取る必要のあるバイト数（Ｎ）は、以下のように計算できる。
N = ( f / (1-f) ) * L * B
【０３５１】
例えば、１００ＭＢ／秒の持続帯域幅と、平均シークあたり待ち時間１０ミリ秒のディスクを考える。９０％のピーク性能（ｆ＝．９）を達成するためには、
N = (.9 / (1 - .9)) * 10 ms/seek * 100 MB/s
N = 9 MB/seek
【０３５２】
従って、指定の比の性能を達成するためのゴールは、少なくとも９ＭＢの順次バーストでデータを読み取ることである。データのターゲットが、ディスクベースのシステムである場合、ターゲットの書き込み性能に基づいて、同じ式が当てはまる。
【０３５３】
概念上は、インデックスストアからのデータのエクスポートは、ロー毎にまたはカラム毎に行うことができる。モードの選択は、宛先データストアの能力に応じて決まる。カラムをエクスポートするとき、ＢＩ、ＡＩまたはＭＩ（これらはそれぞれ、最初に、カラムによってソートされ、次に、タプルＩＤによってソートされてよい）から広範囲のソートされたデータがエクスポートされてよい。要求されたタプルが一旦ソートされると、各カラムについて、少なくとも９ＭＢのタプルを読み取る必要がある。効率を良くするために、１つのカラムからの全てのタプルは、次のカラムに移動する前に、読み取られ、出力に書き込まれてよい。
【０３５４】
ローをエクスポートするとき、少なくとも２つの選択肢がある。ＲＩが利用可能な場合、要求されたデータは、ＲＩでタプルＩＤによってソートされ、ソート順で読み取ることができる。ＲＩもソート順で記憶されるので、これによって、ディスクに順次アクセスする。次に、出力システムに合わせて適切にローをフォーマットする必要がある。
【０３５５】
ＲＩをエクスポートに使用しない場合、ローは、例えば、ＢＩ、ＡＩ及びＭＩから構築されてよい。効率性のために、大きいチャンクのデータを、一度に、ＢＩ、ＡＩ及びＭＩの各カラムから読み取る。出力ローを生成するために、所与のローについてデータを各出力カラムから読み取った後、ローを生成することができる。
【０３５６】
十分なＲＡＭがあれば、各カラムのＮメガバイトのチャンクは、ＲＡＭに読み取ることができ、そして、ローを出力することができる。カラムが圧縮される場合、メモリを節約するために、カラムは、可能な程度まで圧縮したままでよい。さらに、データが書き出されると、メモリは、リアルタイムで解放されてよい。１つのカラムのＮメガバイトのチャンクは、別のカラムのＮメガバイトのチャンクと同数のタプルを有する可能性は低い（特に、圧縮を使用しているとき）。従って、１つのカラムのタプルが別のカラムのタプルの前に枯渇することになるので、各カラムのチャンクは、独立して、フェッチされる必要があり得る。ディスクの待ち時間を最小にするために、プリフェッチを採用することができる。しかし、プリフェッチ及び部分解凍は両方とも、変換の必要メモリを増やし得る。
【０３５７】
ＢＩ、ＡＩ及びＭＩからのローのバルクエクスポートについての疑似コードの例である。
create a cache for each column,
this cache caches data for a tid with a 
replacement policy geared towards streaming 
and implements prefetching.
for tid in output_touple_ids:
start building new touple
for each column of this touple:
lookup tid in cache
if tid present
evict tid to optimize for streaming
check for free space in this cache, 
if ample free space, 
prefetch the next block
if tid not present,
fetch the block of data containing the tid from
the AI,
if necessary,
decompress chunk containing datum 
add datum to touple
add touple to output buffer
if output buffer is full,
send output to destination
【０３５８】
システムが、ＲＡＭを制限している場合、変換は、複数のパスで行うことができる。ここで、各パスは、できるだけ多くのカラムチャンクを読み取り、部分的なロー出力チャンクを生成し、それらはディスクに記憶される。そうすると、部分的なロー出力チャンクは、カラムのように扱うことができ、プロセスは、全てのローが出力されるまで、繰り返すことができる。
【０３５９】
例えば、図１５を参照すると、カラムＡ、Ｂ、Ｃ、Ｄを含むインデックスの、不揮発性ストレージ１５８０（例えば、ハードディスクドライブ上)の配置例が示されている。あるローをエクスポートするために、カラムＡ、Ｂ、Ｃ、Ｄのそれぞれからのデータが要求される。不揮発性ストレージ１５８０の各カラムからの単一のカラム値の読み取りは、シークタイム及びアクセスタイムに大きなペナルティとなり得る。その読み取りに代えて、各カラムのチャンクをメモリに読み取ることができる。これを単純化して例示すると、不揮発性ストレージ１５８０の各カラムには、１０２４個のエントリがある。メモリ１５８４（揮発性のダイナミックランダムアクセスメモリであってよい)には、５１２個のエントリが入る余地がある。よって、カラムＡ、Ｂ、Ｃ、Ｄのそれぞれに対する１２８個のエントリが、次に、不揮発性ストレージ１５８０からメモリ１５８４に読み取られる。
【０３６０】
４つの読み取りのそれぞれが完了すると、それぞれ、４つのカラムＡ、Ｂ、Ｃ、Ｄのそれぞれからのエントリを含む、１２８のローをエクスポートすることができる。様々な実装において、各カラムのエントリのサイズは異なってよい。従って、メモリ１５８４内のストレージスペースは、多くのエントリを記憶するカラムが多くのスペースを与えられるように、カラム間で不均等に分けられてよい。こうすることによって、各カラムについて、ほぼ同数のエントリを記憶することができる。あるいは、メモリ１５８４は、カラム間で等しくストレージを割り当ててよい。その結果、多くのエントリを記憶するカラムは、メモリ１５８４内に、一度に記憶されるエントリが少なくなる。従って、ローがエクスポートされていくにつれて、これらのカラムからの新しいデータは、エントリの少ないカラムより早く、メモリ１５８４にロードされる必要がある。
【０３６１】
インデックスストア管理
インデックスストアは、スナップショット、回復、サイズ変更、及び、移行など、様々な管理機能をサポートするように構成されてよい。これらの機能は、インデックスストアの書き込みと、Ｌｉｎｕｘ（登録商標）論理ボリュームマネージャ（ＬＶＭ）等の基礎的システム技術の利用との、適切なオーケストレーションによって、実装することができる。
【０３６２】
インデックスストアのスナップショットは、インデックスストアをクローンするために、または、回復を支援するために、バックアップに使用することができる。スナップショットは、書き込みのバッファリングを開始し、インデックスストアをディスクにフラッシュし、ファイルシステムまたはボリュームマネージャ内の基礎的スナップショットファシリティを使用し、そして、書き込みを適用することによって、達成することができる。さらに、ＬｅｖｅｌＤＢ等のアーキテクチャに基づいたシステムでは、書き込みをバッファリングする代わりに、システムが、データを圧縮し、スナップショットの部分として、下位レベルにマークを付け、それら下位レベルがさらに圧縮されないようにし、下位レベルを含むファイルをコピーし、そして、圧縮を再度有効にするこができる。
【０３６３】
回復は、基礎的なシステムに従ってバックアップデータをリストアし、インデックスストレージサービスを開始し、そして、リストアされたデータを指摘するようにメタデータサービスを更新することによって、達成される。記憶されたタプルＩＤのセットは、スナップショットが撮られる時に、メタデータサービスに記録され、スナップショットがリストアされる時にリストアされる。スナップショットからのリストアの後、欠けているデータは、全てのタプルＩＤのセットと、回復されたインデックスストアに記憶されたタプルＩＤのセットとを比較することによって、決定することができる。
【０３６４】
インデックスストアの縮小は、インデックスストア内の全てのデータを圧縮し、ファイルシステムサイズを小さくし、論理ボリュームサイズを小さくすることによって、達成されてよい。ディスク（または、仮想ディスク）を取り除くための十分なフリースペースがある場合、そのディスク上のデータは、ボリュームグループ内の他のフリースペースに移行することができ、ディスクは、ボリュームグループから取り除くことができ、次に、システムから取り除くことができる。インデックスストアの成長は、必要があれば、ディスクまたは仮想ディスクを追加することによって行ってよい。ディスクが追加された場合、そのディスクは、ボリュームグループに含むことができるので、論理ボリュームサイズを増やし、ひいては、ファイルシステムサイズを増やすことができる。インデックスストアの一部の実装においては、ファイルシステムは用いなくてもよく、その場合、インデックスストアは、ファイルシステムに依存する代わりに、サイズ変更操作を実施してよい。一部の実装においては、インデックスストアは、ＬＶＭを用いなくてもよく、自身で直接、ディスクを管理することができる。
【０３６５】
クラウド環境において、または、サーバメンテナンス中に、インデックスストアを１つのマシンから別のマシンに移行させるのが望ましい。最も簡単なケースは、これをオフラインで行うことである。これは、読み取り及び書き込みをブロックし、インデックスストレージサービスをシャットダウンし、ファイルシステムをアンマウントし、論理ボリュームを無効にし、ディスク（または、仮想ディスク）を新しいマシンに移し、論理ボリュームを再有効化し、ファイルシステムをマウントし、インデックスストレージサービスを再び開始し、そして、メタサービスが所与のインデックスストアが存在する場所を知るようにメタデータサービスを更新することによって、行うことができる。
【０３６６】
オンラインのインデックスストアを移行するために、新しいインデックスストアを立ち上げながら、システムは、書き込みをバッファリングし、古いインデックスストアからの読み取りを行ってよい。次に、データは、古いインデックスストアから新しいインデックスストアにコピーされ、新しいインデックスストアは、アクティブとしてマーク付けされる。次に、読み取りは、新しいインデックスストアに向けられて、最後に、バッファリングされた書き込みが適用される。この移行を最適化するために、新しいインデックスストアをスナップショットからリストアすることができる。このようなシナリオにおいては、書き込みはバッファリングされ、インデックスストアの現在の状態と、スナップショットとの間のデルタ（増分）を計算することができる。デルタは、新しいシステムのスナップショットを最新にするために、適用することができる。次に、新しいインデックスストアは、アクティブとマーク付けされ、バッファリングされた書き込みは、新しいインデックスストアに適用される。バッファリング時間を最小にするために、書き込みをバッファリングする前に、複数のデルタを計算、適用することができる。
【０３６７】
インデックスストア拡張子
系列
１つのデータストアから別のデータストアにデータを移す時、システムを通って移動する各データの系列を追跡可能であるのが望ましい。実施例として、各レコードが復帰改行で分けられたＪＳＯＮレコードを含むファイルのコレクションを考える。これらのファイルからのデータは、インデックスストアにロードしてよく、インデックスストアからデータウェアハウスにロードされてよい。レコードの系列を維持するために、各レコードは、例えば、各レコードのソースファイル名と行番号を記録することによって、追跡することができる。系列情報は、追加のカラム(またはカラムのセット)として、インデックスストアに記憶することができる。
【０３６８】
これらの追加カラムも、データウェアハウスにロードされてよい。こうすると、エンドユーザは、レコードの元のソースを見つけることができる。ユーザは、エラーがあるか否かを知ろうとして、または、削除された可能性のある、もしくは、ロードしないと選択された他のデータを見つけようとして、レコードの元のソースを見つけたいかもしれない。システムは、その情報を用いて、データの紛失があるか否かを決定することができる（例えば、ファイルやローによるソートを行い、ファイルまたはローが無くなっているかを見つける）。同様に、また、おそらくは類似の利益を伴って、データが、インデックスストアからデータウェアハウスにロードされる時、追加カラムを作成して、インデックスストアのタプルＩＤをデータウェアハウスに記録することができる。これによって、システムは、ある種のエラーからの回復が可能になり、インデックスストアとデータウェアハウスとのデータの比較が可能になる。
【０３６９】
テンポラル（時間による）／バイテンポラル（２つの時間による）サポート
時間は、多くのシステムにおいて基本的変数である。一部の分析は、時間フィールドの意味を理解するシステムによって、改善される、または、可能になる。オブジェクトの複数のバージョンを保持し、時間を使って、それらのバージョンを区別するデータベースは、テンポラル（時間）データベースと呼ばれることが多い。オブジェクトに適用する時間には複数の概念がある。時間についての２つ一般的概念は、トランザクション時間（ＴＴ）と有効時間（ＶＴ）である。トランザクション時間は、システムがトランザクションを行った時間である。有効時間は、１つのデータが有効である時点または、時間範囲である。例えば、ある人が住んでいる特定の住所は、その人がそこに住んでいる特定の期間（ＶＴ）に関連する。住所がシステムに記録された時は、ＴＴである。
【０３７０】
多くの環境において、データの履歴を見ることできるのは、有利である。履歴データにクエリを行う１つの機構は、クエリＡＳ  ＯＦとして、特定の時点を定義することである。システムに、２０１４年１月３１日現在（ＡＳ  ＯＦ）入手可能であった全ての情報に基づいて、質問に応答するよう求めるとする。これらのクエリは、ＡＳ  ＯＦ時以下の最大ＴＴを有するオブジェクトをレビューしてよい。
【０３７１】
他の環境においては、ユーザは、オブジェクトに関する事実が、経時的にどのように変化したかについて知りたい場合がある。ある人の自宅の住所が、それぞれ、異なる有効時間を有する多くのバージョンで、データベースに記録されている場合がある。データベースのユーザが、ＡＳ  ＡＴ特定の時間で、その人の住所のクエリを行いたいとする。このクエリは、ＶＴがＡＳ  ＡＴ時間を含むオブジェクトをレビューしてよい。
【０３７２】
時間の１つの概念（トランザクション時間であることが多い)だけを主にサポートするデータベースは、モノテンポラルと考えられる。トランザクション時間と有効時間の両方など、時間の２つの概念をサポートするデータベースは、バイテンポラルと考えられる。バイテンポラルデータベースは、オブジェクトのバージョンの二次元空間をサポートし、ＡＳ  ＯＦで特定のＴＴと、ＡＳ  ＡＴで特定のＶＴの両方のクエリを行うことによって、バージョンの絞り込みをサポートする。
【０３７３】
Ｒ木、ｋｄ木、及び、Ｚ−ｏｒｄｅｒｉｎｇ（Ｚ順序付け）等の空間的インデックス方法を用いて、Ｎ次元空間で互いに近いオブジェクトが、インデックスで互いに近くなるように、多次元に沿ってインデックスを構築することができる。
【０３７４】
インデックスストアの時間性をサポートするために、時間の次元について別のインデックスを作成することができる。このインデックスは、トランザクション時間をタプルｉｄにマップするテンポラル時間インデックス（ＴＴＩ）であってよい。別のインデックスは、有効時間をタプルｉｄにマップする有効時間インデックス（ＶＴＩ）であってよい。バイテンポラルシステムは、バイテンポラルインデックス（ＢＴＩ）内の有効時間とテンポラル時間の両方をタプルｉｄにマップするための空間的インデックスを含んでよい。
【０３７５】
更新
上記のインデックスストアは、様々な実装において、バルク挿入またはバルク追加を効率よく処理する。これは、ハードディスクドライブを有するシステム上での、クエリ及び抽出に効果がある。更新及び削除(既存のタプルが何らかの方法で変更されるとき、更新が起こる)を効率よく処理するためには、インデックスストアへの何らかの変更が必要となり得る。これらの更新は、ＭｏｎｇｏＤＢ及びそのｏｐｌｏｇ等の何らかの種類のトランザクションストアが行った変更の順序付リストとして、到着してよい。
【０３７６】
更新を処理する１つの方法は、更新をオブジェクトのインプレース値に適用することである。単一のローの更新は、インデックスストアにおいては高価になり得るので、更新は書き込み最適化ストア（例えば、ローストア）にバッファリングされる。図１４を参照すると、書き込み最適化ストア１５５２が示されている。クエリは、最初に、書き込み最適化ストア内の値を探し、次に、インデックスストアを探す。十分なデータが書き込み最適化ストアにあれば、そのデータをパッケージにして、インデックスストアでバルク更新を行うことができる。
【０３７７】
更新を処理する別の方法は、入力からレコード／オブジェクトを取り出し、それらを、何らかのキー及びトランザクションレジスタに記録されたトランザクション時間に基づいて、異なるバージョンのレコード／オブジェクトに変換することである。変換されたレコード／オブジェクトは、次に、新しいレコードとして、インデックスストアに追加することができる。宛先ストアがテンポラルな場合、ＡＳ  ＯＦクエリを用いて、過去のクエリを行うことができる。
【０３７８】
データ変換
中間ストアが存在する場合、中間ストアからデータをエクスポートするときに、変換を行うことができる。これによって、異なる宛先に対して異なる変換が可能になり、また、変換を行う前に、良く定義された単一のソースデータ表現の作成をサポートし得る。中間ストアを使用しない場合、各カラムを関係に変換する時に、変換を行ってよい。
【０３７９】
型変換
１つのよくある変換は、値を１つの型から別の型に変換することである。例えば、ＪＳＯＮは、データ型を定義しないので、文字列（例えば、ＩＳＯ  ８６０１に従って）または数値（例えば、ＵＮＩＸ（登録商標）エポックからの秒で）として、日付を記憶するのが一般的である。宛先が、データ型をサポートしている(大抵の関係データベースはサポートしている)場合、型変換ディレクティブを追加して、値を日付に変換することができる。同様のディレクティブを用いて、適切な文字列を数字に型変換することができる。これらの型変換ディレクティブは、データの予備知識を用いて手動で指定することもでき、スキーマ推論中に収集された統計を用いて自動で推論することもできる。
【０３８０】
データクリーニング
様々な他のデータクリーニング操作を、エクスポート中に行うことができる。例えば、ある属性があるドメインにあることが分かっている場合（例えば、州コードを表す文字列または郵便番号を表す数字）、値は、省略できるまたは、デフォルトに変換できる。
【０３８１】
データの分割と結合
上記のように、システムは、配列及びマップからのデータを別々のテーブルに分割してよいが、一部のケースでは、ユーザは、関係スキーマに対して追加の制御を望む場合がある。例えば、ユーザは、組み合わせて同じ宛先にしたい複数のソース、または、その逆、を有する場合がある。テーブルを組み合わせるために、ユーザは、結合キーを指定してよく、結合は、エクスポートの前にインデックスストアで行うことができる。
【０３８２】
データを分割するために、別個のテーブルに配置するためのカラムのセットを識別する。グローバルに固有のレコードｉｄを結合キーとして用いることができ、テーブルは、別々にエクスポートされる。これらのカラムは関連する属性セットを識別するために、手動で、または、上記のような統計的方法を用いて指定することができる。
【０３８３】
シュレッディングと呼ばれる操作によって、単一の属性の値に基づいて、データをテーブルにパーティション化する。これは、単一の属性の値がレコードの型を決定するイベントのようなデータソースについては、特に有用である。どのカラムが各ｉｄと関連付けられているかを特定する統計を収集することができ、各レコード型について別個のテーブルをエクスポートすることができる。
【０３８４】
採集ターゲット
データウェアハウス
ＥＴＬプロセスの１つの可能な出力先（または、ターゲット）は、データウェアハウスである。データウェアハウスは、ローフォーマット（例えば、ＣＳＶ）で出力ファイルのセットを作成することによって、動的スキーマの変更に従ってデータウェアハウスを適合させるための対応する一連のＡＬＴＥＲ  ＴＡＢＬＥ／ＣＯＬＵＭＮコマンドと共にロードされてよい。
【０３８５】
Ｖｅｒｔｉｃａ、Ｇｒｅｅｎｐｌｕｍ、Ａｓｔｅｒ／Ｔｅｒａｄａｔａ、及び、Ａｍａｚｏｎ  Ｒｅｄｓｈｉｆｔの製品を含む、分析用に設計された一部データウェアハウスは、異なるカラムを別々に記憶するカラム指向のストレージを用いる。これらのシステムにおいては、新しいカラムの追加は、既存データの修正を必要とせず、より効率が良いと思われる。このようなデータウェアハウスへのファイルのロードは、データウェアハウスがサポートするコマンドを用いて行ってよい。複数の並列ロードを受け入れることができる宛先への供給について以下に記載する。
【０３８６】
無関係オブジェクトストア
ユーザは、関係ストアの代わりに、オブジェクトストアのロードを選んでよい。データをオブジェクトストアにロードする１つの方法は、求められる出力フォーマットに従って、累積的ＪＳＯＮスキーマを用いて、オブジェクトをシリアライズすることである。
【０３８７】
オーケストレーション
ＥＴＬプロセスの個々の構成要素は、分散コンピュータ環境内、すなわち、クラウドで、または、プライベートデータセンター内で、スケジュール、及び、実行することができる。スケジューリングは、データソース及び宛先の性質、インデックスストアが用いられているか否か、並びに、求められる並列処理の程度に応じて決まってよい。パイプラインの各段階の状態は、回復、統計、及び、系列をサポートするためにメタデータサービスに記憶されてよい。
【０３８８】
ＥＴＬプロセスの実施例は、次の構成要素にセグメント化されてよい。すなわち、新しいデータの検出（Ｄ）、ソースからデータを抽出（Ｓ）、ソースのスキーマを推論（Ｉ）、オプションでインデックスストアをロード（Ｌ）、累積スキーマを生成（Ｇ）、ａｌｔｅｒ  ｔａｂｌｅステートメントの生成（Ａ）、オプションで、中間フォーマットでデータをエクスポート（Ｅ）、及び、データを宛先にコピー（Ｃ）
【０３８９】
検出（Ｄ）プロセスの実施例は、下記の疑似コードを用いて記述される。
old_metadata = None
while True:
metadata = source.get_metadata() 
if old_metadata == metadata:
# nothing new here 
sleep if necessary to prevent overwhelming source
continue
# find new stuff
new_stuff = metadata - old_metadata
# build chunks of appropriate size
chunk = new Chunk()
for item in new_stuff: 
chunk.add_data(item)
if chunk.big_enough():
mds.record_chunk(chunk) 
chunk = new Chunk()
【０３９０】
インデックスストアを用いた採集プロセスは、データ抽出（Ｓ）、スキーマ推論（Ｉ）、及び、インデックスストアのロード（Ｌ）を含んでよく、それらは合わせてＳＩＬと呼ばれる。ＳＩＬプロセスの例の疑似コードを下記に示す、ここで、インデックスストアは、“ＩＳＳ”と呼ぶ。
while True:
# Get any unprocessed chunk of source data
chunk = mds.get_any_unprocessed_chunk()
# code below can be in an asynchronous task
cumulative = new Schema() 
for record in chunk.read():
schema = get_schema(record) 
cumulative.update(schema)
iss.write(record)
iss.commit_chunk()
mds.save_chunk_schema(chunk, cumulative)
【０３９１】
スキーマ生成プロセス（Ｇ）の例の疑似コードは下記のようになる。
parent = None
while True:
# get a few committed chunks such that they form a
# reasonable copy size
chunks = mds.get_committed_chunks()
# generate a cumulative schema across loads
cumulative = Schema()
for chunk in chunks:
cumulative.update(mds.get_schema(chunk))
parent = mds.store_new_cumulative(cumulative, chunks,
parent)
【０３９２】
インデックスストアからのエクスポートプロセス（Ｅ）の例の疑似コードは下記のようになる。
while True:
cumulative, chunks = mds.get_unexpoeted_schema()
# code below can be in an asynchronous task
# export the new chunks according to the
# cumulative schema
intermediate = new Intermediate()
for record in iss.get_chunks(chunks):
export_data = prepare_output(record, cumulative)
intermediate.append(export_data) 
mds.record_schema_export(cumulative, intermediate)
【０３９３】
テーブル変更（ａｌｔｅｒ  ｔａｂｌｅ）要素（Ａ）及びコピー要素（Ｃ）を含む、累積的にＡＣと呼ばれる、プロセスの例の疑似コードは下記のようになる。
while True:
schema, output = mds.get_uncopied_output()
previous = mds.get_parent_schema(schema)
# generate alter table statements 
if schema != previous:
difference = schema - previous
warehouse.alter_table(difference)
warehouse.copy_from(output)
【０３９４】
インデックスストアを用いず、データが、データソースからターゲットにストリーム配信される場合、プロセス全体は、ＳＩＥＧＣＡと呼んでよく、データ抽出（Ｓ）、スキーマ推論（Ｉ）、データエクスポート（Ｅ）、コピー（Ｃ）、及び、ターゲットのテーブルの変更（Ａ）を含む。ＳＩＥＧＣＡプロセスの例の疑似コードは下記のようになる。
cumulative = new Schema()
intermediate = new Intermediate()
while True:
# Get any unprocessed chunk of source data 
chunk = mds.get_any_unprocessed_chunk()
# code below can be in an asynchronous task
for record in chunk.read():
schema = get_schema(record) 
if schema != cumulative:
mds.record_schema_export(cumulative,
intermediate)
cumulative.update(schema)
intermediate = new Intermediate()
intermediate.append(record)
iss.write(record)
mds.save_chunk_schema(chunk, cumulative)
【０３９５】
図１６Ａ、１６Ｂにおいて、本開示の原理に従った、ＥＴＬプロセスの構成要素の並列化の依存関係図を示す。図１６Ａは、中間インデックスストアの使用を示している。検出プロセス（Ｄ）は、６つのサブプロセス１６００−１．．．１６００−６に分けて示されている。依存関係は、矢印で示され、ここで、Ｄ2  １６００−２は、Ｄ1  １６００−１等に依存している。言い換えれば、Ｄ2は、Ｄ1がが完了しないと、完了できない。ここで説明が簡単なように記載しているように、依存関係が厳密な場合、Ｄ2は、Ｄ1が完了するまで、開始することさえできない。これは、Ｄ1が完了して、Ｄ2に開始点を残すまで、Ｄ2は、新しいデータの検出をどこから始めるべきかも分からないからであろう。ほんの一例として、検出サブプロセスＤ1は、最初の１０，０００個の新しいオブジェクトを取得するように構成されてよい。サブプロセスＤ2は、サブプロセスＤ1が中止した場所から初めて、次の１０，０００個の新しいオブジェクトを識別する。
【０３９６】
図１６Ａ、１６Ｂに示す依存関係は、一定の状況においては、断たれてよい。例えば、Ｄ1及びＤ2が、別々のデータソース、または、データソースの異なった部分を調べている場合、Ｄ2は、Ｄ1の完了を待たずに開始してよい。
【０３９７】
抽出プロセス（Ｓ）は、サブプロセス１６０４−１．．．１６０４−６を含む。各抽出サブプロセス１６０４は、各検出ステップ１６００に依存する。この依存関係は、ソースから抽出するファイル／オブジェクト／レコードは、検出サブプロセス中に識別されるという事実から生じる。
【０３９８】
スキーマ推論は、抽出サブプロセス（Ｓ）で抽出されたレコードに関して行われるので、１６０８−１．．．１６０８−６で示す各推論サブプロセス（Ｉ）は、各抽出サブプロセス（Ｓ）に依存する。推論される（Ｉ）各レコードについては、そのレコードは、中間ストレージにロードされる（Ｌ）ので、ロードサブプロセス１６１２−１．．．１６１２−６は、それぞれ、各推論サブプロセスに従属する。
【０３９９】
１６１６−１．．．１６１６−３で示されるスキーマ生成サブプロセス（Ｇ）は、以前のスキーマを取得し、１つまたは複数のサブプロセスからの新しく推論されたスキーマを追加して、新しい累積スキーマを生成する。ヒューリスティックを用いて、推論サブプロセスが幾つ、単一のスキーマ生成サブプロセスに供給されるかを決定してよい。図１６Ａに見られるように、数字は変数であってよい。
【０４００】
抽出サブプロセス１６２０−１．．．１６２０−３は、生成されたスキーマを各生成サブプロセスから受信し、生成サブプロセスに対応するロードサブプロセスからデータを抽出する。抽出サブプロセス１６２０は、データウェアハウス等のターゲットにロードするための中間ファイルのセットを構築してよい。抽出サブプロセスを含む各サブプロセスは、内部並列化を活用できるように最適化されてよい。
【０４０１】
生成サブプロセスに基づいて、テーブル変更サブプロセス１６２４−１．．．１６２４−３は、ターゲットが、スキーマサブプロセス１６１６が決定したスキーマの任意の新しいオブジェクトを収容するためのコマンドを生成する。例えば、Ａ2は、任意の追加のオブジェクトがＧ2によって累積スキーマに追加されたオブジェクトか否かを、Ｇ1の後既に存在したオブジェクトと比較して、決定する。ターゲットのためのコマンドは、データ定義言語（ＤＤＬ：Ｄａｔａ  Ｄｅｆｉｎｉｔｉｏｎ Ｌａｎｇｕａｇｅ）ステートメントの形式をとってよい。テーブル変更サブプロセスとしてラベル付けされているが、実際の言語またはステートメントは、特定のステートメント“ａｌｔｅｒ  ｔａｂｌｅ”を用いなくてもよい。累積スキーマが、テーブル変更サブプロセス１６２４によってターゲットに反映された時点で、コピーサブプロセス１６２８−１．．．１６２８−３において、データはターゲットにコピーされる。
【０４０２】
図１６Ｂにおいて、ストリーミングアプローチを示す。ここでは、カラムまたはインデックスストア等の中間ストアはない。代わりに、データは、ターゲットに直接、採集され、１６１２のロードサブプロセスは省略される。結果として、抽出サブプロセス１６２０は、スキーマ推論サブプロセス１６０８に直接依存する。この実装においては、テーブル変更サブプロセス１６２４は、コピーサブプロセス１６２８に依存し、図１６Ａの依存関係と逆であることに留意する。
【０４０３】
ジョブの弾力的なスケジューリング
インデックスストアを用いるとき、採集タスク（ＳＩＬ）及びエクスポートタスク（Ｅ）は、計算集約的であってよい。これらのタスクは、内部で並列化することができる。さらに、これらのタスクは、その依存関係が満たされれば、ジョブスケジューリングシステム（例えば、ＰＢＳ、ＬＳＦ、ＹＡＲＮ、ＭＥＳＯＳ等）を介して非同期的に発行することもできる。これらのジョブスケジューリングシステムの多くは、ステップ間の依存関係も符号化することができる。（図１６Ａに示すような)依存グラフを知ることによって、スケジューリングモジュールは、全てのノードが使用中であるが、同時に、未処理の（outstanding）ジョブがあまり多くないことを保証しているグラフで、古いジョブを発行することができる。
【０４０４】
エラー回復
エラー回復の目的で、サブプロセスの一部または全ては、システムの状態に関するメタデータと、サブプロセスがシステムに行おうとする変化とを、記録する。ステップが失敗した場合、回復コードは、このメタデータを用いて、中断された操作を終えるか、再試行できるように不完全な操作を取り消すことができる。例えば、ロードサブプロセスは、ロード中のタプルＩＤのセットを記録する。ロードサブプロセスが失敗すると、そのセットに一致するタプルＩＤを有する全てのレコードをパージするにように指示するコマンドが、インデックスストアに発行されてよい。そうすると、ロードは再試行できる。
【０４０５】
エクスポート最適化
一部の関係ストアは、中間ファイルなしにデータを直接ロードする機構を有している。例えば、Ｐｏｓｔｇｒｅｓは、ＣＯＰＹ  ＦＲＯＭ  ＳＴＤＩＮコマンドをサポートしており、データを直接データベースに供給することができる。エクスポートプロセスは、このインタフェースを用いて、データを直接、出力システムに書き込むことができるので、エクスポート（Ｅ）ステップとコピー（Ｃ）ステップをマージすることができる。ＡｍａｚｏｎのＲｅｄｓｈｉｆｔ等、一部のシステムは、リモートプロシージャコールを介して、ウェアハウスから直接、データをインデックスストアに引き出してくる機構を有する。この場合、ユーザは、マニフェストァイルを作成し、コピーするために発行するセキュアシェル（ｓｓｈ）コマンドのセットをリストにする。各ｓｓｈコマンドは、ホストと、そのホスト上で実行するコマンドと、を指定する。タプルＩＤのセットをインデックスストアから抽出するコマンドを指定することによって、宛先データベースは、エクスポートのために必要なレコード／オブジェクトを、インデックスストアから引き出すことができる。
【０４０６】
監視
リソース監視
監視システムは、システムが使用するハードウェアリソースとソフトウェアリソースを追跡する。それらリソースは、コレクタ、採集パイプライン、メタデータストア、（オプションの）インデックスストア、及び、データウェアハウスが使用する計算リソース及びストレージリソースを含んでよい。監視システムは、ＣＰＵ、メモリ、ディスクの使用率などを含むが、それらに限られないメトリクスと、ネットワーク要求への応答と、を追跡する。
【０４０７】
監視サービスが、（パブリックであってもプライベートであっても）クラウド内に、または、プログラム的に割り当てられたリソースを有する別のシステムに配置される場合、監視システムを用いて、必要に応じて、システムのスケールアップまたはスケールダウンを自動的に行うことができる。例えば、インデックスストアのストレージスペース（Ａｍａｚｏｎ  ＥＢＳ等のサービスを用いる仮想ハードディスクの形をとってよい)が十分でないことを監視サービスが検出した場合、監視サービスは、ユーザの介入なしに、追加のストレージを自動的に供給する要求をトリガすることができる。同様に、採集パイプラインが用いるワーカーマシンが、日常的にＣＰＵ使用率が低い場合、監視サービスは、そのマシンをシャットダウンすることができる。
【０４０８】
リソース監視機能は、Ｎａｇｉｏｓ等の監視フレームワークに依存してよい。
【０４０９】
採集監視
基本的なリソース監視に加えて、追加の監視を、特に、採集パイプラインに対して行うことができる。採集プロセスの各段階(スキーマ推論、インデックスストアのロード、スキーマ計算など)に関するメタデータを、採集中にセントラルメタデータストアに記憶することができ、そのメタデータを用いてシステムに関するメトリクスをインテロゲートする（問い合わせる）ことができる。最も基本的なレベルでは、この機構を用いて、停止したプロセスまたは正確に機能していないプロセスを識別することができる。
【０４１０】
監視システムは、どの段階が自動的に再開するのか、及び、どのくらい長く各段階がかかるのかを追跡することもできる。これによって、サービスの問題の識別を支援してよい。さらに、監視システムからの履歴データは、ユーザデータの異常を示し得る。例えば、一定量のソースデータのロードにかかる時間が大きく変わった場合、そのデータのどの特性が変更された可能性があるのかをユーザが調べるために、そのデータにフラグを立てることができる。
【０４１１】
クエリ監視
監視システムは、インデックスストアまたはデータウェアハウスに対して行われるクエリの実行時間を監視することができる。類似のクエリの実行時間がどのように変化するかを観察することによって、システムの問題の可能性、及び、ソースデータの特性の変化を、識別することができる。この情報は、データウェアハウスにおけるインデックスの使用、または、インデックスストアにおけるクエリ計画を知らせることができる。例えば、めったにクエリされないカラムは、専用インデックスを有する必要はないかもしれず、クエリ時に、一定の方法でソートされることが多いカラムは、頻繁なクエリに従ってソートされた新しいインデックスを有することによって利益を得てよい。
【０４１２】
結論
上記は、事実上単なる例示にすぎず、その開示、用途、または使用に限定することを意図してはいない。開示の広範な教示は、様々な形態で実装することができる。従って、この開示は特定の例を含むが、開示の真の範囲は、それに限定されるべきではない。図面、明細書、及び、特許請求の範囲を検討すると、他の変更形態が明らかになるであろう。本明細書においては、Ａ、Ｂ、及び、Ｃの少なくとも１つという文言は、非排他的論理ＯＲを使用する論理（ＡまたはＢまたはＣ）を意味すると解釈されるべきである。方法内の１つまたは複数のステップは、本開示の原理を変えること無く、異なる順序で（または同時に）実行されてよいことは理解されたい。
【０４１３】
以下の定義を含むこの出願において、モジュールという用語は、回路という用語と置き換え可能である。モジュールという用語は、特定用途向け集積回路（ＡＳＩＣ）、デジタル、アナログ、もしくはアナログ／デジタル混合ディスクリート回路、デジタル、アナログ、もしくはアナログ／デジタル混合集積回路、組み合わせ論理回路、フィールドプログラマブルゲートアレイ（ＦＰＧＡ）、コードを実行する（共有、専用、もしくはグループ）プロセッサ、プロセッサが実行するコードを記憶する（共有、専用、もしくはグループ）メモリ、記載した機能を提供する他の適切なハードウェア構成要素、またはシステムオンチップにおけるものなどの上記の一部もしくは全ての組み合わせ、を指してよく、それらの一部であってよく、または、それらを含み得る。
【０４１４】
コードという用語は、上記で使用される際、ソフトウェア、ファームウェア、及び／またはマイクロコードを含んでよく、プログラム、ルーチン、関数、クラス、及び／またはオブジェクトのことを指してよい。共有プロセッサという用語は、多数のモジュールから幾つかのまたは全てのコードを実行する単一プロセッサを包含する。グループプロセッサという用語は、追加プロセッサと組み合わせて、１つまたは複数のモジュールから幾つかのまたは全てのコードを実行するプロセッサを包含する。共有メモリという用語は、多数のモジュールから幾つかのまたは全てのコードを記憶する単一メモリを包含する。グループメモリという用語は、追加メモリと組み合わせて、１つまたは複数のモジュールから幾つかのまたは全てのコードを記憶するメモリを包含する。メモリという用語は、コンピュータ可読媒体という用語のサブセットであってよい。コンピュータ可読媒体という用語は、媒体を通って伝搬する一時的な電気及び電磁信号を包含せず、従って、有形及び非一時的であると考えてよい。非一時的な有形のコンピュータで可読媒体の例は、不揮発性メモリ、揮発性メモリ、磁気ストレージ、及び、光ストレージを含むが、それらに限定されない。
【０４１５】
この出願に記載された装置及び方法は、１つまたは複数のプロセッサによって実行される１つまたは複数のコンピュータプログラムによって部分的にまたは全体的に実装されてよい。コンピュータプログラムは、少なくとも１つの非一時的な有形のコンピュータ可読媒体上に記憶されるプロセッサ実行可能命令を含む。コンピュータプログラムはまた、記憶されたデータを含んでよく、及び／または、記憶されたデータに依存してよい。
【図１Ａ】
0006416194.tif 000002
【図１Ｂ】
0006416194.tif 000003
【図１Ｃ】
0006416194.tif 000004
【図１Ｄ】
0006416194.tif 000005
【図２Ａ】
0006416194.tif 000006
【図２Ｂ】
0006416194.tif 000007
【図２Ｃ】
0006416194.tif 000008
【図２Ｄ】
0006416194.tif 000009
【図２Ｅ】
0006416194.tif 000010
【図２Ｆ】
0006416194.tif 000011
【図３】
0006416194.tif 000012
【図４】
0006416194.tif 000013
【図５】
0006416194.tif 000014
【図６】
0006416194.tif 000015
【図７】
0006416194.tif 000016
【図８】
0006416194.tif 000017
【図９】
0006416194.tif 000018
【図１０Ａ】
0006416194.tif 000019
【図１０Ｂ】
0006416194.tif 000020
【図１１】
0006416194.tif 000021
【図１２】
0006416194.tif 000022
【図１３Ａ】
0006416194.tif 000023
【図１３Ｂ】
0006416194.tif 000024
【図１３Ｃ】
0006416194.tif 000025
【図１３Ｄ】
0006416194.tif 000026
【図１３Ｅ】
0006416194.tif 000027
【図１４】
0006416194.tif 000028
【図１５】
0006416194.tif 000029
【図１６Ａ】
0006416194.tif 000030
【図１６Ｂ】
0006416194.tif 000031