<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>pyspark - DataTalks.RU. Data Engineering / DWH / Data Pipeline</title>
	<atom:link href="https://datatalks.ru/tag/pyspark/feed/" rel="self" type="application/rss+xml" />
	<link>https://datatalks.ru/tag/pyspark/</link>
	<description>RoadMap для инженера данных. Дорожная карта по инструментам Data Engineer</description>
	<lastBuildDate>Thu, 25 Dec 2025 18:38:41 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://datatalks.ru/wp-content/uploads/2024/12/cropped-logo_datatalks-32x32.png</url>
	<title>pyspark - DataTalks.RU. Data Engineering / DWH / Data Pipeline</title>
	<link>https://datatalks.ru/tag/pyspark/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>PySpark Interview &#8212; Вопросы и ответы</title>
		<link>https://datatalks.ru/pyspark-interview-questions-and-answers/</link>
					<comments>https://datatalks.ru/pyspark-interview-questions-and-answers/#respond</comments>
		
		<dc:creator><![CDATA[Data Engineer (Admin)]]></dc:creator>
		<pubDate>Thu, 25 Dec 2025 17:48:14 +0000</pubDate>
				<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[Apache PySpark]]></category>
		<category><![CDATA[pyspark]]></category>
		<guid isPermaLink="false">https://datatalks.ru/?p=2580</guid>

					<description><![CDATA[<p>Basic PySpark Interview Questions Каковы основные преимущества использования PySpark по сравнению с традиционным Python для обработки больших данных? PySpark, Python API для Apache Spark, предлагает несколько преимуществ по сравнению с традиционным Python для обработки больших данных. К ним относятся масштабируемость для работы с массивными наборами данных, высокая производительность за счёт параллельной обработки, отказоустойчивость для обеспечения [&#8230;]</p>
<p>Сообщение <a href="https://datatalks.ru/pyspark-interview-questions-and-answers/">PySpark Interview &#8212; Вопросы и ответы</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Basic PySpark Interview Questions</h1>
<h2>Каковы основные преимущества использования PySpark по сравнению с традиционным Python для обработки больших данных?</h2>
<p><strong>PySpark</strong>, <strong>Python API</strong> для <strong>Apache Spark</strong>, предлагает несколько преимуществ по сравнению с традиционным Python для обработки больших данных. К ним относятся масштабируемость для работы с массивными наборами данных, высокая производительность за счёт параллельной обработки, отказоустойчивость для обеспечения надёжности данных, а также интеграция с другими инструментами для работы с большими данными внутри экосистемы Apache.</p>
<h2>Как создать SparkSession в PySpark? Каковы его основные назначения?</h2>
<p>В PySpark <strong>SparkSession</strong> является точкой входа для использования функциональности Spark и создаётся с помощью API <code>SparkSession.builder</code>. Его основные назначения включают взаимодействие с <strong>Spark SQL</strong> для обработки структурированных данных, создание <strong>DataFrame</strong>, конфигурирование свойств Spark, а также управление жизненным циклом <strong>SparkContext</strong> и <strong>SparkSession</strong>. Ниже приведён пример того, как может быть создан <strong>SparkSession</strong>:</p><pre class="urvanov-syntax-highlighter-plain-tag">from pyspark.sql import SparkSession
     
spark = SparkSession.builder \
         .appName("MySparkApp") \
         .master("local[*]") \
         .getOrCreate()</pre><p></p>
<h2>Опиши различные способы чтения данных в PySpark.</h2>
<p><strong>PySpark</strong> поддерживает чтение данных из различных источников, таких как <strong>CSV</strong>, <strong>Parquet</strong> и <strong>JSON</strong>, среди прочих. Для этой цели он предоставляет разные методы, включая <code>spark.read.csv()</code>, <code>spark.read.parquet()</code>, <code>spark.read.json()</code>, <code>spark.read.format()</code> и <code>spark.read.load()</code>. Ниже приведён пример того, как данные могут быть прочитаны в PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag">df_from_csv = spark.read.csv("my_file.csv", header=True)
df_from_parquet = spark.read.parquet("my_file.parquet")
df_from_json = spark.read.json("my_file.json")</pre><p></p>
<h2>Как обрабатывать пропущенные данные в PySpark?</h2>
<p>В PySpark пропущенные данные можно обрабатывать с использованием нескольких методов. Можно удалять строки или столбцы, содержащие пропущенные значения, с помощью метода <code>.dropna()</code>. Также можно заполнять пропущенные данные конкретным значением или использовать методы интерполяции с помощью <code>.fillna()</code>. Кроме того, можно выполнять импутацию пропущенных значений с использованием статистических методов, таких как среднее значение или медиана, применяя <code>Imputer</code>. Ниже приведён пример обработки пропущенных данных в PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag"># Как удалить строки
df_from_csv.dropna(how="any")

# Как заполнить пропущенные значения константой
df_from_parquet.fillna(value=2)

# Как выполнить импутацию значений медианой
from pyspark.ml.feature import Imputer
imputer = Imputer(strategy="median", inputCols=["price","rooms"], outputCols=["price_imputed","rooms_imputed"])
model = imputer.fit(df_from_json)
df_imputed = model.transform(df_from_json)</pre><p></p>
<h2>Как можно кэшировать данные в PySpark для повышения производительности?</h2>
<p>Одним из преимуществ PySpark является возможность использовать методы <code>.cache()</code> или <code>.persist()</code> для хранения данных в памяти или на заданном уровне хранения. Это улучшает производительность за счёт предотвращения повторных вычислений и снижения необходимости сериализации и десериализации данных. Ниже приведён пример того, как кэшировать данные в PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag"># Как кэшировать данные в памяти
df_from_csv.cache()

# Как сохранить данные на локальном диске
df_from_csv.persist(storageLevel=StorageLevel.DISK_ONLY)</pre><p>При использовании <code>cache()</code> применяется только уровень хранения по умолчанию:</p>
<ul>
<li><code>MEMORY_ONLY</code> для <strong>RDD</strong></li>
<li><code>MEMORY_AND_DISK</code> для <strong>Dataset</strong></li>
</ul>
<p>При использовании <code>persist()</code> вы можете указать нужный уровень хранения как для <strong>RDD</strong>, так и для <strong>Dataset</strong>.</p>
<p><strong>Из официальной документации:</strong></p>
<ul>
<li>Вы можете пометить <strong>RDD</strong> для сохранения с помощью методов <code>persist()</code> или <code>cache()</code>.</li>
<li>Каждый сохранённый <strong>RDD</strong> может храниться с использованием разного уровня хранения.</li>
<li>Метод <code>cache()</code> — это сокращённая форма использования уровня хранения по умолчанию, а именно <code>StorageLevel.MEMORY_ONLY</code> (хранение десериализованных объектов в памяти).</li>
</ul>
<p>Используйте <code>persist()</code>, если вы хотите назначить уровень хранения, отличный от:</p>
<ul>
<li><code>MEMORY_ONLY</code> для <strong>RDD</strong></li>
<li>или <code>MEMORY_AND_DISK</code> для <strong>Dataset</strong></li>
</ul>
<p><strong>Подробнее почитать:</strong></p>
<ul>
<li><a href="https://sparkbyexamples.com/spark/spark-difference-between-cache-and-persist/" target="_blank" rel="noopener">Spark Difference between Cache and Persist?</a></li>
</ul>
<h2>Опиши выполнение соединений в PySpark</h2>
<p><strong>PySpark</strong> позволяет выполнять несколько типов соединений, таких как <strong>inner</strong>, <strong>outer</strong>, <strong>left</strong> и <strong>right</strong>. Используя метод <code>.join()</code>, можно задать условие соединения через параметр on и тип соединения через параметр how, как показано в примере:</p><pre class="urvanov-syntax-highlighter-plain-tag"># Как выполнить inner join двух наборов данных
df_from_csv.join(df_from_json, on="id", how="inner")

# Как выполнить outer join наборов данных
df_from_json.join(df_from_parquet, on="product_id", how="outer")</pre><p></p>
<h2>В чём заключаются ключевые различия между RDD, DataFrame и Dataset в PySpark?</h2>
<p><strong>Spark Resilient Distributed Dataset (RDD)</strong>, <strong>DataFrame</strong> и <strong>Dataset</strong> являются ключевыми абстракциями в Spark, которые позволяют работать со структурированными данными в распределённой вычислительной среде. Несмотря на то что все они представляют данные, между ними существуют важные различия.</p>
<p><strong>RDD</strong> являются низкоуровневыми API, не имеющими схемы и предоставляющими полный контроль над данными; они представляют собой неизменяемые коллекции объектов.</p>
<p><strong>DataFrame</strong> являются высокоуровневыми API, построенными поверх <strong>RDD</strong> и оптимизированными для производительности, но не обладающими типобезопасностью; они организуют структурированные и полуструктурированные данные в именованные столбцы.</p>
<p><strong>Dataset</strong> объединяют преимущества <strong>RDD</strong> и <strong>DataFrame</strong>, являясь высокоуровневыми API, которые предоставляют типобезопасную абстракцию; они поддерживают <strong>Python</strong> и <strong>Scala</strong>, обеспечивают проверку типов во время компиляции и при этом работают быстрее, чем DataFrame.</p>
<h2>Объясни концепцию ленивых вычислений в PySpark. Как она влияет на производительность?</h2>
<p><strong>PySpark</strong> реализует стратегию, называемую <strong>ленивыми вычислениями</strong>, при которой преобразования, применяемые к распределённым наборам данных, таким как <strong>RDD</strong>, <strong>DataFrame</strong> или <strong>Dataset</strong>, не выполняются немедленно. Вместо этого Spark строит последовательность операций или преобразований, которые должны быть выполнены над данными, называемую ориентированным ациклическим графом, или DAG. Такой подход улучшает производительность и оптимизирует выполнение, поскольку вычисления откладываются до момента, когда вызывается действие и их выполнение становится действительно необходимым.</p>
<h2>Какова роль партиционирования в PySpark и каким образом оно может улучшить производительность?</h2>
<p>В <strong>PySpark</strong> партиционирование данных является ключевой возможностью, которая помогает равномерно распределять нагрузку между узлами кластера. Партиционирование означает разделение данных на более мелкие части, называемые партициями, которые обрабатываются независимо и параллельно на разных узлах кластера.</p>
<p>Это повышает производительность за счёт параллельной обработки, уменьшения перемещения данных и более эффективного использования ресурсов. Управлять партиционированием можно с помощью таких методов, как <code>.repartition()</code> и <code>.coalesce()</code>.</p>
<h2>Объясни концепцию широковещательных переменных в PySpark и приведи пример использования</h2>
<p><strong>Широковещательные переменные</strong> являются важной возможностью распределённых вычислительных фреймворков Spark.</p>
<p>В PySpark это разделяемые переменные только для чтения, которые кэшируются и распространяются по узлам кластера для того, чтобы избежать операций <strong>shuffle</strong>. Они могут быть особенно полезны в распределённых приложениях машинного обучения, которым необходимо использовать и загружать предварительно обученную модель. В этом случае модель передаётся как широковещательная переменная, что помогает сократить накладные расходы на передачу данных и повысить производительность.</p>
<h2>В чём различия между PySpark и pandas?</h2>
<p><strong>PySpark</strong> и <strong>pandas</strong> оба широко используются для обработки данных, однако между ними существуют ключевые различия. <strong>PySpark</strong> ориентирован на масштабируемость и предназначен для работы с большими данными и распределённой обработки, тогда как <strong>pandas</strong> подходит для относительно небольших наборов данных, которые помещаются в память.</p>
<p>С точки зрения производительности PySpark выполняет параллельные вычисления на уровне кластера, что делает его значительно быстрее при работе с большими объёмами данных по сравнению с pandas, который работает на одной машине. С точки зрения удобства использования pandas проще для разведочного анализа данных, тогда как PySpark более сложен, но при этом сильно оптимизирован для распределённых вычислений.</p>
<h2>Как можно преобразовать DataFrame из pandas в PySpark DataFrame и обратно?</h2>
<p><strong>DataFrame pandas</strong> можно преобразовать в <strong>PySpark DataFrame</strong> с помощью метода <code>spark.createDataFrame()</code>, а <strong>PySpark</strong> <strong>DataFrame</strong> обратно в <strong>pandas DataFrame</strong> с помощью метода <code>.toPandas()</code>.</p><pre class="urvanov-syntax-highlighter-plain-tag">import pandas as pd
from pyspark.sql import SparkSession

# Инициализация SparkSession
spark = SparkSession.builder.appName("Example").getOrCreate()

# Создание Pandas DataFrame
pdf = pd.DataFrame({'id': [1, 2, 3], 'value': [10, 20, 30]})

# Преобразование в PySpark DataFrame
df_spark = spark.createDataFrame(pdf)

# Обратное преобразование в Pandas DataFrame
pdf_new = df_spark.toPandas()</pre><p></p>
<h1>Intermediate PySpark Interview Questions</h1>
<p>Рассмотрев основы, перейдём к вопросам для собеседования по PySpark среднего уровня, которые глубже затрагивают архитектуру и модель выполнения приложений Spark.</p>
<h2>Что такое Spark Driver и каковы его обязанности?</h2>
<p><strong>Spark Driver</strong> — это основной процесс, который координирует выполнение приложений Spark, распределяя задачи по кластеру. Он взаимодействует с менеджером кластера для выделения ресурсов, планирования задач и мониторинга выполнения Spark-задач (Tasks).</p>
<h2>Что такое Spark DAG?</h2>
<p><strong>Ориентированный ациклический граф (DAG)</strong> в Spark является ключевым понятием, поскольку он представляет <strong>логическую модель выполнения Spark</strong>. Он называется ориентированным, потому что каждая вершина представляет преобразование, выполняемое в определённом порядке, заданном рёбрами. Он является ациклическим, так как в плане выполнения отсутствуют циклы или петли. Этот план оптимизируется с использованием конвейерных преобразований, объединения задач и проталкивания предикатов.</p>
<h2>Какие типы менеджеров кластеров доступны в Spark?</h2>
<p>В настоящее время Spark поддерживает несколько менеджеров кластеров для управления ресурсами и планирования заданий.</p>
<ul>
<li>К ним относится <strong>Standalone</strong> — простой менеджер кластера, встроенный в Spark.</li>
<li><strong>Hadoop YARN</strong> — универсальный менеджер в экосистеме Hadoop, используемый для планирования заданий и управления ресурсами.</li>
<li><strong>Kubernetes</strong> применяется для автоматизации, развёртывания, масштабирования и управления контейнеризованными приложениями.</li>
<li><strong>Apache Mesos</strong> — распределённая система, используемая для управления ресурсами на уровне приложений.</li>
</ul>
<h2>Опиши, как реализовать пользовательское преобразование в PySpark</h2>
<p>Для реализации пользовательского преобразования в <strong>PySpark</strong> можно определить Python-функцию, которая работает с PySpark <strong>DataFrame</strong>, а затем использовать метод <code>.transform()</code> для вызова этого преобразования. Ниже приведён пример реализации пользовательского преобразования в PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag"># Определение Python-функции, работающей с PySpark DataFrame
def get_discounted_price(df):
    return df.withColumn("discounted_price", \
                          df.price - (df.price * df.discount) / 100) 

# Вызов преобразования
df_discounted = df_from_csv.transfrom(get_discounted_price)</pre><p></p>
<h2>Объясни концепцию оконных функций в PySpark и приведи пример</h2>
<p>Оконные функции в <strong>PySpark</strong> позволяют применять операции к окну строк, возвращая одно значение для каждой входной строки. С их помощью можно выполнять ранжирование, аналитические операции и агрегатные функции. Ниже приведён пример применения оконной функции в <strong>PySpark</strong>:</p><pre class="urvanov-syntax-highlighter-plain-tag">from pyspark.sql.window import Window
from pyspark.sql.functions import row_number

# Определение оконной функции
window = Window.orderBy("discounted_price")

# Применение оконной функции
df = df_from_csv.withColumn("row_number", row_number().over(window))</pre><p></p>
<h2>Как обрабатывать ошибки и исключения в PySpark?</h2>
<p>Одним из наиболее полезных способов обработки ошибок и исключений в преобразованиях и действиях PySpark является оборачивание кода в блоки try-except для их перехвата. В RDD можно использовать операцию <code>foreach</code> для итерации по элементам и обработки исключений.</p>
<h2>Каково назначение чекпойнтов в PySpark?</h2>
<p>В <strong>PySpark</strong> чекпойнтинг означает сохранение <strong>RDD</strong> на диск, чтобы к этой промежуточной точке можно было обратиться в будущем вместо повторного вычисления RDD из исходного источника. Чекпойнты обеспечивают возможность восстановления после сбоев, поскольку драйвер может быть перезапущен с использованием ранее вычисленного состояния.</p>
<h2>Как PySpark выполняет вывод схемы и как можно задать схему явно?</h2>
<p><strong>PySpark</strong> автоматически выводит схему при загрузке структурированных данных, однако для лучшего контроля и повышения эффективности можно явно определить схему с помощью <strong>StructType</strong> и <strong>StructField</strong>.</p><pre class="urvanov-syntax-highlighter-plain-tag">from pyspark.sql.types import StructType, StructField, IntegerType, StringType

schema = StructType([
    StructField("id", IntegerType(), True),
    StructField("name", StringType(), True)
])

df = spark.read.csv("data.csv", schema=schema, header=True)</pre><p></p>
<h1>Advanced PySpark Interview Questions</h1>
<p>Для тех, кто претендует на более старшие позиции или стремится продемонстрировать более глубокое понимание <strong>PySpark</strong>, далее рассматриваются продвинутые вопросы для собеседования, которые углубляются в тонкости преобразований и оптимизаций внутри экосистемы <strong>PySpark</strong>.</p>
<h2>Объясни различия между узкими и широкими преобразованиями в PySpark</h2>
<p>В <strong>PySpark</strong> узкие преобразования выполняются тогда, когда каждый входной партиции соответствует не более одной выходной партиции и при этом не требуется выполнение <strong>shuffle</strong>. К таким преобразованиям относятся, например, <code>map()</code>, <code>filter()</code> и <code>union()</code>. В противоположность этому, широкие преобразования необходимы для операций, при которых каждая входная партиция может вносить вклад в несколько выходных партиций, и при этом требуется перераспределение данных, выполнение соединений или агрегаций. Примерами таких преобразований являются <code>groupBy()</code>, <code>join()</code> и <code>sortBy()</code>.</p>
<h2>Что такое оптимизатор Catalyst в Spark и как он работает?</h2>
<p>В Spark оптимизатор <strong>Catalyst</strong> является компонентом <strong>Spark SQL</strong>, основанным на правилах и предназначенным для оптимизации производительности запросов. Его основная задача заключается в преобразовании и улучшении SQL-запросов или операций <strong>DataFrame</strong>, заданных пользователем, с целью генерации эффективного физического плана выполнения, адаптированного под конкретный запрос и характеристики набора данных.</p>
<h2>Опиши, как реализовать пользовательские агрегации в PySpark</h2>
<p>Для реализации пользовательских агрегаций в <strong>PySpark</strong> можно совместно использовать методы <code>groupBy()</code> и <code>agg()</code>. Внутри вызова <code>agg()</code> можно передавать различные функции из модуля <code>pyspark.sql.functions</code>. Кроме того, можно применять пользовательские агрегации <strong>Pandas</strong> к группам внутри <strong>PySpark</strong> <strong>DataFrame</strong> с помощью метода <code>.applyInPandas()</code>. Ниже приведён пример реализации пользовательских агрегаций в <strong>PySpark</strong>:</p><pre class="urvanov-syntax-highlighter-plain-tag"># Использование groupBy и agg с функциями
from pyspark.sql import functions as F
df_from_csv.groupBy("house_id").agg(F.mean("price_discounted"))

# Использование applyInPandas
def normalize_price(df):
    disc_price = df["discounted_price"]
    df["normalized_price"] = disc_price.mean() / disc_price.std()

df_from_csv.groupBy("house_id").applyInPandas(normalize_price)</pre><p></p>
<h2>С какими трудностями ты сталкивался при работе с большими наборами данных в PySpark и как ты их преодолевал?</h2>
<p>С помощью этого вопроса можно обратиться к собственному опыту и рассказать о конкретном случае, в котором возникали сложности при работе с <strong>PySpark</strong> и большими наборами данных, которые могут включать следующее:</p>
<ul>
<li>Управление памятью и использование ресурсов.</li>
<li>Перекос данных и неравномерное распределение нагрузки.</li>
<li>Оптимизация производительности, особенно для широких преобразований и операций shuffle.</li>
<li>Отладка и устранение неисправностей сложных сбоев заданий.</li>
<li>Эффективное партиционирование и хранение данных.</li>
</ul>
<p>Для преодоления этих проблем <strong>PySpark</strong> предоставляет возможности партиционирования наборов данных, кэширования промежуточных результатов, использования встроенных техник оптимизации, надёжного управления кластером и применения механизмов отказоустойчивости.</p>
<h2>Как интегрировать PySpark с другими инструментами и технологиями в экосистеме больших данных?</h2>
<p>PySpark обладает тесной интеграцией с различными инструментами для работы с большими данными, включая <strong>Hadoop</strong>, <strong>Hive</strong>, <strong>Kafka</strong> и <strong>HBase</strong>, а также с облачными хранилищами, такими как <strong>AWS S3</strong> и <strong>Google Cloud Storage</strong>.</p>
<p>Такая интеграция осуществляется с использованием встроенных коннекторов, библиотек и API, предоставляемых PySpark.</p>
<h2>Какие лучшие практики существуют для тестирования и отладки приложений PySpark?</h2>
<p>К числу рекомендуемых лучших практик для тестирования и отладки приложений <strong>PySpark</strong> относятся написание модульных тестов с использованием <code>pyspark.sql.test.SQLTestUtils</code> совместно с <strong>Python-библиотеками</strong>, такими как <code>pytest</code>, отладка приложений и логирование сообщений с помощью библиотеки <code>logging</code>, а также <strong>Spark UI</strong>, и оптимизация производительности с использованием API Spark <code>org.apache.spark.metrics</code> и инструментов мониторинга производительности.</p>
<h2>Как бы ты решал вопросы безопасности и конфиденциальности данных в среде PySpark?</h2>
<p>В настоящее время обмен данными стал значительно проще, поэтому защита чувствительной и конфиденциальной информации является важным способом предотвращения утечек данных. Одной из лучших практик является применение шифрования данных во время обработки и хранения. В <strong>PySpark</strong> этого можно добиться, используя функции <code>aes_encrypt()</code> и <code>aes_decrypt()</code> для столбцов <strong>DataFrame</strong>. Также для достижения этой цели можно использовать сторонние библиотеки, такие как библиотека <code>cryptography</code>.</p>
<h2>Опиши, как использовать PySpark для построения и развёртывания модели машинного обучения</h2>
<p><strong>PySpark</strong> предоставляет библиотеку <strong>MLlib</strong> — масштабируемую библиотеку машинного обучения для построения и развёртывания моделей машинного обучения на больших наборах данных. API этой библиотеки может использоваться на различных этапах ML-процесса, таких как предварительная обработка данных, инженерия признаков, обучение модели, оценка качества и развёртывание. Используя кластеры <strong>Spark</strong>, можно развёртывать модели машинного обучения на базе <strong>PySpark</strong> в промышленной среде, применяя <strong>пакетный</strong> или <strong>потоковый инференс</strong>.</p>
<h2>Как можно оптимизировать операции shuffle в PySpark?</h2>
<p><strong>Операции <code>shuffle</code></strong> возникают, когда данные перераспределяются между партициями, и они могут быть затратными с точки зрения производительности. Для оптимизации <code>shuffle</code> можно применять следующие подходы:</p>
<ul>
<li>Стратегически использовать <code>repartition()</code> для балансировки партиций перед затратными операциями, такими как <code>join</code>.</li>
<li>Отдавать предпочтение <code>coalesce()</code> вместо <code>repartition()</code> при уменьшении количества партиций, поскольку это минимизирует перемещение данных.</li>
<li>Выполнять широковещательные соединения небольших таблиц с помощью <code>broadcast()</code> перед соединением с большими таблицами, чтобы избежать операций, интенсивно использующих <code>shuffle</code>.</li>
<li>Настраивать конфигурации <strong>Spark</strong>, такие как <code>spark.sql.shuffle.partitions</code>, для оптимизации количества партиций при <strong>shuffle-операциях</strong>.</li>
</ul>
<h1>Вопросы для собеседования по PySpark для Data Engineer</h1>
<p>Если вы проходите собеседование на позицию инженера данных, ожидайте вопросы, которые оценивают вашу способность проектировать, оптимизировать и устранять проблемы в приложениях <strong>PySpark</strong> в промышленной среде.</p>
<p>Ниже приведены типичные вопросы, с которыми можно столкнуться.</p>
<h2>Опиши, как бы ты оптимизировал задание PySpark, которое работает медленно. На какие ключевые факторы ты бы обратил внимание?</h2>
<p>Если задание PySpark работает медленно, существует несколько аспектов, которые можно улучшить для оптимизации его производительности:</p>
<ul>
<li>Обеспечение корректного размера и количества партиций данных для минимизации перераспределения данных во время преобразований.</li>
<li>Использование <strong>DataFrame</strong> вместо <strong>RDD</strong>, поскольку они уже используют несколько модулей оптимизации для повышения производительности рабочих нагрузок <strong>Spark</strong>.</li>
<li>Использование <strong>широковещательных соединений</strong> и <strong>широковещательных переменных</strong> при соединении небольшого набора данных с большим набором данных.</li>
<li>Кэширование и сохранение промежуточных <strong>DataFrame</strong>, которые используются повторно.</li>
<li>Настройка количества партиций, ядер исполнителей и числа экземпляров для эффективного использования ресурсов кластера.</li>
</ul>
<p>Выбор подходящих форматов файлов для уменьшения объёма данных.</p>
<h2>Как обеспечить отказоустойчивость в приложениях PySpark?</h2>
<p>Для обеспечения отказоустойчивости в приложениях PySpark можно использовать несколько стратегий:</p>
<ul>
<li>Использование чекпойнтинга для сохранения данных в определённых точках.</li>
<li>Репликация данных путём их сохранения на разных машинах.</li>
<li>Ведение журнала изменений, выполняемых над данными до их применения.</li>
<li>Выполнение проверок валидации данных для выявления ошибок.</li>
<li>Выбор корректного уровня сохранения данных.</li>
</ul>
<p>Использование встроенных механизмов отказоустойчивости Spark для автоматического повторного выполнения задач, которые завершились с ошибкой.</p>
<h2>Какие существуют способы развертывания и управления приложениями PySpark?</h2>
<p>Мы можем развертывать и управлять приложениями PySpark с помощью следующих инструментов:</p>
<ul>
<li><strong>YARN:</strong> менеджер ресурсов, который помогает развертывать и управлять приложениями в Hadoop-кластерах.</li>
<li><strong>Kubernetes:</strong> Spark предоставляет поддержку для развертывания приложений в кластерах Kubernetes.</li>
<li><strong>Databricks:</strong> предоставляет полностью управляемую платформу для приложений PySpark, абстрагируя сложность управления кластерами.</li>
</ul>
<h2>Как вы бы мониторили и устраняли проблемы в заданиях PySpark, работающих в production-среде?</h2>
<p><strong>PySpark</strong> предоставляет следующие инструменты для мониторинга и устранения проблем заданий, работающих в <strong>production-среде</strong>:</p>
<ul>
<li><strong>Spark UI:</strong> веб-интерфейс, который помогает отслеживать прогресс выполнения заданий, использование ресурсов и выполнение задач.</li>
<li><strong>Логирование:</strong> мы можем настроить логирование для сбора детальной информации об ошибках и предупреждениях.</li>
<li><strong>Метрики:</strong> мы можем использовать системы мониторинга для сбора и анализа метрик, связанных с состоянием кластера и производительностью заданий.</li>
</ul>
<h2>Объясните разницу между динамическим и статическим распределением ресурсов в Spark и в каких случаях вы бы выбрали каждый из них</h2>
<p>В <strong>Spark</strong> статическое распределение ресурсов означает предварительное и постоянное выделение фиксированных ресурсов, таких как память и количество ядер <strong>executors</strong>, на всё время выполнения приложения. В отличие от этого, динамическое распределение ресурсов позволяет Spark динамически изменять количество <strong>executors</strong> в зависимости от нагрузки. Ресурсы могут добавляться или удаляться по мере необходимости, что улучшает использование ресурсов и снижает затраты.</p>
<h2>Как вы принимаете решение между использованием DataFrames и RDD в PySpark?</h2>
<p>Выбор между <strong>DataFrames</strong> и <strong>RDD</strong> зависит от структуры данных и типа операций, которые необходимо выполнять.</p>
<p>Используйте <strong>DataFrames</strong>, когда:</p>
<ul>
<li>требуется обработка структурированных данных со схемой;</li>
<li>нужна оптимизированная обработка с использованием Catalyst и Tungsten;</li>
<li>используются SQL-запросы и встроенные трансформации.</li>
</ul>
<p>Используйте <strong>RDD</strong>, когда:</p>
<ul>
<li>нужны низкоуровневые трансформации и более детальный контроль над вычислениями;</li>
<li>вы работаете с неструктурированными или полуструктурированными данными;</li>
<li>требуется большая гибкость в определении трансформаций.</li>
</ul>
<h2>Как бы вы реализовали инкрементальную обработку данных в PySpark?</h2>
<p><strong>Инкрементальная обработка</strong> необходима для эффективной работы с постоянно растущими наборами данных. Она может быть реализована с помощью:</p>
<ul>
<li><strong>Использования Delta Lake:</strong> хранение обновлений в формате Delta позволяет эффективно обрабатывать инкрементальные изменения.</li>
<li><strong>Использования watermarking в structured streaming:</strong> помогает отбрасывать устаревшие данные, сохраняя при этом агрегаты с состоянием.</li>
<li><strong>Партиционирования и фильтрации:</strong> загрузка только новых или изменённых данных вместо переработки всего объёма.</li>
<li><strong>Использования checkpointing:</strong> сохранение промежуточных результатов для предотвращения переработки с нуля в случае сбоя.</li>
</ul>
<p>Сообщение <a href="https://datatalks.ru/pyspark-interview-questions-and-answers/">PySpark Interview &#8212; Вопросы и ответы</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datatalks.ru/pyspark-interview-questions-and-answers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Apache Spark Quick Start &#8212; Как начать работать с PySpark</title>
		<link>https://datatalks.ru/apache-spark-quick-start/</link>
					<comments>https://datatalks.ru/apache-spark-quick-start/#respond</comments>
		
		<dc:creator><![CDATA[Data Engineer (Admin)]]></dc:creator>
		<pubDate>Sat, 11 Jan 2025 20:26:29 +0000</pubDate>
				<category><![CDATA[Apache Spark]]></category>
		<category><![CDATA[Apache Spark Docker]]></category>
		<category><![CDATA[Apache Spark Jupyter Notebook]]></category>
		<category><![CDATA[Bucketing]]></category>
		<category><![CDATA[Catalyst]]></category>
		<category><![CDATA[docker]]></category>
		<category><![CDATA[how to install spark]]></category>
		<category><![CDATA[JAVA]]></category>
		<category><![CDATA[JVM]]></category>
		<category><![CDATA[Partitioning]]></category>
		<category><![CDATA[Py4J]]></category>
		<category><![CDATA[pyspark]]></category>
		<category><![CDATA[Pyspark Jupyter Notebook]]></category>
		<category><![CDATA[pyspark notebook]]></category>
		<category><![CDATA[pyspark пример]]></category>
		<category><![CDATA[RDD]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[Spark Session]]></category>
		<guid isPermaLink="false">https://datatalks.ru/?p=636</guid>

					<description><![CDATA[<p>СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ Что посмотреть на русском по Spark? Однозначно плейлист &#171;DataLearn: DE-101 &#124; Модуль 7&#187;. Здесь вы получите базовое понимание инструмента. Краткое описание терминов Spark Application (Приложение) &#8212; Пользовательская программа, созданная на Spark. [&#8230;]</p>
<p>Сообщение <a href="https://datatalks.ru/apache-spark-quick-start/">Apache Spark Quick Start &#8212; Как начать работать с PySpark</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<p><span style="color: #ff6600;">СТАТЬЯ В ПРОЦЕССЕ НАПИСАНИЯ</span></p>
<h1>Что посмотреть на русском по Spark?</h1>
<p>Однозначно плейлист <a href="https://www.youtube.com/playlist?list=PLkcP_moW_BpMuwnpqNlE_wuLy-FI8vaJd" target="_blank" rel="noopener">&#171;DataLearn: DE-101 | Модуль 7&#187;</a>. Здесь вы получите базовое понимание инструмента.</p>
<h1>Краткое описание терминов Spark</h1>
<ul>
<li><strong>Application (Приложение)</strong> &#8212; Пользовательская программа, созданная на Spark. Состоит из программы-драйвера и исполнителей на кластере.</li>
<li><strong>Application JAR</strong> &#8212; JAR-файл, содержащий приложение Spark пользователя. В некоторых случаях пользователи могут захотеть создать &#171;uber JAR&#187;, который будет содержать их приложение вместе с его зависимостями. Однако, пользовательский JAR не должен включать библиотеки Hadoop или Spark, так как они будут добавлены во время выполнения.</li>
<li><strong>Cluster manager &#8212; </strong>Внешний сервис для получения ресурсов в кластере.<br />
<strong>Типы Cluster Manager:</strong></p>
<ul>
<li><strong>Standalone (автономный менеджер)</strong> – простой менеджер кластеров, входящий в состав Spark, который упрощает настройку кластера.</li>
<li><span style="color: #ff0000;"><strong>Apache Mesos (Deprecated)</strong></span> &#8212; общий менеджер кластера, который также может запускать Hadoop MapReduce и сервисные приложения.</li>
<li><strong>Hadoop YARN</strong> – менеджер ресурсов в Hadoop 3.</li>
<li><strong>Kubernetes</strong> – система с открытым исходным кодом для автоматизации развертывания, масштабирования и управления контейнеризированными приложениями.</li>
</ul>
</li>
<li><strong>Deploy mode (Режим развертывания)</strong> &#8212; Определяет, где запускается и работает процесс драйвера:
<ul>
<li><strong>В режиме кластера (cluster mode)</strong> фреймворк запускает драйвер внутри кластера.</li>
<li><strong>В режиме клиента (client mode)</strong> ведомый (подчиненный) запускает драйвер за пределами кластера.</li>
<li>Можно определить, в каком режиме вы находитесь, выполнив метод <code>deployMode()</code>. Метод возвращает свойство, защищенное от изменения (только для чтения).</li>
</ul>
</li>
<li><strong>Driver program (Программа-драйвер)</strong> &#8212; Процесс, выполняющий основную функцию <code>main()</code> приложения и создающий контекст SparkContext. Все начинается именно здесь. Это процесс JVM, который управляет приложением Spark, обрабатывая вводимые пользователем данные и распределяя работу между исполнителями.</li>
<li><strong>Executor (Исполнитель)</strong> &#8212; Процесс, запускаемый для приложения на рабочем узле. Исполнитель выполняет задачи и сохраняет промежуточные данные в памяти или на диске. У каждого приложения имеются собственные исполнители.</li>
<li><strong>Job (Задание)</strong> &#8212; Параллельное вычисление (выполнение), состоящее из нескольких задач, которые порождаются в ответ на некоторое действие Spark (например, <code>save()</code> или <code>collect()</code>). В Spark job представляет собой ряд преобразований, применяемых к данным. Он охватывает весь рабочий процесс от начала до конца. Одно приложение Spark может иметь более одного job Spark.</li>
<li><strong>Stage (Этап)</strong> &#8212; Stage — это сегмент задания, выполняемый без data shuffling (перетасовки данных). Spark разбивает job (задание) на разные этапы, когда преобразование требует перетасовки данных между разделами.</li>
<li><strong>Task (Задача)</strong> &#8212; Минимальная единица работы, которая передается одному исполнителю. Каждый этап делится на несколько задач, которые выполняют обработку параллельно в разных data partitions (разделах данных).</li>
<li><strong>Worker node (Рабочий узел)</strong> &#8212; Любой узел, который может выполнять код приложения в кластере.</li>
<li><strong>RDD</strong> &#8212; это первичная абстракция данных. Используются ли DataFrames или Datasets, они компилируются в RDD за кулисами. Он представляет собой неизменяемую, секционированную коллекцию записей, с которой можно работать параллельно. Данные внутри RDD хранятся в памяти как можно дольше и как можно больше.</li>
</ul>
<hr />
<p><strong>Схема Spark с компонентами:</strong></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components.jpeg"><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-787" src="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components.jpeg" alt="" width="1039" height="800" srcset="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components.jpeg 1039w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components-300x231.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components-1024x788.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components-768x591.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components-450x346.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_components-780x601.jpeg 780w" sizes="(max-width: 1039px) 100vw, 1039px" /></a></p>
<h1>Основы архитектуры Apache Spark</h1>
<p>Архитектура Apache Spark используется не только для обработки в реальном времени, но и для пакетной обработки, и она может обеспечить производительность в сто раз выше, чем традиционный метод map-reduce, реализованный в Hadoop.</p>
<p><strong>Архитектура Spark или Apache Spark</strong> — это фреймворк параллельной обработки, поддерживающий обработку в памяти для повышения производительности аналитических приложений больших данных и ядро Apache Spark, ресурсы которого управляются YARN. Проще говоря, архитектура Spark известна своей скоростью и эффективностью.</p>
<p><strong>Вот ее основные особенности:</strong></p>
<ul>
<li>Он обрабатывает данные быстрее, что экономит время при операциях чтения и записи.</li>
<li>Он обеспечивает потоковую передачу данных в режиме реального времени, что делает его действительно востребованной технологией в современном мире больших данных.</li>
</ul>
<p><strong><span style="color: #ff6600;">ПРИМЕЧАНИЕ: </span>YARN</strong> — это своего рода менеджер ресурсов, который в основном используется для управления ресурсами вашей архитектуры Spark.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components.png"><img decoding="async" class="aligncenter size-full wp-image-789" src="https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components.png" alt="" width="881" height="592" srcset="https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components.png 881w, https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components-300x202.png 300w, https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components-768x516.png 768w, https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components-370x250.png 370w, https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components-450x302.png 450w, https://datatalks.ru/wp-content/uploads/2025/01/apache_core_components-780x524.png 780w" sizes="(max-width: 881px) 100vw, 881px" /></a></p>
<p>Архитектура Spark основана на двух важных абстракциях: <strong>устойчивом распределенном наборе данных (RDD)</strong> и <strong>направленном ациклическом графе (DAG)</strong>.</p>
<h2>Понимание операций DAG в Spark</h2>
<p>Общая иерархия приложения Spark представлена на картинке:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_app_job_stage_task_executor.jpeg"><img decoding="async" class="aligncenter size-full wp-image-885" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_app_job_stage_task_executor.jpeg" alt="" width="604" height="391" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_app_job_stage_task_executor.jpeg 604w, https://datatalks.ru/wp-content/uploads/2025/01/spark_app_job_stage_task_executor-300x194.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_app_job_stage_task_executor-450x291.jpeg 450w" sizes="(max-width: 604px) 100vw, 604px" /></a></p>
<p><em>В этом разделе будет описано, как код Spark разбивается на Job и Stage Tasks через DAG.</em></p>
<hr />
<p><strong>DAG (Directed Acyclic Graph)</strong> &#8212; это направленный ациклический граф, другими словами это набор вершин и ребер. Вершины представляют <strong>RDD</strong>, а ребра представляют операцию, которая должна быть применена к RDD. В Spark DAG каждое ребро направляется от более раннего к более позднему в последовательности. При вызове Action созданный DAG отправляется в <strong>DAG Scheduler</strong>, который далее разбивает граф на этапы задачи.</p>
<p><strong>DAGScheduler</strong> — это уровень планирования Apache Spark, который реализует поэтапное планирование с использованием <strong>Jobs (заданий)</strong> и <strong>Stages (стадий)</strong>.</p>
<p><strong>DAGScheduler</strong> преобразует <strong>логический план выполнения</strong> (RDD lineage of dependencies built using RDD transformations) в <strong>физический план выполнения</strong> (с использованием Stages).</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_dag_schedule_job_stages_how_it_works.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-878" src="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_dag_schedule_job_stages_how_it_works.jpeg" alt="" width="420" height="520" srcset="https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_dag_schedule_job_stages_how_it_works.jpeg 420w, https://datatalks.ru/wp-content/uploads/2025/01/apache_spark_dag_schedule_job_stages_how_it_works-242x300.jpeg 242w" sizes="(max-width: 420px) 100vw, 420px" /></a></p>
<p>После вызова действия RDD в SparkContext передает логический план DAGScheduler, который он в свою очередь преобразует в набор Stages (этапов), отправляемых в виде TaskSets для выполнения.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/dagscheduler_rdd_partitions_job_resultstage.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-881" src="https://datatalks.ru/wp-content/uploads/2025/01/dagscheduler_rdd_partitions_job_resultstage.jpeg" alt="" width="653" height="409" srcset="https://datatalks.ru/wp-content/uploads/2025/01/dagscheduler_rdd_partitions_job_resultstage.jpeg 653w, https://datatalks.ru/wp-content/uploads/2025/01/dagscheduler_rdd_partitions_job_resultstage-300x188.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/dagscheduler_rdd_partitions_job_resultstage-450x282.jpeg 450w" sizes="(max-width: 653px) 100vw, 653px" /></a></p>
<p><strong>PySpark DAG Visualization:</strong></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-882" src="https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization.png" alt="" width="771" height="1257" srcset="https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization.png 771w, https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization-184x300.png 184w, https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization-628x1024.png 628w, https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization-768x1252.png 768w, https://datatalks.ru/wp-content/uploads/2025/01/pyspark_dag_visualization-450x734.png 450w" sizes="(max-width: 771px) 100vw, 771px" /></a></p>
<p><strong>Как это работает в Spark?</strong></p>
<ul>
<li><strong>Sequence of Computations (Последовательность вычислений):</strong> в Spark, когда вы выполняете действия или преобразования с данными, они изначально представлены как ряд операций. Вместо того, чтобы выполнять каждую операцию немедленно, Spark создает DAG этих операций.</li>
<li><strong>Lazy Evaluation (Ленивая оценка):</strong> этот DAG формирует план выполнения, который оценивается и оптимизируется до фактического вычисления. Ленивая оценка Spark означает, что преобразования не вычисляются сразу, а накапливаются до тех пор, пока не будет вызвано действие. Это позволяет Spark оптимизировать план выполнения, например, путем комбинирования преобразований.</li>
<li><strong>Fault Tolerance (Отказоустойчивость):</strong> структура DAG способствует отказоустойчивости. Если узел выходит из строя во время вычислений, Spark может пересчитать только раздел потерянных данных, используя отношения, представленные DAG, вместо того, чтобы переделывать всю операцию.</li>
<li><strong>Optimized Execution (Оптимизированное выполнение):</strong> DAG позволяет Spark эффективно перестраивать вычислительные задачи. Зная зависимости и преобразования, Spark может выполнять этапы параллельно, оптимизировать распределение ресурсов и выполнять конвейеризацию операций.</li>
<li><strong>Task Scheduling (Планирование задач):</strong> После того, как DAG создан и оптимизирован, Spark делит его на набор этапов с наборами задач, которые запланированы для выполнения. Каждый этап в DAG может выполняться параллельно через доступные исполнители.</li>
</ul>
<p>По сути, DAG гарантирует, что Выполнение задач Spark выполняется эффективно, с оптимизацией скорости и управлением ресурсами, интегрированными на каждом этапе. Это ключевой механизм, который лежит в основе надежной производительностиApache Spark в задачах обработки данных.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-793" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process.jpg" alt="" width="800" height="600" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process.jpg 800w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-300x225.jpg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-768x576.jpg 768w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-280x210.jpg 280w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-560x420.jpg 560w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-450x338.jpg 450w, https://datatalks.ru/wp-content/uploads/2025/01/spark_job_scheduling_process-780x585.jpg 780w" sizes="(max-width: 800px) 100vw, 800px" /></a></p>
<p>Еще одна иллюстрация как работает DAG (<a href="https://data-flair.training/blogs/dag-in-apache-spark/" target="_blank" rel="noopener">источник</a>):</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-893 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd.jpeg" alt="" width="1152" height="824" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd.jpeg 1152w, https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd-300x215.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd-1024x732.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd-768x549.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd-450x322.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/spark_driver_dag_stages_jobs_rdd-780x558.jpeg 780w" sizes="(max-width: 1152px) 100vw, 1152px" /></a></p>
<h2>Понимание компонентов RDD: Resilient, Distributed, Dataset</h2>
<p><strong>RDD (Resilient Distributed Dataset)</strong> &#8212; является фундаментальной концепцией в Apache Spark, которая обозначает три основных атрибута.</p>
<p>Давайте разберемся, что означает каждый термин:</p>
<ul>
<li><span style="color: #ff6600;"><strong>Resilient (Устойчивый)</strong></span>
<ul>
<li><strong>Отказоустойчивость:</strong> RDD разработаны для автоматического восстановления после ошибок или сбоев. Если узел в кластере выходит из строя, потерянные данные могут быть пересчитаны из его родословной, что гарантирует целостность данных.</li>
<li><strong>Эффективное восстановление:</strong> с помощью процесса, известного как родословная, RDD могут повторно вычислять только утраченную часть данных, что делает восстановление эффективным без существенного нарушения процессов.</li>
</ul>
</li>
<li><strong><span style="color: #ff6600;">Distributed (Распределенный)</span></strong>
<ul>
<li><strong>Масштабируемость по узлам:</strong> данные распределяются по различным узлам в кластере, что позволяет выполнять параллельную обработку. Такое распределение повышает как скорость, так и эффективность, поскольку задачи могут использовать несколько машин.</li>
<li><strong>Балансировка нагрузки:</strong> рабочие нагрузки равномерно распределяются по узлам, что позволяет избежать возникновения узких мест, обеспечивая оптимальное использование ресурсов и повышение производительности.</li>
</ul>
</li>
<li><strong><span style="color: #ff6600;">Dataset (Набор данных)</span></strong>
<ul>
<li><strong>Логическая группировка данных:</strong> RDD представляют собой набор данных в логической структуре, позволяя пользователям манипулировать большими объемами данных с помощью единого унифицированного интерфейса.</li>
<li><strong>Преобразования и действия:</strong> с помощью RDD можно выполнять различные преобразования (например, сопоставление и фильтрация) и действия (например, подсчет и сбор) для беспрепятственного манипулирования и анализа данных.</li>
</ul>
</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/rdd_properties_spark.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1050" src="https://datatalks.ru/wp-content/uploads/2025/01/rdd_properties_spark.jpeg" alt="" width="667" height="486" srcset="https://datatalks.ru/wp-content/uploads/2025/01/rdd_properties_spark.jpeg 667w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_properties_spark-300x219.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_properties_spark-450x328.jpeg 450w" sizes="(max-width: 667px) 100vw, 667px" /></a></p>
<p><strong>Внутри каждый RDD в Spark имеет пять ключевых свойств:</strong></p>
<ul>
<li><strong>List of Partitions (Список разделов):</strong> RDD разделен на разделы, которые являются единицами параллелизма в Spark.</li>
<li><strong>Computation Function (Функция вычисления):</strong> Функция определяет, как вычислять данные для каждого раздела.</li>
<li><strong>Dependencies (Зависимости):</strong> RDD отслеживает свои зависимости от других RDD, которые описывают, как он был создан.</li>
<li><strong>Partitioner &#8212; Разделитель (необязательно):</strong> для RDD «ключ-значение» разделитель определяет, как разделяются данные, например, с помощью хэш-разделителя.</li>
<li><strong>Preferred Locations &#8212; Предпочтительные расположения (необязательно):</strong> в этом свойстве перечислены предпочтительные расположения для вычисления каждого раздела, например расположения блоков данных в HDFS.</li>
</ul>
<p><strong>Lazy Evaluation (Ленивая оценка)</strong></p>
<p>Когда вы определяете RDD, его внутренние данные не доступны или не преобразуются немедленно, пока действие не запустит выполнение. Такой подход позволяет Spark определить наиболее эффективный способ выполнения преобразований.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1051" src="https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action.jpeg" alt="" width="776" height="363" srcset="https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action.jpeg 776w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action-300x140.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action-768x359.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_transformation_action-450x211.jpeg 450w" sizes="(max-width: 776px) 100vw, 776px" /></a></p>
<p><strong>RDD в Apache Spark поддерживает два типа операций:</strong></p>
<ul>
<li><strong>Трансформации</strong> &#8212; это функции, которые принимают существующие RDD в качестве входных данных и выводят один или несколько RDD. Однако данные в существующем RDD в Spark не изменяются, поскольку они неизменяемы.</li>
<li><strong>Действия в Spark</strong> — это функции, которые возвращают конечный результат вычислений RDD. Он использует lineage graph для загрузки данных в RDD в определенном порядке. После того, как все преобразования выполнены, действия возвращают конечный результат в драйвер Spark.</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-902" src="https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action.jpeg" alt="" width="946" height="526" srcset="https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action.jpeg 946w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action-300x167.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action-768x427.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action-450x250.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_lineage_transformation_action-780x434.jpeg 780w" sizes="(max-width: 946px) 100vw, 946px" /></a></p>
<p><strong>Partitions (Разделы)</strong></p>
<p>При создании RDD Spark делит данные на несколько фрагментов, называемых разделами. Каждый раздел представляет собой логическое подмножество данных и может обрабатываться независимо с помощью разных исполнителей. Это позволяет Spark выполнять операции с большими наборами данных параллельно.</p>
<p><strong>RDD операции:</strong></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_rdd_operations.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-905" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_rdd_operations.jpeg" alt="" width="677" height="371" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_rdd_operations.jpeg 677w, https://datatalks.ru/wp-content/uploads/2025/01/spark_rdd_operations-300x164.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_rdd_operations-450x247.jpeg 450w" sizes="(max-width: 677px) 100vw, 677px" /></a></p>
<p><strong>Существуют narrow (узкие) и wide (широкие) преобразования.</strong></p>
<ul>
<li>В узком преобразовании все элементы данных, необходимые для вычисления записей в single partition (одном разделе), находятся в одном разделе родительского RDD.</li>
<li>В широком преобразовании все элементы данных, необходимые для вычисления записей в одном разделе, могут находиться во многих разделах родительского RDD, поэтому для завершения преобразования разделы необходимо перетасовать (shuffled).</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/Apache_Spark_101_Shuffling.gif" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-912 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/Apache_Spark_101_Shuffling.gif" alt="" width="1420" height="817" /></a></p>
<p>Narrow vs Wide Transformations:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-917" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation.jpeg" alt="" width="1189" height="768" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation.jpeg 1189w, https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation-300x194.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation-1024x661.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation-768x496.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation-450x291.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/spark_narrow_wide_transformation-780x504.jpeg 780w" sizes="(max-width: 1189px) 100vw, 1189px" /></a></p>
<p><strong>Two-stage Spark job:</strong></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/Example_of_a_simple_two_stage_Spark_job.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-908" src="https://datatalks.ru/wp-content/uploads/2025/01/Example_of_a_simple_two_stage_Spark_job.jpeg" alt="" width="660" height="321" srcset="https://datatalks.ru/wp-content/uploads/2025/01/Example_of_a_simple_two_stage_Spark_job.jpeg 660w, https://datatalks.ru/wp-content/uploads/2025/01/Example_of_a_simple_two_stage_Spark_job-300x146.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/Example_of_a_simple_two_stage_Spark_job-450x219.jpeg 450w" sizes="(max-width: 660px) 100vw, 660px" /></a></p>
<p><strong>DAGScheduler</strong> проходит по родословной RDD от конечного RDD (с действием) обратно к исходному RDD, создавая DAG этапов на основе границ перемешивания. Этапы формируются там, где существуют широкие зависимости (границы перемешивания). Каждый этап состоит из параллельных задач, которые могут выполняться на разных разделах. Этапы создаются как <strong>ResultStages</strong> (конечный этап) или <strong>ShuffleMapStages</strong> (промежуточные этапы, которые выполняют перемешивание).</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-920" src="https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD.jpeg" alt="" width="1432" height="374" srcset="https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD.jpeg 1432w, https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD-300x78.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD-1024x267.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD-768x201.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD-450x118.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/DAGScheduler_RDD_lineage_final_RDD-780x204.jpeg 780w" sizes="(max-width: 1432px) 100vw, 1432px" /></a></p>
<p><strong>Shuffling</strong> происходит, когда данные перераспределяются между разделами. Это необходимо, когда преобразование требует информации из других разделов, например, суммирования всех значений в столбце. Spark соберет требуемые данные из каждого раздела и объединит их в новый раздел, вероятно, на другом исполнителе. <strong>Shuffling</strong> — это механизм, который Spark использует для перераспределения данных между разными исполнителями и даже между машинами.</p>
<p><strong>Перемешивание Spark</strong> срабатывает, когда мы выполняем определенные операции преобразования, такие как <code>gropByKey()</code>, <code>reducebyKey()</code>, <code>join()</code> на RDD и DataFrame.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-927 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark.jpeg" alt="" width="1807" height="911" srcset="https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark.jpeg 1807w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-300x151.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-1024x516.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-768x387.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-1536x774.jpeg 1536w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-450x227.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-780x393.jpeg 780w, https://datatalks.ru/wp-content/uploads/2025/01/shuffling_dependency_wide_spark-1600x807.jpeg 1600w" sizes="(max-width: 1807px) 100vw, 1807px" /></a></p>
<p>Еще одна иллюстрация работы приложения Spark</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1062" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan.jpeg" alt="" width="1052" height="506" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan.jpeg 1052w, https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan-300x144.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan-1024x493.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan-768x369.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan-450x216.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/spark_application_execution_plan-780x375.jpeg 780w" sizes="(max-width: 1052px) 100vw, 1052px" /></a></p>
<p><strong>Apache Spark Internals: Understanding Physical Planning (Stages, Tasks &amp; Pipelining)</strong></p>
<p><iframe title="Apache Spark Internals: Understanding Physical Planning (Stages, Tasks &amp; Pipelining)" width="1170" height="658" src="https://www.youtube.com/embed/TMb6xJc48zc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<p><strong>Apache Spark Internals: Task Scheduling &#8212; Execution of a Physical Plan</strong></p>
<p><iframe title="Apache Spark Internals: Task Scheduling - Execution of a Physical Plan" width="1170" height="658" src="https://www.youtube.com/embed/-iF7_tDtc3k?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<h2>Что такое кластер Apache Spark?</h2>
<p><strong>Кластеры Apache Spark</strong> — это группа компьютеров, которые работают как один компьютер и обрабатывают выполнение различных команд, выдаваемых из блокнотов. Apache Spark использует архитектуру типа «master-worker», которая по сути может иметь <strong>master process (главный процесс)</strong> и <strong>worker processes (рабочие процессы)</strong>, которые могут выполняться на нескольких машинах.</p>
<p>В <strong>Master node</strong> (главном узле) у вас есть <strong>программа драйвера (driver)</strong>, которая управляет приложением, поэтому код, который вы пишете, ведет себя как программа драйвера. Внутри программы драйвера первое, что мы делаем, это создаем <strong>Spark context.</strong> Предполагая, что к Spark context может быть шлюзом ко всем или любым функциям Spark при идентичном подключении к базе данных. <strong>Worker nodes (рабочие узлы)</strong> — это подчиненные узлы, чья работа заключается в основном в выполнении задач.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark.png" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-730 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark.png" alt="" width="1459" height="411" srcset="https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark.png 1459w, https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark-300x85.png 300w, https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark-1024x288.png 1024w, https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark-768x216.png 768w, https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark-450x127.png 450w, https://datatalks.ru/wp-content/uploads/2025/01/driver_program_apache_spark-780x220.png 780w" sizes="(max-width: 1459px) 100vw, 1459px" /></a></p>
<p>Главный узел содержит программу драйвера, которая управляет приложением, создавая объект контекста Spark. <strong>Объект контекста Spark</strong> работает с менеджером кластера для управления различными заданиями. Задача рабочих узлов — выполнять задания и возвращать результаты главному узлу.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/Spark_master_node_driver_program_spark_context_workers.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-732 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/Spark_master_node_driver_program_spark_context_workers.jpeg" alt="" width="710" height="760" srcset="https://datatalks.ru/wp-content/uploads/2025/01/Spark_master_node_driver_program_spark_context_workers.jpeg 710w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_master_node_driver_program_spark_context_workers-280x300.jpeg 280w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_master_node_driver_program_spark_context_workers-450x482.jpeg 450w" sizes="(max-width: 710px) 100vw, 710px" /></a></p>
<h2>Основные компоненты архитектуры Apache Spark</h2>
<ul>
<li><strong>Программа драйвера:</strong> запускает основную функцию и отвечает за координацию задач в кластере. Она определяет один или несколько объектов SparkContext, которые являются основными точками входа для взаимодействия с механизмом выполнения Spark.</li>
<li><strong>Spark Context:</strong> центральный координатор для приложений Spark. Он взаимодействует с менеджером кластера для распределения ресурсов и планирования задач. Spark Context также управляет кэшированием и распределенным хранением RDD.</li>
<li><strong>Менеджер кластера:</strong> отвечает за управление ресурсами и планирование задач в кластере. Spark может работать с различными менеджерами кластера, такими как автономные, Apache Mesos, Hadoop YARN и Kubernetes.</li>
<li><strong>Executor:</strong> это процессы JVM, работающие на рабочих узлах, которые выполняют задачи, запланированные программой драйвера. Каждый executor запускает несколько задач одновременно в отдельных потоках и напрямую взаимодействует с программой драйвера, чтобы сообщать о состоянии задач. Executors также отвечают за кэширование разделов RDD в памяти или на диске.</li>
<li><strong>Задача:</strong> это наименьшая единица работы в Spark, представляющая собой одну операцию над разделом данных. Задачи объединяются в этапы, которые представляют собой группы задач с одинаковой операцией и зависимостями.</li>
<li><strong>RDD (Resilient Distributed Dataset):</strong> это неизменяемая, распределенная коллекция объектов, которые могут обрабатываться параллельно. RDD распределяются по узлам кластера, и Spark автоматически управляет их распределением, отказоустойчивостью и восстановлением.</li>
<li><strong>Планировщик DAG:</strong> делит приложение Spark на этапы на основе зависимостей между RDD. Он планирует задачи на узлах-исполнителях, принимая во внимание локальность данных и ресурсы кластера.</li>
<li><strong>Выполнение запроса:</strong> оптимизатор запросов Spark Catalyst и механизм выполнения Tungsten оптимизируют и выполняют запросы SQL и операции DataFrame/Dataset. Catalyst оптимизирует планы запросов, используя такие методы, как predicate pushdown и project pruning, в то время как Tungsten оптимизирует физическое выполнение, используя такие методы, как генерация кода и управление памятью.</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture.png" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-735 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture.png" alt="" width="1536" height="826" srcset="https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture.png 1536w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture-300x161.png 300w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture-1024x551.png 1024w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture-768x413.png 768w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture-450x242.png 450w, https://datatalks.ru/wp-content/uploads/2025/01/Spark_Architecture-780x419.png 780w" sizes="(max-width: 1536px) 100vw, 1536px" /></a></p>
<p><span style="color: #ff6600;"><strong>Как компоненты Spark взаимодействуют для выполнения оптимизированного плана</strong></span>, созданного SparkContext. <strong>SparkContext</strong> передаёт этот план менеджеру кластера (который может быть автономным, YARN или Mesos) в рамках Spark. Менеджер кластера сначала проверяет доступные ресурсы и соответствующим образом назначает рабочие узлы. Эти узлы обрабатывают загрузку данных и выполняют задачи в распределённых разделах данных, обеспечивая быстрые вычисления в Apache Spark.</p>
<p>Дополнительным преимуществом архитектуры Spark является ее беспроблемное развертывание на распределенных системах хранения данных, таких как <strong>Hadoop</strong>, без необходимости какой-либо дополнительной поддержки для эффективной работы на этих платформах.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_context.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1905" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_context.jpeg" alt="" width="950" height="512" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_context.jpeg 950w, https://datatalks.ru/wp-content/uploads/2025/01/spark_context-300x162.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_context-768x414.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/spark_context-450x243.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/spark_context-780x420.jpeg 780w" sizes="(max-width: 950px) 100vw, 950px" /></a></p>
<h2>Как Executor обрабатывает данные в приложении Spark?</h2>
<p>В приложении Spark Executor играет решающую роль в управлении обработкой и хранением данных.</p>
<p>Вот как это работает:</p>
<ul>
<li><strong>Инициирование на Worker Nodes (рабочих узлах):</strong> каждый Executor инициируется как процесс на рабочем узле, гарантируя, что приложение эффективно использует распределенные вычислительные ресурсы.</li>
<li><strong>Выполнение задач и управление данными:</strong> Executors отвечают за выполнение назначенных им задач. Они предназначены для хранения данных либо в памяти для быстрого доступа, либо на диске для более постоянного хранения. Эта двойная возможность позволяет исполнителям сбалансировать скорость и доступность ресурсов, оптимизируя производительность.</li>
<li><strong>Взаимодействие с данными:</strong> Executors активно взаимодействуют с внешними источниками данных. Они считывают входные данные, необходимые для обработки, и записывают выходные данные обратно в эти источники, поддерживая бесперебойный поток информации в среду Spark и из нее.</li>
<li><strong>Application-Specific Allocation:</strong> каждое приложение Spark инициализирует свой собственный набор Executors. Это гарантирует, что задачи будут выполнены в изоляции от других запущенных приложений, предотвращая конфликты ресурсов и оптимизируя производительность приложения.</li>
</ul>
<p><strong>Job</strong> — это параллельное вычисление, состоящее из нескольких задач, и каждое распределенное действие — это job. Группа задач, которые могут быть выполнены для выполнения одной и той же задачи на нескольких исполнителях, представляет Stage. Каждое job разбивается на наборы задач, которые зависят друг от друга.</p>
<p>Ресурсы, предоставляемые всем рабочим узлам в соответствии с их потребностями, и управление всеми узлами осуществляется с помощью Cluster Manager, т.е. Cluster Manager — это режим, в котором мы можем запустить Spark.</p>
<h2>Что такое Spark Session | Точка входа в Spark</h2>
<p><strong>Spark Session</strong> — это унифицированная точка входа для приложений Spark; она была представлена в Spark 2.0. Она действует как соединитель для всех базовых функций Spark, включая RDD, DataFrames и Datasets, предоставляя унифицированный интерфейс для работы со структурированной обработкой данных. Это один из самых первых объектов, которые вы создаете при разработке приложения Spark PySpark или Spark SQL. Как разработчик Spark, вы создаете SparkSession с помощью метода <code>SparkSession.builder()</code>.</p>
<p><strong>Spark Session</strong> объединяет несколько ранее отдельных контекстов, таких как SQLContext, HiveContext и StreamingContext, в одну точку входа, упрощая взаимодействие со Spark и его различными API. Он позволяет пользователям выполнять различные операции, такие как чтение данных из различных источников, выполнение SQL-запросов, создание DataFrames и Datasets, а также эффективное выполнение действий с распределенными наборами данных.</p>
<ul>
<li><strong>SparkSession.builder()</strong>– Возвращаемый SparkSession.Builder класс. Это конструктор для SparkSession.master(), appName() и getOrCreate() являются методами SparkSession.Builder.</li>
<li><strong>master()</strong> – Это позволяет приложениям Spark подключаться и работать в разных режимах (локальный, автономный кластер, Mesos, YARN) в зависимости от конфигурации.</li>
<li><strong>Используйте local[x]</strong> при запуске на локальном ноутбуке. x должно быть целым числом и должно быть больше 0; это показывает, сколько разделов он должен создать при использовании RDD, DataFrame и Dataset. В идеале xзначение должно быть числом ядер ЦП, которые у вас есть.</li>
<li>Для standalone использования <code>spark://master:7077</code></li>
<li><strong>appName()</strong> – Задает имя для приложения Spark, которое отображается в веб-интерфейсе Spark. Если имя приложения не задано, задается случайное имя.</li>
<li><strong>getOrCreate()</strong> – Возвращает объект SparkSession, если он уже существует. Создает новый, если он не существует.</li>
</ul>
<h3><strong>Создать еще один Spark Session</strong></h3>
<p>Иногда вам может потребоваться создать несколько сеансов, что можно легко сделать с помощью <code>newSession()</code> метода. Он использует то же имя приложения и мастера, что и существующий сеанс. Базовый <strong>SparkContext</strong> будет одинаковым для обоих сеансов, так как у вас может быть только один контекст на приложение Spark.</p>
<h3><strong>Spark Session vs Spark Context</strong></h3>
<p><strong>Сессия Spark</strong> — это основной объект в Spark — точка входа каждого приложения Spark. Сессия представляет собой обертку вокруг sparkContext и содержит все метаданные, необходимые для начала работы с распределенными данными.</p>
<p><strong>SparkContext</strong> — это переменная объекта Spark Session, которая используется для работы с RDD.</p>
<p><strong>Контекст SQL</strong> — это то же самое, что и контекст Spark, переменная объекта сеанса Spark, которая используется для выполнения операций с DataFrames и DataSets.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/spark_session.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-775 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/spark_session.jpeg" alt="" width="666" height="293" srcset="https://datatalks.ru/wp-content/uploads/2025/01/spark_session.jpeg 666w, https://datatalks.ru/wp-content/uploads/2025/01/spark_session-300x132.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/spark_session-450x198.jpeg 450w" sizes="(max-width: 666px) 100vw, 666px" /></a></p>
<p>Когда мы закончим анализ, мы можем очистить кэш Spark и завершить сессию с помощью <code>SparkSession.stop()</code>.</p>
<h2>Сериализация данных в PySpark</h2>
<p><strong>Сериализация данных в Spark</strong> — это процесс преобразования объектов в байтовый поток, который может быть передан по сети, сохранён в файл или использован в распределённой среде для хранения и обработки данных. В контексте Spark, сериализация имеет особое значение, потому что данные и объекты должны быть переданы между различными узлами или процессами, а также сохранены в формате, который позволяет их быстро считывать и восстанавливать.</p>
<p>Когда мы говорим о физической сериализации данных в Spark, мы имеем в виду преобразование объектов Python (или других языков, которые поддерживает Spark) в бинарный формат, который может быть эффективно передан и обработан на разных узлах кластера или в локальном режиме.</p>
<h3><strong>Что происходит при сериализации</strong></h3>
<p><strong>Сериализация</strong> — это процесс, при котором объект (например, список, словарь, или даже пользовательский класс) преобразуется в последовательность байтов. Эти байты могут быть сохранены в файл, переданы по сети или использованы для передачи данных между разными процессами (например, между рабочими узлами кластера).</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/serialization_spark_process.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1074" src="https://datatalks.ru/wp-content/uploads/2025/01/serialization_spark_process.jpeg" alt="" width="487" height="403" srcset="https://datatalks.ru/wp-content/uploads/2025/01/serialization_spark_process.jpeg 487w, https://datatalks.ru/wp-content/uploads/2025/01/serialization_spark_process-300x248.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/serialization_spark_process-450x372.jpeg 450w" sizes="(max-width: 487px) 100vw, 487px" /></a></p>
<h3><strong>Типы сериализаторов в PySpark</strong></h3>
<p>В Spark доступны два основных сериализатора для общего использования:</p>
<p><strong>JavaSerializer (по умолчанию):</strong></p>
<p>Класс: <code>org.apache.spark.serializer.JavaSerializer</code></p>
<p>Этот сериализатор используется по умолчанию в Spark, в основном из-за его совместимости с объектами Java. Он использует встроенный механизм сериализации Java, что делает его высокосовместимым со всеми объектами Java.</p>
<ul>
<li><strong>Плюсы:</strong> Простота, не требует дополнительных настроек, работает с широким спектром типов объектов.</li>
<li><strong>Минусы:</strong> медленнее и производит больше сериализованных данных по сравнению с Kryo. Не идеально подходит для высокопроизводительных приложений с интенсивным использованием памяти.</li>
</ul>
<p><strong>KryoSerializer</strong></p>
<p>Класс: <code>org.apache.spark.serializer.KryoSerializer</code></p>
<p><strong>Kryo</strong> — это более оптимизированный сериализатор, разработанный для производительности и эффективности использования пространства. Он быстрее и генерирует меньшие сериализованные данные, что делает его предпочтительным выбором при работе со сложными структурами данных.</p>
<ul>
<li><strong>Плюсы:</strong> более высокая производительность для больших или сложных объектов, минимизирует размер данных.</li>
<li><strong>Минусы:</strong> требуется ручная регистрация пользовательских классов (т.е. нестандартных типов Java), что добавляет дополнительные шаги и накладные расходы на настройку.</li>
</ul>
<h3><strong>Как работает сериализация в PySpark</strong></h3>
<p>В Spark данные сериализуются, когда они перемещаются между узлами или сохраняются на диске.</p>
<p><strong> Вот упрощенный вид процесса:</strong></p>
<ol>
<li>Данные подготавливаются на узле драйвера и сериализуются в двоичный формат с помощью настроенного сериализатора.</li>
<li>Сериализованные данные передаются на рабочие узлы кластера.</li>
<li>Рабочие узлы десериализуют данные для обработки.</li>
<li>Результаты с рабочих узлов снова сериализуются перед отправкой обратно на узел драйвера.</li>
</ol>
<p>Сериализатор влияет как на задержку, так и на объем памяти этих шагов. Сериализация Kryo быстрее и генерирует меньше данных, что может снизить использование памяти и ускорить передачу по сети, что особенно полезно для итеративных задач или больших наборов данных.</p>
<h2>Spark Partitioning и Bucketing</h2>
<p><strong>Spark Partitioning и Bucketing</strong> — это техники организации данных в Apache Spark, которые помогают улучшить производительность при обработке больших объемов данных.</p>
<p><strong>Partitioning в Spark</strong> — это процесс распределения данных по разным частям (партициям) для параллельной обработки. Каждая партиция — это подмножество данных, которое может обрабатываться отдельным потоком или задачей.</p>
<p>Партиционирование данных позволяет Spark эффективно распределять работу между кластерами.<br />
При правильном partitioning можно уменьшить количество операций shuffle (перераспределение данных между узлами) в кластере, что значительно ускоряет обработку данных.</p>
<p><strong>Bucketing</strong> — это метод организации данных в дисковых файлах с использованием более контролируемого подхода. В отличие от partitioning, который делит данные на основе значений столбцов, bucketing делит данные на несколько фиксированных &#171;ведер&#187; (buckets) по хэш-значению.</p>
<p>Каждый &#171;bucket&#187; представляет собой раздел данных, который соответствует определенному диапазону или значению.</p>
<p><strong>Partitioning</strong> — это метод, который делит данные на части на уровне кластеров.<br />
<strong>Bucketing</strong> — это метод на уровне файловой системы, где данные делятся на несколько частей в рамках одного файла.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/partitioning_and_bucketing_apache_spark.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-933 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/partitioning_and_bucketing_apache_spark.jpeg" alt="" width="717" height="488" srcset="https://datatalks.ru/wp-content/uploads/2025/01/partitioning_and_bucketing_apache_spark.jpeg 717w, https://datatalks.ru/wp-content/uploads/2025/01/partitioning_and_bucketing_apache_spark-300x204.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/partitioning_and_bucketing_apache_spark-450x306.jpeg 450w" sizes="(max-width: 717px) 100vw, 717px" /></a></p>
<p><strong>Партиционирование:</strong> Используйте партиционирование, когда вам нужно распределить данные для параллельной обработки и оптимизировать локальность данных. Это полезно для фильтрации и объединений (joins), где условие фильтрации соответствует ключу партиции.</p>
<p><strong>Бакетирование:</strong> Используйте бакетирование, когда у вас есть большие наборы данных, и вы хотите оптимизировать производительность запросов, особенно для фильтров на основе равенства. Это полезно для сценариев, когда данные часто запрашиваются по конкретным критериям.</p>
<p><strong>Комбинирование обоих методов:</strong> В некоторых случаях сочетание партиционирования и бакетирования может дать наилучшие результаты. Вы можете разделить данные на партиции по высокоуровневой категории, а затем применить бакетирование внутри каждой партиции.</p>
<p>На следующей диаграмме показан поток распределенной обработки:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1065" src="https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark.jpeg" alt="" width="1424" height="728" srcset="https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark.jpeg 1424w, https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark-300x153.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark-1024x524.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark-768x393.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark-450x230.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/distributed_processing_flow_apache_spark-780x399.jpeg 780w" sizes="(max-width: 1424px) 100vw, 1424px" /></a></p>
<ul>
<li>Драйвер Spark создает план выполнения для распределенной обработки между множеством исполнителей Spark.</li>
<li>Драйвер Spark назначает задачи каждому исполнителю на основе плана выполнения. По умолчанию драйвер Spark создает разделы RDD (каждый соответствует задаче Spark) для каждого объекта S3 (Part1 &#8230; N). Затем драйвер Spark назначает задачи каждому исполнителю.</li>
<li>Каждая задача Spark загружает свой назначенный объект S3 и сохраняет его в памяти в разделе RDD. Таким образом, несколько исполнителей Spark загружают и обрабатывают свою назначенную задачу параллельно.</li>
</ul>
<h2>Оптимизатор Catalyst</h2>
<p>Внутри Spark используется движок, называемый оптимизатором Catalyst.для оптимизации планов выполнения. Catalyst имеет оптимизатор запросов, который можно использовать при запуске высокоуровневых API Spark, таких как Spark SQL, DataFrame и наборы данных, как показано на следующей диаграмме.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1068" src="https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark.jpeg" alt="" width="1487" height="791" srcset="https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark.jpeg 1487w, https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark-300x160.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark-1024x545.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark-768x409.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark-450x239.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/catalyst_optimizer_spark-780x415.jpeg 780w" sizes="(max-width: 1487px) 100vw, 1487px" /></a></p>
<p>Поскольку оптимизатор Catalyst не работает напрямую с RDD API, высокоуровневые API обычно быстрее низкоуровневого RDD API. Для сложных соединений оптимизатор Catalyst может значительно повысить производительность, оптимизируя план выполнения задания. Вы можете увидеть оптимизированный план вашего задания Spark на вкладке SQL пользовательского интерфейса Spark.</p>
<h3>Адаптивное выполнение запросов</h3>
<p>Оптимизатор Catalyst выполняет оптимизацию времени выполнения с помощью процесса, называемого <strong>Adaptive Query Execution</strong>.</p>
<p><strong>Adaptive Query Execution</strong> использует статистику времени выполнения для повторной оптимизации плана выполнения запросов во время выполнения вашего задания. Adaptive Query Execution предлагает несколько решений проблем производительности, включая объединение разделов после перемешивания, преобразование объединения сортировки-слияния в широковещательное объединение и оптимизацию перекошенного объединения.</p>
<h3>Объединение разделов после перемешивания</h3>
<p>Эта функция уменьшает разделы RDD (объединяет) после каждого перемешивания на основе map выходной статистики. Она упрощает настройку номера раздела перемешивания при выполнении запросов. Вам не нужно устанавливать номер раздела перемешивания, чтобы он соответствовал вашему набору данных. Spark может выбрать правильный номер раздела перемешивания во время выполнения после того, как у вас будет достаточно большое начальное количество разделов перемешивания.</p>
<h3>Преобразование сортировочно-слиятельного соединения в широковещательное соединение</h3>
<p>Эта функция распознает, когда вы объединяете два набора данных существенно разного размера, и использует более эффективный алгоритм объединения на основе этой информации. Для получения более подробной информации см. документацию Apache Spark. Стратегии присоединения обсуждаются в разделе «Оптимизация перемешиваний» .</p>
<h3>Оптимизация косого соединения</h3>
<p><strong>Перекос данных</strong> — одно из наиболее распространенных узких мест для заданий Spark. Он описывает ситуацию, в которой данные перекошены в определенные разделы RDD (и, следовательно, определенные задачи), что задерживает общее время обработки приложения. Это часто может снизить производительность операций соединения. Функция оптимизации перекоса соединения динамически обрабатывает перекос в соединениях сортировки-слияния, разделяя (и реплицируя при необходимости) перекошенные задачи на задачи примерно одинакового размера.</p>
<h2>Spark RDD vs. DataFrame vs. Dataset</h2>
<p>Понимание разницы между Spark RDD, DataFrames и наборами данных имеет важное значение в мире распределенной обработки данных. Эти различия, начиная от контроля и удобства и заканчивая сложностью и ясностью, позволяют специалистам по данным эффективно использовать возможности Apache Spark, независимо от характера их данных или сложности их задач.</p>
<p><strong>Вот некоторая информация о Spark RDD, DataFrames и Datasets:</strong></p>
<ul>
<li><strong>Spark RDD:</strong> самая базовая абстракция данных в Spark. Это неизменяемые и распределенные коллекции данных. RDD предлагают детальный контроль над обработкой данных, но они могут быть сложны в использовании.</li>
<li><strong>Spark DataFrames:</strong> абстракция более высокого уровня, чем RDD. Это структурированные данные, организованные в именованные столбцы, похожие на таблицу в базе данных. DataFrames проще в использовании, чем RDD, но они предлагают меньший контроль над обработкой данных.</li>
<li><strong>Spark Datasets:</strong> это новая абстракция данных в Spark, которая объединяет преимущества RDD и DataFrames. Datasets — это распределенные коллекции данных с дополнительной схемой. Они предлагают баланс контроля и удобства, что делает их хорошим выбором для различных задач обработки данных.</li>
</ul>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1056" src="https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api.jpeg" alt="" width="1548" height="682" srcset="https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api.jpeg 1548w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-300x132.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-1024x451.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-768x338.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-1536x677.jpeg 1536w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-450x198.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/history_of_spark_api-780x344.jpeg 780w" sizes="(max-width: 1548px) 100vw, 1548px" /></a></p>
<p>Таблица сравнения:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1058" src="https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark.jpeg" alt="" width="1386" height="485" srcset="https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark.jpeg 1386w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark-300x105.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark-1024x358.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark-768x269.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark-450x157.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/rdd_dataset_dataframe_apache_spark-780x273.jpeg 780w" sizes="(max-width: 1386px) 100vw, 1386px" /></a></p>
<h1>YouTube Videos Apache Spark</h1>
<p>Прежде чем мы перейдем к настройке среды, я публикую подборку видео по Apache Spark</p>
<h2>PySpark Tutorial for Beginners</h2>
<p>PlayList <a href="https://www.youtube.com/playlist?list=PLwFJcsJ61ouiU1wvzzRk3pjU8xT9buJhr" target="_blank" rel="noopener">PySpark Tutorial for Beginners</a></p>
<p><iframe title="PySpark Tutorial for Beginners" width="1170" height="658" src="https://www.youtube.com/embed/videoseries?list=PLwFJcsJ61ouiU1wvzzRk3pjU8xT9buJhr" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<h2>Apache Spark Architecture &#8212; EXPLAINED!</h2>
<p><iframe title="Apache Spark Architecture - EXPLAINED!" width="1170" height="658" src="https://www.youtube.com/embed/iXVIPQEGZ9Y?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
<h1>Java и Apache Spark</h1>
<p>Установка Java необходима для работы с PySpark, потому что Apache Spark написан на языке программирования Scala, который работает на платформе <strong>Java (JVM &#8212; Java Virtual Machine).</strong> Spark использует компоненты и библиотеки, которые требуют наличия Java.</p>
<table>
<thead>
<tr>
<th>Компонент</th>
<th>Зачем нужен</th>
<th>Установка</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Java</strong></td>
<td>Spark внутри работает на JVM, поэтому она обязательна</td>
<td>Установим</td>
</tr>
<tr>
<td><strong>Python</strong></td>
<td>Пишем код на Python</td>
<td>Установим нужную версию (если python еще не установлен)</td>
</tr>
<tr>
<td><strong>PySpark</strong></td>
<td>Библиотека для работы со Spark из Python</td>
<td>Установим через pip</td>
</tr>
</tbody>
</table>
<blockquote><p>Scala компилируется под Java VM.</p>
<hr />
</blockquote>
<p><span style="font-family: Roboto; font-size: revert;">Когда вы запускаете PySpark, Python-код взаимодействует с кластером Spark через </span><strong style="font-family: Roboto; font-size: revert;">Py4J</strong><span style="font-family: Roboto; font-size: revert;"> — библиотеку, которая позволяет Python-коду общаться с Java-объектами. </span></p>
<p><span style="font-family: Roboto; font-size: revert;">Таким образом, Java необходима для:</span></p>
<ul>
<li><strong>Запуска Spark:</strong> Для инициализации ядра Spark и работы всех его компонентов требуется Java.</li>
<li><strong>Совместимости с компонентами Spark:</strong> Spark и его различные компоненты (например, Spark SQL, MLlib и т.д.) используют Java и требуют Java Runtime для своей работы.</li>
<li><strong>Использования Py4J:</strong> Эта библиотека позволяет взаимодействовать Python-коду с JVM-кодом Spark, обеспечивая выполнение задач и обработки данных в распределенной среде.</li>
</ul>
<p>Таким образом, для корректной работы PySpark обязательно наличие Java на машине.</p>
<h1>Установка и настройка Apache Spark на отдельной машине</h1>
<hr />
<p>Все инструкции и примеры по работе с Apache Spark отдельно собраны в одном репозитории <strong><a href="https://github.com/ivanshamaev/pyspark-learning" target="_blank" rel="noopener">GitHub: pyspark-learning</a></strong>.</p>
<hr />
<p>В рамках этой статьи основной целью является написание Guide, который позволит начать работу в рамках одной машины (я все инсталляции выполняю на Ubuntu). На других ОС действия должны быть похожими, но скорей всего будут чем-то отличаться.</p>
<p>Я начну с описания установки Java, затем перейду к установки Apache Spark и PySpark. После этого будет приведены примеры скриптов для работы с PySpark.</p>
<h2>Установка JAVA</h2>
<p>Если у вас на машине отсутствует Java, то начинаем с инсталляции Java (будем использовать Java 11 версии).</p><pre class="urvanov-syntax-highlighter-plain-tag">sudo apt update
sudo apt install openjdk-11-jdk</pre><p>Проверяем, что Java установлена:</p><pre class="urvanov-syntax-highlighter-plain-tag">java -version</pre><p>Ожидаемый вывод должен быть примерно:</p><pre class="urvanov-syntax-highlighter-plain-tag">openjdk version "11.0.XX"</pre><p><strong>Далее нам необходимо установить переменную окружения <code>JAVA_HOME</code>.</strong></p>
<p>Запускаем команду:</p><pre class="urvanov-syntax-highlighter-plain-tag">sudo update-alternatives --config java</pre><p>Копируем</p><pre class="urvanov-syntax-highlighter-plain-tag">/usr/lib/jvm/java-11-openjdk-amd64/bin/java</pre><p>Добавляем в среду переменные в /etc/environment</p>
<p><code>/etc/environment</code> — это системный файл, который используется для настройки глобальных переменных окружения. Переменные в этом файле доступны для всех пользователей системы.</p>
<p>Команда редактирования переменных:</p><pre class="urvanov-syntax-highlighter-plain-tag">sudo nano /etc/environment</pre><p>Добавляем 2 строки:</p><pre class="urvanov-syntax-highlighter-plain-tag">JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export JAVA_HOME</pre><p>Перезагружаем с помощью команды:</p><pre class="urvanov-syntax-highlighter-plain-tag">. /etc/environment</pre><p>Проверяем $JAVA_HOME</p><pre class="urvanov-syntax-highlighter-plain-tag">echo $JAVA_HOME</pre><p>Результат:</p><pre class="urvanov-syntax-highlighter-plain-tag">/usr/lib/jvm/java-11-openjdk-amd64</pre><p></p>
<h2>Установка Apache Spark и PySpark &#8212; Вариант 1 &#171;Light&#187;</h2>
<ul>
<li><strong>Нужно ли ставить Spark отдельно?</strong><br />
Нет. Если ты устанавливаешь через <code>pip install pyspark</code>, он включает <strong>Spark</strong> внутрь пакета. Можно начать работать без отдельной установки Spark.</li>
<li><strong>Нужна ли Java?</strong><br />
Да, обязательно. <strong>PySpark использует Java-процессы под капотом.</strong></li>
</ul>
<h3><strong>Установка PySpark в виртуальном окружении</strong></h3>
<p>Устанавливаем виртуальную среду</p><pre class="urvanov-syntax-highlighter-plain-tag">python3 -m venv venv</pre><p>Активируем среду</p><pre class="urvanov-syntax-highlighter-plain-tag">source venv/bin/activate</pre><p>Устанавливаем PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag">pip install pyspark</pre><p>Запускаем PySpark:</p><pre class="urvanov-syntax-highlighter-plain-tag">pyspark</pre><p>Результат выполнения команды:</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-899 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI.jpeg" alt="" width="1264" height="379" srcset="https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI.jpeg 1264w, https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI-300x90.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI-1024x307.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI-768x230.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI-450x135.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/local_pyspark_command_spark_version_3_5_4_WEB_UI-780x234.jpeg 780w" sizes="(max-width: 1264px) 100vw, 1264px" /></a></p>
<h3><strong>Использование Spark UI</strong></h3>
<p>При локальном запуске PySpark предоставляет веб-интерфейс Spark UI для мониторинга процессов.</p>
<p>После запуска PySpark откройте <a href="http://localhost:4040" target="_blank" rel="noopener" data-wplink-url-error="true">http://localhost:4040</a>.</p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors.jpeg" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter wp-image-897 size-full" src="https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors.jpeg" alt="" width="1204" height="544" srcset="https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors.jpeg 1204w, https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors-300x136.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors-1024x463.jpeg 1024w, https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors-768x347.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors-450x203.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/localhost_spark_ui_jobs_stages_storage_executors-780x352.jpeg 780w" sizes="(max-width: 1204px) 100vw, 1204px" /></a></p>
<p>В Spark UI отражается следующая информация:</p>
<ul>
<li><strong>Активные задачи</strong> — список всех текущих заданий, которые выполняются на Spark.</li>
<li><strong>DAG выполнения</strong> — Directed Acyclic Graph (DAG) отображает последовательность операций, которые Spark будет выполнять на данных. Это помогает понять, как данные передаются через различные этапы выполнения.</li>
<li><strong>Использование памяти и shuffle</strong> — показывает, сколько памяти используется на каждом этапе обработки и как Spark проводит операции shuffle (перемещение данных между узлами или процессами). В локальном режиме это будет важно для отслеживания, не переполняется ли память вашего устройства.</li>
</ul>
<p>Если PySpark установлен локально через <code>pip</code>, то Spark запускается в <strong>локальном режиме (Local mode)</strong>. В локальном режиме Spark по-прежнему использует свой распределённый движок, разделяя задачи на подзадачи и управляя их параллельным выполнением. Это позволяет работать с большими объемами данных, но ограничивает производительность количеством доступных ядер и памяти вашего устройства.</p>
<p><code>.master("local[*]")</code> означает запуск Spark с использованием всех доступных ядер процессора. Вы можете также указать конкретное количество потоков, например, <code>.master("local[4]")</code>, чтобы использовать только 4 ядра.</p>
<p><strong>Процесс выполнения PySpark кода локально:</strong></p>
<ol>
<li>Вы пишете код на Python с использованием PySpark.</li>
<li>Запускаете SparkSession, который инициализирует Spark.</li>
<li>Spark начинает разбиение данных и распределение их по доступным ядрам процессора.</li>
<li>Данные обрабатываются, и результаты возвращаются обратно в ваш код.</li>
</ol>
<p><strong>Важно!</strong> Если вы работаете с большим объёмом данных, которые не помещаются в память вашего устройства, вы можете столкнуться с проблемами производительности или даже с нехваткой памяти. Но для понимания PySpark &#8212; локальной машины будет достаточно для экспериментов с инструментом.</p>
<h3><strong>Установка Jupyter Notebook и запуск примера PySpark</strong></h3>
<p>В той же виртуальной среде запускаем команды установки Jupyter Notebook:</p><pre class="urvanov-syntax-highlighter-plain-tag">pip install notebook</pre><p>Стартуем Jupyter Notebook:</p><pre class="urvanov-syntax-highlighter-plain-tag">jupyter notebook</pre><p>Откроется <a href="http://localhost:8888/tree" target="_blank" rel="noopener" data-wplink-url-error="true">http://localhost:8888/tree</a></p>
<p><a href="https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run.jpeg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-758" src="https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run.jpeg" alt="" width="783" height="263" srcset="https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run.jpeg 783w, https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run-300x101.jpeg 300w, https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run-768x258.jpeg 768w, https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run-450x151.jpeg 450w, https://datatalks.ru/wp-content/uploads/2025/01/jupyter_notebook_run-780x262.jpeg 780w" sizes="(max-width: 783px) 100vw, 783px" /></a></p>
<h3><strong>Запуск примера приложения PySpark в Jupyter Notebook</strong></h3>
<p>todo</p>
<h2>Установка Apache Spark и PySpark &#8212; Вариант 2 &#171;Docker Compose&#187;</h2>
<p>todo</p>
<h1>Как работать с Apache Spark в Google Colab?</h1>
<p><strong>Пример:</strong></p>
<ul>
<li><a href="https://gitlab.com/PythonRu/notebooks/-/blob/master/pyspark_beginner.ipynb" target="_blank" rel="noopener">https://gitlab.com/PythonRu/notebooks/-/blob/master/pyspark_beginner.ipynb</a> &#8212; описание в статье <a href="https://pythonru.com/biblioteki/pyspark-dlja-nachinajushhih" target="_blank" rel="noopener">Руководство по PySpark для начинающих</a></li>
</ul>
<p>todo</p>
<h1>Подборка примеров по Apache Spark</h1>
<ul>
<li><a href="https://github.com/spark-examples/pyspark-examples" target="_blank" rel="noopener">https://github.com/spark-examples/pyspark-examples</a> &#8212; Pyspark RDD, DataFrame and Dataset Examples in Python language</li>
</ul>
<h1>Использованные материалы для подготовки статьи</h1>
<ul>
<li><a href="https://vutr.substack.com/p/the-overview-of-apache-spark" target="_blank" rel="noopener">The Overview Of Apache Spark</a></li>
<li></li>
</ul>
<p>Сообщение <a href="https://datatalks.ru/apache-spark-quick-start/">Apache Spark Quick Start &#8212; Как начать работать с PySpark</a> появились сначала на <a href="https://datatalks.ru">DataTalks.RU. Data Engineering / DWH / Data Pipeline</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://datatalks.ru/apache-spark-quick-start/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
