Spark DataFrames、 データセットとSQLマニュアル :
少数のHive最適化はまだSparkに含まれていません。これらの一部(インデックスなど)は、Spark SQLのメモリ内計算モデルのため、それほど重要ではありません。その他は、Spark SQLの将来のリリース用にスロット化されています。
Sparkを初めて使用するため、次の2つの理由から少し困惑しています。
Spark SQLはビッグデータを処理するように設計されており、少なくとも私のユースケースでは、データサイズは利用可能なメモリのサイズをはるかに超えています。これが珍しいことではないと仮定すると、「Spark SQLのメモリ内計算モデル」とはどういう意味ですか? Spark SQLは、データがメモリに収まる場合にのみ推奨されますか?
データがメモリに収まると仮定しても、非常に大きなデータセットのフルスキャンには時間がかかる可能性があります。私は この引数 をメモリ内データベースのインデックス作成に対して読みましたが、私は確信していませんでした。そこの例では、10,000,000レコードテーブルのスキャンについて説明していますが、それは実際にはビッグデータではありません。数十億のレコードがあるテーブルをスキャンすると、「SELECT x WHERE y = z」タイプの単純なクエリがすぐに返るのではなく、永遠にかかることがあります。
インデックスには、遅いINSERT/UPDATE、スペース要件などの欠点があることを理解しています。しかし、私のユースケースでは、最初に大量のデータを処理してSpark SQLにロードし、このデータを全体、それ以上の修正なし。 Spark SQLは、初期の分散処理とデータのロードに役立ちますが、インデックス作成の欠如により、インタラクティブな探索が予想以上に遅くなり、面倒になります。
それでは、なぜSpark SQLチームがインデックスを重要でないと考えているのか、それがロードマップから外れていると考えています。独自に同等のものを実装することなく、インデックス作成の利点を提供できる別の使用パターンがありますか?
入力データのインデックス作成
分散データ構造のインデックス作成:
インデックス化された構造のいくつかの形式がSparkエコシステムに存在すると言われています。最も注目すべきはDatabricksがそのプラットフォームで Data Skipping Index を提供していることです。
Succinct (今日はほとんど非アクティブ)などのその他のプロジェクトでは、異なるアプローチを採用し、ランダムアクセスをサポートした高度な圧縮技術を使用しています。
もちろん、これは疑問を提起します-効率的なランダムアクセスが必要な場合、最初からデータベースとして設計されているシステムを使用しないのはなぜですか。 Apache Foundationによって管理されている少なくともいくつかを含む、多くの選択肢があります。同時にSparkプロジェクトが進化するにつれて、使用した見積もりが将来のSpark=方向を完全に反映していない可能性があります。
一般的に、インデックスの有用性はよくても疑問です。代わりに、データのパーティション分割がより重要です。それらは非常に異なるものであり、選択したデータベースがインデックスをサポートしているからといって、Sparkがやろうとしていることを考えれば意味がありません。 。
それでは、インデックスとは何ですか?
永久記憶装置が非常に高価な(本質的に無料ではなく)昔、リレーショナルデータベースシステムは、永久記憶装置の使用を最小限に抑えることを目的としていました。リレーショナルモデルは、必然的に、レコードを複数の部分に分割し(データを正規化し)、それらを異なる場所に保存しました。顧客レコードを読み取るには、customer
テーブル、customerType
テーブルを読み取るか、address
テーブルからいくつかのエントリを取得するなどの方法があります。必要なものを見つけるためにテーブル全体を読む必要があり、非常に多くのテーブルをスキャンする必要があるため、非常にコストがかかります。
しかし、これが物事を行う唯一の方法ではありません。固定幅の列を用意する必要がない場合は、データのセット全体を1か所に保存できます。大量のテーブルでフルテーブルスキャンを実行する代わりに、単一のテーブルでのみ実行する必要があります。そして、それはあなたが思っているほど悪くはありません、特にデータを分割できるなら。
40年後、物理法則が変更されました。ハードドライブのランダムな読み取り/書き込み速度と線形の読み取り/書き込み速度は大幅に異なります。基本的に、ディスクごとに1秒間に350回のヘッド移動を行うことができます。 (やや多かれ少なかれ、それは良い平均数です。)一方、単一のディスクドライブは1秒あたり約100 MBを読み取ることができます。どういう意味ですか?
計算して考えてみてください。つまり、という意味です。ディスクヘッドの移動あたり300 KB未満しか読み取っていない場合は、ドライブのスループットを調整しています。
うんちょっと考えてみてください。
インデックスの目的は、ディスクヘッドを目的のディスク上の正確な場所に移動し、そのレコードを読み取ることです。たとえば、address
の一部として結合されたcustomer
レコードだけです。記録。そして、それは無駄だと言います。
現代の物理学に基づいてインデックスを設計している場合、ターゲットデータの100 KB以内に収まるだけで済みます(データが大きなチャンクでレイアウトされていると仮定しますが、とにかくここで理論について話します) 。上記の数値に基づくと、それ以上の精度は無駄です。
次に、正規化されたテーブルの設計に戻ります。 customer
レコードは、実際には5つのテーブルに保持されている6つの行に分割されているとします。ディスクヘッドの合計6回の移動(インデックスがメモリにキャッシュされているため、ディスクの移動はないと想定します)。つまり、1.8 MBの線形/非正規化された顧客レコードを読み取ることができ、同じくらい効率的です。
また、顧客履歴についてはどうですか?今日の顧客がどのように見えるかだけを見たくなかった場合、完全な履歴または履歴のサブセットが必要だと想像してください。上記のすべてに10または20を掛けると、画像が得られます。
インデックスよりも優れているのは、データのパーティション分割です。つまり、すべての顧客レコードを1つのパーティションにまとめます。ディスクヘッドを1回動かすだけで、顧客履歴全体を読み取ることができます。 1つのディスクヘッドが移動します。
インデックスが必要な理由をもう一度教えてください。
インデックスvs ___?
誤解しないでください。検索を「事前に調理する」ことに価値があります。しかし、物理の法則は、従来のインデックスよりも優れた方法を示唆しています。顧客レコードを正確に1つの場所に保存し、それへのポインター(インデックス)を作成する代わりに、レコードを複数の場所に保存してみませんか?
ディスクスペースは基本的に無料です。使用するストレージの量(リレーショナルモデルの古いアーティファクト)を最小限にしようとする代わりに、ディスクを検索キャッシュとして使用します。
地理的および営業担当の両方でリストされた顧客を見たいと思う場合、それらの検索を最適化する方法で保存された顧客レコードの複数のコピーを作成します。私が言ったように、メモリキャッシュのようにディスクを使用します。さまざまな永続データを一緒に描画してメモリ内キャッシュを構築する代わりに、永続データを構築してメモリ内キャッシュをミラーリングするので、必要なことはそれを読み取るだけです。実際、メモリに保存しようとしても気にしないでください-必要なときはいつでもディスクから直接読んでください。
気が狂ったように思える場合は、これを考慮してください。メモリにキャッシュすると、おそらく2回キャッシュすることになります。 OS /ドライブコントローラーがメインメモリをキャッシュとして使用している可能性があります。他の誰かが既にいるので、データをキャッシュすることを気にしないでください!
しかし、私は脱線します...
簡単に言えば、Sparkは、適切な種類のインデックス付け-将来の使用をより効率的にするために未加工データから複雑な派生データを作成する機能を完全にサポートします。あなたがそれをしたい。