Best practices
- Каждый вызов
DROP
добавляет этап в плане, поэтому лучше избегать множественного исключения колонок. Эффективнее использовать одиночныйSELECT
с нужным набором колонок; - использование операции
LIMIT
имеет свои особенности, влияющие на производительность. В Apache Spark она работает следующим образом: на каждой партиции выполняется стадия LocalLimit, её результат отправляется в shuffle и по всем собранным в shuffle результатам выполняется операция GlobalLimit. В случае использованияlimit(x).collect()
илиtake(x)
операция проходит в несколько итераций. Изначально количество участвующих партиций начинается с одной и с каждой итерацией умножается на значение параметраspark.sql.limit.scaleUpFactor
(по умолчанию равно четырём). В случае использования операцийcount()
илиwrite.save("/output/path")
операция LocalLimit выполняется на каждой партиции, и для больших датасетов с множеством партиций производительность limit ухудшается. Существует два варианта решения данной проблемы:- если значение limit является небольшим, таким, что результат выполнения take(x) помещается в памяти драйвера, можно использовать
limitedDf = spark.createDataFrame(spark.sparkContext.parallelize(df.take(10000)), df.schema)
; - в качестве альтернативы операции
LIMIT
можно использовать TABLESAMPLE. Но если указыватьTABLESAMPLE (x ROWS)
, то в плане выполнения такой вызов будет эквивалентенLIMIT x
.
- если значение limit является небольшим, таким, что результат выполнения take(x) помещается в памяти драйвера, можно использовать
- Для чтения данных, использующих Hive-совместимую схему партиционирования по директориям в Кипарисе, опция
recursiveFileLookup
должна явно быть выставлена вfalse
:spark.read.option("recursiveFileLookup", "false")
. В SPYT она по умолчанию выставлена вtrue
для унификации с поведением YQL и CHYT.