Sorgu planında BroadcastNestedLoopJoin olduğunda yayın devre dışı bırakılıyor

Bu makalede, sorgu planının fiziksel planda olması durumunda yayının nasıl devre dışı bırakılacağı açıklanır BroadcastNestedLoopJoin .

Yayın eşiğini devre dışı bıraktıktan sonra,-1 ' e ayarlayarak yayının durdurulmasını beklediğinizi, spark.sql.autoBroadcastJoinThreshold ancak Apache Spark daha büyük tabloyu yayınladıktan ve bir yayın hatasıyla başarısız olmasına çalışır.

Bu davranış bir hata DEĞIL, ancak beklenmeyen bir durum olabilir. Beklenen davranışı inceleyeceğiz ve bu sorun için bir azaltma seçeneği sağlayacağız.

Tablo oluşturma

Biri null değerler table_withNull ve diğeri null değer olmadan olmak üzere iki tablo oluşturarak başlayın tblA_NoNull .

sql("SELECT id FROM RANGE(10)").write.mode("overwrite").saveAsTable("tblA_NoNull")
sql("SELECT id FROM RANGE(50) UNION SELECT NULL").write.mode("overwrite").saveAsTable("table_withNull")

Yayını devre dışı bırakma girişimi

spark.sql.autoBroadcastJoinThresholdBir yan tümcesine sahip bir alt sorguya sahip olan sorgu için yayını ayarlayarak yayını devre dışı bırakmayı denedik in .

spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)
sql("select * from table_withNull where id not in (select id from tblA_NoNull)").explain(true)

Sorgu planını gözden geçirmeniz durumunda BroadcastNestedLoopJoin Bu durum olası en son geri dönüş olur. Yayını devre dışı bırakmaya çalıştıktan sonra bile görüntülenir.

== Physical Plan ==
*(2) BroadcastNestedLoopJoin BuildRight, LeftAnti, ((id#2482L = id#2483L) || isnull((id#2482L = id#2483L)))
:- *(2) FileScan parquet default.table_withnull[id#2482L] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[dbfs:/user/hive/warehouse/table_withnull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<id:bigint>
+- BroadcastExchange IdentityBroadcastMode, [id=#2586]
   +- *(1) FileScan parquet default.tbla_nonull[id#2483L] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[dbfs:/user/hive/warehouse/tbla_nonull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<id:bigint>

İşlenen veriler yeterince büyükse, Spark tabloyu yayınladenediğinde Bu yayın hatalarıyla sonuçlanır.

Yerine kullanarak sorguyu yeniden yazın not exists````in

Bunun yerine sorguyu yeniden yazarak sorunu çözebilirsiniz not exists in .

// It can be rewritten into a NOT EXISTS, which will become a regular join:
sql("select * from table_withNull where not exists (select 1 from tblA_NoNull where table_withNull.id = tblA_NoNull.id)").explain(true)

Kullanarak not exists , sorgu ile çalışır SortMergeJoin .

== Physical Plan ==
SortMergeJoin [id#2482L], [id#2483L], LeftAnti
:- Sort [id#2482L ASC NULLS FIRST], false, 0
:  +- Exchange hashpartitioning(id#2482L, 200), [id=#2653]
:     +- *(1) FileScan parquet default.table_withnull[id#2482L] Batched: true, DataFilters: [], Format: Parquet, Location: InMemoryFileIndex[dbfs:/user/hive/warehouse/table_withnull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<id:bigint>
+- Sort [id#2483L ASC NULLS FIRST], false, 0
   +- Exchange hashpartitioning(id#2483L, 200), [id=#2656]
      +- *(2) Project [id#2483L]
         +- *(2) Filter isnotnull(id#2483L)
            +- *(2) FileScan parquet default.tbla_nonull[id#2483L] Batched: true, DataFilters: [isnotnull(id#2483L)], Format: Parquet, Location: InMemoryFileIndex[dbfs:/user/hive/warehouse/tbla_nonull], PartitionFilters: [], PushedFilters: [IsNotNull(id)], ReadSchema: struct<id:bigint>

Açıklama

Spark ve SQL 'in null işleme için biraz farklı semantiklerine sahip olduğundan Spark bunu otomatik olarak yapmaz.

SQL 'de, not in değerlerde null değer varsa not in sonucun boş olduğunu gösterir. Bu nedenle yalnızca ile yürütülebilir BroadcastNestedLoopJoin . not inKüme içinde null değer bulunmadığından emin olmak için tüm değerler bilinmelidir.

Örnek not defteri

Bu not defteri, Spark 'ın neden otomatik olarak geçiş yapmaz gösteren bir örnek BroadcastNestedLoopJoin içerir SortMergeJoin .

BroadcastNestedLoopJoin Örnek Not defteri

Not defterini alma