查詢計畫

Python Spark SQL 入門

Mark Plutowski

Data Scientist

Explain

EXPLAIN SELECT * FROM table1
Python Spark SQL 入門

載入 DataFrame 並註冊

df = spark.read.load('/temp/df.parquet')
df.registerTempTable('df')
Python Spark SQL 入門

執行 EXPLAIN 查詢

spark.sql('EXPLAIN SELECT * FROM df').first()
Row(plan='== Physical Plan ==\n
*FileScan parquet [word#1928,id#1929L,title#1930,part#1931] 
  Batched: true, 
  Format: Parquet, 
  Location: InMemoryFileIndex[file:/temp/df.parquet], 
  PartitionFilters: [], 
  PushedFilters: [], 
  ReadSchema: struct<word:string,id:bigint,title:string,part:int>')

Python Spark SQL 入門

解讀 EXPLAIN 輸出

== Physical Plan ==

  • FileScan parquet [word#1928,id#1929L,title#1930,part#1931]
  • Batched: true,
  • Format: Parquet,
  • Location: InMemoryFileIndex[file:/temp/df.parquet],
  • PartitionFilters: [],
  • PushedFilters: [],
  • ReadSchema: struct<word:string,id:bigint,title:string,part:int>'
Python Spark SQL 入門

df.explain()

df.explain()
== Physical Plan ==
FileScan parquet [word#963,id#964L,title#965,part#966] 
Batched: true, Format: Parquet, 
Location: InMemoryFileIndex[file:/temp/df.parquet], 
PartitionFilters: [], PushedFilters: [], 
ReadSchema: struct<word:string,id:bigint,title:string,part:int>
spark.sql("SELECT * FROM df").explain()
== Physical Plan ==
FileScan parquet [word#712,id#713L,title#714,part#715] 
Batched: true, Format: Parquet, 
Location: InMemoryFileIndex[file:/temp/df.parquet], 
PartitionFilters: [], PushedFilters: [], 
ReadSchema: struct<word:string,id:bigint,title:string,part:int>

Python Spark SQL 入門

快取後的 df.explain()

df.cache()
df.explain()
== Physical Plan ==
InMemoryTableScan [word#0, id#1L, title#2, part#3]
   +- InMemoryRelation [word#0, id#1L, title#2, part#3], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
      +- FileScan parquet [word#0,id#1L,title#2,part#3] 
         Batched: true, Format: Parquet, Location: 
         InMemoryFileIndex[file:/temp/df.parquet], 
         PartitionFilters: [], PushedFilters: [], 
         ReadSchema: struct<word:string,id:bigint,title:string,part:int>
spark.sql("SELECT * FROM df").explain()
== Physical Plan ==
InMemoryTableScan [word#0, id#1L, title#2, part#3]
   +- InMemoryRelation [word#0, id#1L, title#2, part#3], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
     +- FileScan parquet [word#0,id#1L,title#2,part#3] 
        Batched: true, Format: Parquet, 
        Location: InMemoryFileIndex[file:/temp/df.parquet], 
        PartitionFilters: [], PushedFilters: [], 
        ReadSchema: struct<word:string,id:bigint,title:string,part:int>

Python Spark SQL 入門

依詞頻排序的查詢

SELECT word, COUNT(*) AS count 
FROM df 
GROUP BY word 
ORDER BY count DESC

對應的點記法作法:

df.groupBy('word')
  .count()
  .sort(desc('count'))
  .explain()
Python Spark SQL 入門

以 DataFrame 點記法執行相同查詢

== Physical Plan ==
*Sort [count#1040L DESC NULLS LAST], true, 0
+- Exchange rangepartitioning(count#1040L DESC NULLS LAST, 200)
   +- *HashAggregate(keys=[word#963], functions=[count(1)])
      +- Exchange hashpartitioning(word#963, 200)
         +- *HashAggregate(keys=[word#963], functions=[partial_count(1)])
            +- InMemoryTableScan [word#963]
                  +- InMemoryRelation [word#963, id#964L, title#965, part#966],
                     true,10000, StorageLevel(disk, memory, deserialized,
                     1 replicas)
                        +- *FileScan parquet [word#963,id#964L,title#965,part#966]
                           Batched: true, Format: Parquet,
                           Location: InMemoryFileIndex[file:/temp/df.parquet],
                           PartitionFilters: [], PushedFilters: [],
                           ReadSchema: struct<word:string,id:bigint,title:string,part:int>
Python Spark SQL 入門

自下而上閱讀

  • FileScan parquet
  • InMemoryRelation
  • InMemoryTableScan
  • HashAggregate(keys=[word#963], ...)`
  • HashAggregate(keys=[word#963], functions=[count(1)])`
  • Sort [count#1040L DESC NULLS LAST]`
Python Spark SQL 入門

查詢計畫

== Physical Plan ==
*Sort [count#1160L DESC NULLS LAST], true, 0
+- Exchange rangepartitioning(count#1160L DESC NULLS LAST, 200)
   +- *HashAggregate(keys=[word#963], functions=[count(1)])
      +- Exchange hashpartitioning(word#963, 200)
         +- *HashAggregate(keys=[word#963], functions=[partial_count(1)])
            +- *FileScan parquet [word#963] Batched: true, Format: Parquet,
               Location: InMemoryFileIndex[file:/temp/df.parquet], PartitionFilters: [],
               PushedFilters: [], ReadSchema: struct<word:string>

前一個計畫有下列行,但在上面的計畫中缺少:

...
            +- InMemoryTableScan [word#963]
                  +- InMemoryRelation [word#963, id#964L, title#965, part#966], true, 10000,
                     StorageLevel(disk, memory, deserialized, 1 replicas)
...
Python Spark SQL 入門

一起來練習吧!

Python Spark SQL 入門

Preparing Video For Download...