spark.sqlで結合したい2つの大きなHiveテーブルがあります。テーブル1とテーブル2があり、テーブル1に500万行、テーブル2に7000万行があるとします。テーブルはスナップ形式であり、Hiveに寄木細工のファイルとして保存されます。
それらを結合して、いくつかの列でいくつかの集計を行いたいと思います。たとえば、2つの条件(col1、col2など)でフィルタリングしながら、すべての行と列の平均(doubleColumnなど)をカウントします。
注:私は単一のマシンでのテストインストールで作業しています(ただし、これは非常に強力です)。おそらくクラスター内ではパフォーマンスが異なると思います。
私の最初の試みは、次のようなsparksqlを使用することです。
val stat = sqlContext.sql("select count(id), avg(doubleColumn) " +
" FROM db.table1 as t1 JOIN db.table2 " +
" ON t1.id = t2.id " +
" WHERE col1 = val1 AND col2 = val2").collect
残念ながら、エグゼキュータとドライバごとに少なくとも8 GBのメモリを割り当てた場合でも、これは約5分で非常に不十分に実行されます。また、データフレーム構文を使用して、最初に行をフィルタリングし、次のような選択性を高めるために特定の列のみを選択しようとしました。
//Filter first and select only needed column
val df = spark.sql("SELECT * FROM db.tab1")
val tab1= df.filter($"col1" === "val1" && $"col2" === "val2").select("id")
val tab2= spark.sql("SELECT id, doubleColumn FROM db.tab2")
val joined = tab1.as("d1").join(tab2.as("d2"), $"d1.id" === $"d2.id")
//Take the aggregations on the joined df
import org.apache.spark.sql.functions;
joined.agg(
functions.count("id").as("count"),
functions.avg("doubleColumn").as("average")
).show();
ただし、これによるパフォーマンスの大幅な向上はありません。参加のパフォーマンスを向上させるにはどうすればよいですか?
このspark.sqlまたはデータフレーム構文を実行するための最良の方法はどれですか?
より多くのエグゼキュータまたはメモリを与えることは助けになりますか?
キャッシュを使用する必要がありますか?
私は両方のデータフレームtab1、tab2をキャッシュし、結合集約は大幅に向上しましたが、多くのユーザーが同時にいくつかの分析クエリを要求する同時実行に関心があるため、データフレームをキャッシュすることは実用的ではないと思います。
単一ノードで作業していて、クラスター上の実稼働環境に移動すると問題が解決するため、何もする必要はありませんか?
ボーナス質問: Impalaでこのクエリを試したところ、約40秒かかりましたが、spark.sqlよりもはるかに優れていました。インパラはどうして火花よりも優れているのでしょうか?!
このspark.sqlまたはデータフレーム構文を実行するための最良の方法はどれですか?
違いはありません。
より多くのエグゼキュータまたはメモリを与えることは助けになりますか?
問題の原因がデータの偏りではなく、構成を正しく調整した場合のみ。
キャッシュを使用する必要がありますか?
入力データが複数回再利用される場合は、パフォーマンスの観点から(すでに決定したように)推奨される場合があります。
単一ノードで作業していて、クラスター上の実稼働環境に移動すると問題が解決するため、何もする必要はありませんか?
一般に、単一ノードでのパフォーマンステストはまったく役に立ちません。ボトルネック(ネットワークIO /通信)と利点(償却されたディスクI / Oとリソース使用量)の両方を見逃しています。
ただし、parallelsm(spark.sql.shuffle.partitions
、sql.default.parallelism
および入力分割サイズの増加)を大幅に減らすことができます。負荷を分散するように設計されたCounterintuitivSparkスタイルの並列処理は、資産というよりも、単一のマシンでの責任です。通信はシャッフル(ディスク書き込み!)に依存しているため、共有メモリに比べて処理が非常に遅くなり、スケジューリングのオーバーヘッドが大きくなります。
インパラはどうして火花よりも優れているのでしょうか?!
これは、低レイテンシの同時クエリ用に特別に設計されているためです。これは、Spark(データベースとETLフレームワーク)の目標であったものではありません。
あなたとして
並行性に関心があるため、多くのユーザーが同時にいくつかの分析クエリを要求します。
Sparkは正しい選択のようには聞こえません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加