---
title: Управление партиционированием данных
seo:
  description: >-
    Тема «Управление партиционированием данных» для собеседования Data Engineer.
    Какие отличия между операциями repartition и coalesce в контексте Apache
    Spark, и что представляет собой операция partitionBy?
  title: Управление партиционированием данных — Data Engineer
questionDates:
  q-transfer-0311: '2026-10-01'
  q-transfer-0326: '2026-10-01'
---

[Все темы Data Engineer](/prep/data-engineer)

<span
  id="q-14bee738d69b81d2958cc2cdbb098430"
  data-question-redirect="/prep/data-engineer/optimizaciya-raboty-s-dannymi#q-transfer-0297"
></span>

## <strong>Какие отличия между операциями</strong> <code>repartition</code> <strong>и</strong> <code>coalesce</code> <strong>в контексте Apache Spark, и что представляет собой операция</strong> <code>partitionBy</code><strong>?</strong> [#q-14bee738d69b8173a3b1d233e8bf5b87]

В Apache Spark&#58;

1. <code>repartition</code>&#58; Эта операция перераспределяет данные между
   узлами кластера и изменяет количество партиций на указанное количество. Она
   может вызывать shuffle и является более затратной по ресурсам.

1. <code>coalesce</code>&#58; Эта операция объединяет существующие партиции в
   меньшее количество партиций без shuffle. Она более эффективна, когда
   требуется уменьшить количество партиций без перераспределения данных.

1. DataFrameWriter.partitionBy() задаёт разбиение файлов по значениям столбцов при записи. RDD.partitionBy() распределяет пары по ключам с заданным Partitioner и может менять число вычислительных партиций. Эти два API решают разные задачи.

:::note[Ссылки для изучения]

1. [repartition и coalesce: shuffle, параллелизм и число файлов](https://habr.com/ru/companies/neoflex/articles/578654/)
1. [Партиции RDD и секции Hive: partitionBy, hash/range и распределение данных](https://habr.com/ru/companies/sberbank/articles/582090/)
   :::

---

## <strong>Как управлять партиционированием данных в Spark для улучшения производительности?</strong> [#q-14bee738d69b816ab2d2c75778bd0cdc]

Управлять патриционированием данных в Spark можно следующим образом&#58;

- <strong>Используйте оптимальное количество партиций</strong>&#58; Убедитесь,
  что данные равномерно распределены по партициям.

  ```scala
  val rdd = sc.parallelize(data, numPartitions = 100)
  ```

- <strong>Репартиционирование данных</strong>&#58; Используйте
  <code>repartition&#40;&#41;</code> или <code>coalesce&#40;&#41;</code> для
  изменения количества партиций.

  ```scala
  val repartitionedRDD = rdd.repartition(200)
  ```

- <strong>Ключевое партиционирование</strong>&#58; Используйте
  <code>partitionBy&#40;&#41;</code> для распределения данных по ключам.

  ```scala
  val pairRDD = rdd.map(x => (x.key, x.value))
  val partitionedRDD = pairRDD.partitionBy(new HashPartitioner(100))
  ```

:::note[Ссылки для изучения]

1. [repartition и coalesce: shuffle, параллелизм и число файлов](https://habr.com/ru/companies/neoflex/articles/578654/)
1. [Партиции RDD и секции Hive: partitionBy, hash/range и распределение данных](https://habr.com/ru/companies/sberbank/articles/582090/)
   :::

---

## <strong>В каких случаях следует использовать пользовательские функции партиционирования?</strong> [#q-14bee738d69b81f28c3dcbc022f72876]

Пользовательские функции партиционирования следует использовать, когда&#58;

1. <strong>Требуется специфическое распределение данных</strong>&#58; Например,
   равномерное распределение данных по ключам.

1. <strong>Необходимо избежать перекосов данных</strong>&#58; Чтобы
   предотвратить ситуации, когда часть исполнителей перегружена данными.

Пример&#58;

```scala
class CustomPartitioner(partitions: Int) extends Partitioner {
  def numPartitions: Int = partitions
  def getPartition(key: Any): Int = {
    // Ваша логика распределения данных по партициям
    Math.floorMod(key.hashCode, partitions)
  }
}

val pairRDD = rdd.map(x => (x.key, x.value))
val partitionedRDD = pairRDD.partitionBy(new CustomPartitioner(100))
```

:::note[Ссылки для изучения]

1. [Spark Partitioner: интерфейс и критерии собственного распределения](https://habr.com/ru/companies/sberbank/articles/582090/)
   :::

---

## Как выбрать ключ партиционирования? [#q-transfer-0311]

Ключ выбирают из частых фильтров и жизненного цикла данных, чтобы pruning отбрасывал большую часть файлов и партицию можно было независимо загрузить или удалить. Слишком низкая cardinality дает огромные разделы, слишком высокая создает metadata overhead и мелкие файлы. Проверяют равномерность, поздние данные и ожидаемый размер. Партиционирование не заменяет clustering или индекс по другим условиям. Решение проверяют по pruning, числу файлов и стоимости metadata на реальном распределении ключей.

:::note[Ссылки для изучения]

1. [Выбор ключа и количества партиций по запросам и жизненному циклу данных: рекомендации PostgreSQL](https://postgrespro.ru/docs/postgresql/18/ddl-partitioning#DDL-PARTITIONING-DECLARATIVE-BEST-PRACTICES)
   :::

---

## Когда вложенное партиционирование вредит? [#q-transfer-0326]

Вложенные ключи помогают pruning, если запросы часто фильтруют их слева направо. Они вредят, когда комбинации создают тысячи почти пустых каталогов и мелких файлов: listing и catalog metadata становятся дороже самого чтения. Высококардинальный второй уровень особенно опасен. Выбор проверяют по числу файлов на partition, типичному фильтру и retention; clustering часто лучше дополнительного уровня каталога. Решение проверяют по pruning, числу файлов и стоимости metadata на реальном распределении ключей.

:::note[Ссылки для изучения]

1. [Вложенное секционирование и цена слишком большого числа партиций в PostgreSQL](https://postgrespro.ru/docs/postgresql/18/ddl-partitioning#DDL-PARTITIONING-DECLARATIVE-BEST-PRACTICES)
   :::
