web-dev-qa-db-ja.com

パーティション内の要素数を取得するにはどうすればよいですか?

パーティションIDを指定して、spark RDDパーティションの要素数を取得する方法はありますか?パーティション全体をスキャンせずに.

このようなもの:

Rdd.partitions().get(index).size()

スパーク用のそのようなAPIが見当たらないことを除いて。何か案は?回避策は?

ありがとう

16
Geo

以下は、各パーティションのサイズである要素を持つ新しいRDDを提供します。

rdd.mapPartitions(iter => Array(iter.size).iterator, true) 
26
pzecevic

PySpark:

_num_partitions = 20000
a = sc.parallelize(range(int(1e6)), num_partitions)
l = a.glom().map(len).collect()  # get length of each partition
print(min(l), max(l), sum(l)/len(l), len(l))  # check if skewed
_

スパーク/スカラ:

_val numPartitions = 20000
val a = sc.parallelize(0 until 1e6.toInt, numPartitions )
val l = a.glom().map(_.length).collect()  # get length of each partition
print(l.min, l.max, l.sum/l.length, l.length)  # check if skewed
_

RDDだけでなく、データフレームでも同じことが可能です。上記のコードにDF.rdd.glom ...を追加するだけです。

glom()は各パーティションの要素を リストに に変換するため、メモリを大量に消費することに注意してください。メモリ使用量の少ないバージョン(pysparkバージョンのみ):

_import statistics 

def get_table_partition_distribution(table_name: str):

    def get_partition_len (iterator):
        yield sum(1 for _ in iterator)

    l = spark.table(table_name).rdd.mapPartitions(get_partition_len, True).collect()  # get length of each partition
    num_partitions = len(l)
    min_count = min(l)
    max_count = max(l)
    avg_count = sum(l)/num_partitions
    stddev = statistics.stdev(l)
    print(f"{table_name} each of {num_partitions} partition's counts: min={min_count:,} avg±stddev={avg_count:,.1f} ±{stddev:,.1f} max={max_count:,}")


get_table_partition_distribution('someTable')

_

のようなものを出力します

someTable各1445パーティションのカウント:min = 1,201,201 avg±stddev = 1,202,811.6±21,783.4 max = 2,030,137

20
Tagar

pzecevicの答えは機能しますが、概念的には配列を作成してからそれを反復子に変換する必要はありません。イテレータを直接作成し、collect呼び出しでカウントを取得するだけです。

rdd.mapPartitions(iter => Iterator(iter.size), true).collect()

追伸Iterator.applyは引数を配列に変換する可能性が高いため、彼の答えが実際により多くの作業を行っているかどうかはわかりません。

3
Tom Wang