2024.10.21
お互い疑心暗鬼になりがちな、経営企画と事業部の壁 組織に「分断」が生まれる要因と打開策
リンクをコピー
記事をブックマーク
上新卓也氏:それでは発表を始めます。『Deep Dive into Spark SQL with Advanced Performance Tuning』ということで、Spark SQLの内部の詳細とそれらを応用したパフォーマンスチューニングについてお話します。
Databricksでソフトウェアエンジニアとして働いています。Apache Sparkのコミッターで、TwitterやGitHubは基本的にueshinというアカウントで活動しています。
DatabricksはApache Sparkの開発初期メンバーによって設立された会社で、Sparkをベースとしたデータサイエンスであったりエンジニアリングであったりを統合的に扱うUnified Analytics Platformを提供しています。このクラウドサービスはAzureやAWSで利用可能ですので、興味のある方はご利用ください。
それではSpark SQLの話に移っていきます。Spark SQLはSparkのコンポーネントの1つで、スケーラブルで効率的にリレーショナル処理を行うためのものになっています。
Spark SQLはさまざまな異なるデータソース、例えばCassandraやKafkaやRDBMSなどにあるデータや、またファイルベースのさまざまなファイルフォーマット、Parquet、ORC、CSV、JSONなどのデータを読み込んで統合して解析や処理をすることができます。
APIとしてはSQLをはじめとしてそれ以外にもPython、Scala、Java、Rといった言語から利用できるAPIを提供しています。
実際のところはSpark SQLとは言うんですが、SQLのためだけのものではありません。Sparkのエコシステムの新しいコアとなりつつあります。
ざっくりこんな感じになっています。
Spark SQLは一番上のところにある、SQLやDataFrame、Datasetといったこの辺がUser APIとして提供してあります。
そのクエリが、その下にあるCatalyst OptimizationやTungsten execution engineと呼ばれるもので実行されます。データについてはData Source Connectorsがありまして、標準でビルトインで提供してあるものと、APIは公開されているので独自で実装することもできるようになっています。
現在、DataSource APIのバージョン1はすでに提供されているんですけれども、より洗練されたかたちとしてv2の実装が進行中です。Spark3.0までにはみなさんが利用できるようになる見込みになっています。
この濃い青い部分がSpark SQLの中身です。この上にStructured Streaming、ストリーミング処理のライブラリや、機械学習のためのMLlib、あとはグラフ処理のためのGraphFrameなど、その他いろいろなプログラム、ライブラリが実装されています。
SQLやDataFrame、Dataset APIを使って書いた、みなさんが作るSparkのアプリケーションもこれから説明するSparkSQLの最適化であったり、そういった高速化のためのいろいろな機能の恩恵を受けることができるようになっています。
Spark SQLというのは本質的に何かと言うと、みなさんが定義するクエリからSparkを駆動するためのRDDのコンパイラですね。クエリからRDDに変換するためのコンパイラが本質的な動きになります。のちほど1個1個詳細に追っていきますが、ざっくりと処理の流れを見てみます。
まず先ほどのUser APIが一番左にあって、ここで何をしたいのかをみなさんに定義していただきます。そのAPIで作ったプランがここにあって、これがいわゆるASTとか、Abstract Syntax Treeと呼ばれるものです。この時点では例えばどの部分がtableを表すとかそういうことはまだわからないかもしれない。
そのあとのAnalyzerであったり、ここにMetadata Catalogがありますけれども、このあたりを使ってそれぞれのツリーのノードがどういうことを表しているのかを解析します。そのあとにOptimizer、Plannerがheuristics、つまり経験則、もしくはコストに基づいたルールで実行を最適化していきます。
最後にできあがったPhysical Planに対して、これの動きを実際にRDDで動かすためのJavaコードを吐いて、それをコンパイルしてJVM上で実行するというような流れで処理を行なっています。
間にちょいちょいチューニングの話が入ってくるんですけれども、一番基本的な話ではこのプランを見て解釈してそれをチューニングしていくというのが基本的なSpark SQLのチューニングの話になります。
このプランはSQLでEXPLAINコマンドであったりとか、Dataset、DataFrameAPIであればexplain()というメソッドが提供されているのでそれを使ってプランを見るというかたちになります。
今日の発表ではプランの見方などには触れませんが、この間あったHadoop / Spark Conferenceのときに弊社のマネージャーが来ていまして、その人が実際の例に沿ってプランの見方やそれに対するいろいろな解釈を用意しています。そのスライドが公開されていますので、興味がある方はHadoop Conferenceで探して見てみてください。
詳細について1個1個見ていきます。
一番はじめの左のほうにあるやつがUser APIですね。
Spark SQLのUser APIは宣言的APIです。何をしたいのか、何がほしいのかを宣言的に組み立てます。まあSQLとかはそういう言語ですよね。
SQLのAPIとしては標準SQLの2003、もしくはHiveQLを利用することができます。あとそれ以外にDataset、DataFrameのAPIがありますけれども、これはSQLで表現しきれない範囲であってももっといろんな処理を書くことができるようになっています。
Dataset、DataFrameについてはさっきもありましたが、Java、Scala、Python、R、それぞれの言語に組み込まれた普通のライブラリのようなインターフェイスを持っていまして、かなり便利に使うことができます。
ちなみにDatasetについてはJavaとScalaのコンパイラの機能を使っている関係上、PythonやRではサポートされていません。SQLとかDataset、DataFrameを使ってプログラムを書いていくと自動的に裏側ではUnresolvedなLogical Planというのができます。
この次の処理としてはAnalyzerがMetadata Catalogを使ってどのノードが何をしている処理を表すのかというのを解決していきます。
MetadataのCatalogには4種類あります。
1つ目はHive metastoreですね。これはtableのためのカタログです。設定によってPersistentにすることができるので、Sparkアプリケーションを1回落としてまた起動して続きをやるみたいなこともできるようになっています。
次2つはtemporary view managerとglobal temporary view managerで、これは違いとしてはSession-localであるかCross-sessionであるかと。sessionをまたいで使えるかという違いがあります。
最後にfunction registryというのは関数ですね、関数のカタログになっています。これはSession-localなので、UDFとかを定義してあるsessionで登録しても別のsessionでは新たに登録し直さないといけないので、気をつけてください。
CatalogについてPerformance Tipsですけれども、Hive metastoreからPartition metadataを取得するのに非常に時間がかかる場合があります。この場合にはまず1個目はとりあえずHive metastoreのアップグレードをしてみてください。新しいバージョンではパフォーマンスが改善しているので、できるだけ新しいバージョンを使ったほうがいいです。
可能であればCardinalityの高いパーティションカラムを避ける、ですね。パーティションというのはまたあとでもう1回説明しますが、データのセレクトをするときに余計なファイルを読まないようにするような機能があります。Hiveでもあるので、ご存知の方も多いと思います。
それがあるんですけれども、あまりにもCardinalityの高いパーティションがあるとHiveのMetastoreのパフォーマンスが落ちるので、あんまり高すぎると良くないという感じですね。
せっかくパーティションを使っているのであったら、すべてのパーティションを使うのではなく、パーティションの絞り込みを行うような条件をクエリに付けるようにしてください。
これで、MetadataのCatalogからtableであったり関数であったりとか、そういうものをいろいろと解決していくわけです。
次ですね。Optimizerの処理の前にCache Managerが入ります。キャッシュをまず先に差し込みます。
Cache Managerはクエリのプランを調べて、そのプランの一部がキャッシュのプランと一致した場合に、そのプランの一致した部分をキャッシュのプランに置き換えます。
Cache ManagerはCross-sessionなので別のsessionで意図せずキャッシュを使っていた、みたいなことがあって。基本は速くなるかもしれませんが、「あれ、おかしいな」みたいなことになるかもしれないので、これは気をつけたほうがいいかなと思います。
キャッシュデータはキャッシュを使うクエリが初めて実行されたときに作成されます。また、依存しているtableやviewのデータが更新されるとキャッシュを一旦破棄して、次回利用時に再度キャッシュを作るということをします。
これは依存しているtableのデータの更新があったにもかかわらず前のキャッシュを使っていると、なんかtableと整合性が取れないよ、みたいなことになるので、もとになるデータが更新されたらキャッシュをクリアするというようなことですね。
ここでTipsなんですけれども、実はキャッシュは必ずしも速いというわけではないんですね。キャッシュは基本的にメモリにあるんですけど、メモリがいっぱいになってしまうとディスクに書いてしまいます。メモリを1回クリアして、次に利用するときにまたディスクから読み直すということをします。そのため、場合によってはキャッシュではなく、それまでのクエリをもう1回実行したほうが速い場合があります。
なのでメモリがいっぱいあるからいいやとガシガシとキャッシュを使っていると、むしろ遅くなる場合があるので、必要のないキャッシュはしないようにして、ピンポイントで「ここは絶対必要」みたいなところにピッピッピッと置いていくのがいいかなと思います。
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2024.11.20
「元エースの管理職」が若手営業を育てる時に陥りがちな罠 順調なチーム・苦戦するチームの違いから見る、育成のポイント
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.15
好きなことで起業、赤字を膨らませても引くに引けない理由 倒産リスクが一気に高まる、起業でありがちな失敗