> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-detect-table-modification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Руководство по производительности

> Советы по оптимизации производительности DataStore в сравнении с pandas

DataStore обеспечивает существенный прирост производительности по сравнению с pandas во многих операциях. В этом руководстве объясняется, почему это так и как оптимизировать рабочие нагрузки.

<div id="why-faster">
  ## Почему DataStore работает быстрее
</div>

<div id="sql-pushdown">
  ### 1. SQL Pushdown
</div>

Операции выполняются на уровне источника данных:

```python theme={null}
# pandas: загружает ВСЕ данные, затем фильтрует в памяти
df = pd.read_csv("huge.csv")       # Загрузка 10 ГБ
df = df[df['year'] == 2024]        # Фильтрация в Python

# DataStore: фильтрация на уровне источника
ds = pd.read_csv("huge.csv")       # Только метаданные
ds = ds[ds['year'] == 2024]        # Фильтрация в SQL
df = ds.to_df()                    # Загрузка только отфильтрованных данных
```

<div id="column-pruning">
  ### 2. Отсечение столбцов
</div>

Читаются только необходимые столбцы:

```python theme={null}
# DataStore: Считывает только столбцы name, age
ds = pd.read_parquet("wide_table.parquet")
result = ds.select('name', 'age').to_df()

# vs pandas: Считывает все 100 столбцов, затем выбирает нужные
```

<div id="lazy-evaluation">
  ### 3. Отложенное вычисление
</div>

Несколько операций сводятся к одному запросу:

```python theme={null}
# DataStore: Один оптимизированный SQL-запрос
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': 'sum'})
    .sort('sum', ascending=False)
    .head(10)
    .to_df()
)

# Преобразуется в:
# SELECT region, SUM(amount) FROM data
# WHERE amount > 100
# GROUP BY region ORDER BY sum DESC LIMIT 10
```

***

<div id="benchmark">
  ## Бенчмарк: DataStore vs pandas
</div>

<div id="test-environment">
  ### Тестовое окружение
</div>

* Данные: 10 миллионов строк
* Оборудование: стандартный ноутбук
* Формат файла: CSV

<div id="results">
  ### Результаты
</div>

| Операция                    | pandas (мс) | DataStore (мс) | Победитель             |
| --------------------------- | ----------- | -------------- | ---------------------- |
| Подсчёт GroupBy             | 347         | 17             | **DataStore (19.93x)** |
| Комбинированные операции    | 1,535       | 234            | **DataStore (6.56x)**  |
| Сложный конвейер            | 2,047       | 380            | **DataStore (5.39x)**  |
| Несколько Filter+Sort+Head  | 1,963       | 366            | **DataStore (5.36x)**  |
| Filter+Sort+Head            | 1,537       | 350            | **DataStore (4.40x)**  |
| Head/Limit                  | 166         | 45             | **DataStore (3.69x)**  |
| Сверхсложный (10+ операций) | 1,070       | 338            | **DataStore (3.17x)**  |
| Агрегация GroupBy           | 406         | 141            | **DataStore (2.88x)**  |
| Select+Filter+Sort          | 1,217       | 443            | **DataStore (2.75x)**  |
| Filter+GroupBy+Sort         | 466         | 184            | **DataStore (2.53x)**  |
| Filter+Select+Sort          | 1,285       | 533            | **DataStore (2.41x)**  |
| Sort (один столбец)         | 1,742       | 1,197          | **DataStore (1.45x)**  |
| Filter (один)               | 276         | 526            | Сопоставимо            |
| Sort (несколько столбцов)   | 947         | 1,477          | Сопоставимо            |

<div id="insights">
  ### Ключевые выводы
</div>

1. **Операции GroupBy**: DataStore до **19,93x быстрее**
2. **Сложные конвейеры**: DataStore **в 5–6 раз быстрее** (за счёт SQL pushdown)
3. **Простые операции среза**: производительность сопоставима — разница незначительна
4. **Лучший сценарий использования**: многошаговые операции с группировкой и агрегацией
5. **Zero-copy**: `to_df()` не создаёт накладных расходов на преобразование данных

***

<div id="when-datastore-wins">
  ## Когда DataStore — лучший выбор
</div>

<div id="heavy-aggregations">
  ### Тяжелые агрегации
</div>

```python theme={null}
# DataStore превосходит: в 19,93x быстрее
result = ds.groupby('category')['amount'].sum()
```

<div id="complex-pipelines">
  ### Сложные конвейеры
</div>

```python theme={null}
# DataStore превосходит: в 5-6 раз быстрее
result = (ds
    .filter(ds['date'] >= '2024-01-01')
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
    .sort('sum', ascending=False)
    .head(20)
)
```

<div id="large-file-processing">
  ### Обработка больших файлов
</div>

```python theme={null}
# DataStore: загружает только то, что нужно
ds = pd.read_parquet("huge_file.parquet")
result = ds.filter(ds['id'] == 12345).to_df()  # Быстро!
```

<div id="multiple-column-operations">
  ### Операции над несколькими столбцами
</div>

```python theme={null}
# DataStore: объединяет в единый SQL-запрос
ds['total'] = ds['price'] * ds['quantity']
ds['is_large'] = ds['total'] > 1000
ds = ds.filter(ds['is_large'])
```

***

<div id="when-pandas-wins">
  ## Когда pandas показывает сопоставимую производительность
</div>

В большинстве сценариев DataStore не уступает pandas по производительности или превосходит его. Однако в следующих случаях pandas может быть немного быстрее:

<div id="small-datasets">
  ### Небольшие наборы данных (\<1,000 строк)
</div>

```python theme={null}
# Для очень маленьких наборов данных накладные расходы минимальны в обоих случаях
# Разница в производительности незначительна
small_df = pd.DataFrame({'x': range(100)})
```

<div id="simple-slice-operations">
  ### Простые операции со срезами
</div>

```python theme={null}
# Простые операции среза без агрегации
df = df[df['x'] > 10]  # pandas немного быстрее
ds = ds[ds['x'] > 10]  # DataStore сопоставим
```

<div id="custom-python-functions">
  ### Пользовательские лямбда-функции Python
</div>

```python theme={null}
# pandas необходим для пользовательского кода на Python
def complex_function(row):
    return custom_logic(row)

df['result'] = df.apply(complex_function, axis=1)
```

<Info>
  **Важно**

  Даже в случаях, когда DataStore работает «медленнее», производительность обычно **сопоставима с pandas** — на практике разница несущественна. Преимущества DataStore при выполнении сложных операций значительно перевешивают эти редкие исключения.

  Для более точного управления выполнением см. [конфигурацию движка выполнения](/ru/products/chdb/configuration/execution-engine).
</Info>

***

<div id="zero-copy">
  ## Интеграция DataFrame без копирования данных
</div>

DataStore использует **zero-copy** при чтении и записи объектов pandas DataFrame. Это означает:

```python theme={null}
# to_df() НЕ копирует данные — это zero-copy операция
result = ds.filter(ds['x'] > 10).to_df()  # Без накладных расходов на преобразование данных

# То же самое при создании DataStore из DataFrame
ds = DataStore(existing_df)  # Данные не копируются
```

**Ключевые выводы:**

* `to_df()` практически ничего не стоит — без сериализации и копирования в памяти
* DataStore создается из pandas DataFrame мгновенно
* DataStore и представления pandas используют общую память

***

<div id="tips">
  ## Советы по оптимизации
</div>

<div id="use-performance-mode">
  ### 1. Включите режим производительности для ресурсоёмких рабочих нагрузок
</div>

Для рабочих нагрузок с интенсивной агрегацией, где вам не нужен точный формат вывода pandas (порядок строк, столбцы MultiIndex, корректировки dtype), включите режим производительности для максимальной пропускной способности:

```python theme={null}
from chdb.datastore.config import config

config.use_performance_mode()

# Теперь все операции используют выполнение через SQL без накладных расходов pandas:
# - Параллельное чтение Parquet (без preserve_order)
# - Агрегация одним SQL-запросом (filter+groupby в одном запросе)
# - Без накладных расходов на сохранение порядка строк
# - Без MultiIndex, без коррекции типов данных
result = (ds
    .filter(ds['amount'] > 100)
    .groupby('region')
    .agg({'amount': ['sum', 'mean', 'count']})
)
```

**Ожидаемое улучшение**: До 2–8 раз быстрее для рабочих нагрузок с filter+groupby, а также меньшее использование памяти для больших файлов Parquet.

См. [Режим производительности](/ru/products/chdb/configuration/performance-mode) для получения полной информации.

<div id="use-parquet">
  ### 2. Используйте формат Parquet вместо CSV
</div>

```python theme={null}
# CSV: Медленнее, читает весь файл
ds = pd.read_csv("data.csv")

# Parquet: Быстрее, столбцовая структура, сжатые данные
ds = pd.read_parquet("data.parquet")

# Конвертируйте один раз — выигрывайте всегда
df = pd.read_csv("data.csv")
df.to_parquet("data.parquet")
```

**Ожидаемое улучшение**: чтение данных в 3–10 раз быстрее

<div id="filter-early">
  ### 3. Фильтруйте как можно раньше
</div>

```python theme={null}
# Хорошо: сначала фильтрация, затем агрегация
result = (ds
    .filter(ds['date'] >= '2024-01-01')  # Уменьшаем объём данных заранее
    .groupby('category')['amount'].sum()
)

# Менее оптимально: обработка всех данных
result = (ds
    .groupby('category')['amount'].sum()
    .filter(ds['sum'] > 1000)  # Фильтрация слишком поздно
)
```

<div id="select-only-needed-columns">
  ### 4. Выбирайте только нужные столбцы
</div>

```python theme={null}
# Хорошо: отсечение столбцов
result = ds.select('name', 'amount').filter(ds['amount'] > 100)

# Менее оптимально: загружаются все столбцы
result = ds.filter(ds['amount'] > 100)  # Загружает все столбцы
```

<div id="leverage-sql-aggregations">
  ### 5. Используйте агрегации SQL
</div>

```python theme={null}
# GroupBy — это то, где DataStore раскрывает свой потенциал
# Ускорение до 20x!
result = ds.groupby('category').agg({
    'amount': ['sum', 'mean', 'count', 'max'],
    'quantity': 'sum'
})
```

<div id="use-head">
  ### 6. Используйте head() вместо полных запросов
</div>

```python theme={null}
# Не загружайте весь результат, если нужна только выборка
result = ds.filter(ds['type'] == 'A').head(100)  # LIMIT 100

# Избегайте этого для больших результатов
# result = ds.filter(ds['type'] == 'A').to_df()  # Загружает всё
```

<div id="batch-operations">
  ### 7. Батч-операции
</div>

```python theme={null}
# Хорошо: Одно выполнение
result = ds.filter(ds['x'] > 10).filter(ds['y'] < 100).to_df()

# Плохо: Несколько выполнений
result1 = ds.filter(ds['x'] > 10).to_df()  # Выполнение
result2 = result1[result1['y'] < 100]       # Повторное выполнение
```

<div id="use-explain">
  ### 8. Используйте explain() для оптимизации
</div>

```python theme={null}
# Просмотр плана запроса перед выполнением
query = ds.filter(...).groupby(...).agg(...)
query.explain()  # Проверить, выполняется ли pushdown операций

# Затем выполнить
result = query.to_df()
```

***

<div id="profiling">
  ## Данные профилирования рабочей нагрузки
</div>

<div id="enable-profiling">
  ### Включите сбор данных профилирования
</div>

```python theme={null}
from chdb.datastore.config import config, get_profiler

config.enable_profiling()

# Запустите рабочую нагрузку
result = your_pipeline()

# Просмотрите отчёт
profiler = get_profiler()
profiler.report()
```

<div id="identify-bottlenecks">
  ### Выявите узкие места
</div>

```text theme={null}
Отчёт о производительности
==================
Шаг                     Duration    % Итого
----                    --------    -------
SQL execution           2.5s        62.5%     <- Узкое место!
read_csv                1.2s        30.0%
Прочее                  0.3s        7.5%
```

<div id="compare-approaches">
  ### Сравнение подходов
</div>

```python theme={null}
# Тест подхода 1
profiler.reset()
result1 = approach1()
time1 = profiler.get_steps()[-1]['duration_ms']

# Тест подхода 2
profiler.reset()
result2 = approach2()
time2 = profiler.get_steps()[-1]['duration_ms']

print(f"Approach 1: {time1:.0f}ms")
print(f"Approach 2: {time2:.0f}ms")
```

***

<div id="summary">
  ## Краткая сводка лучших практик
</div>

| Практика                          | Эффект                                          |
| --------------------------------- | ----------------------------------------------- |
| Включите режим производительности | В 2–8 раз быстрее для нагрузок с агрегацией     |
| Используйте файлы Parquet         | Чтение в 3–10 раз быстрее                       |
| Фильтруйте как можно раньше       | Сокращает объём обрабатываемых данных           |
| Выбирайте только нужные столбцы   | Снижает I/O и расход памяти                     |
| Используйте GroupBy/агрегации     | До 20 раз быстрее                               |
| Используйте батч-операции         | Позволяет избежать повторного выполнения        |
| Профилируйте перед оптимизацией   | Помогает выявить реальные узкие места           |
| Используйте explain()             | Позволяет проверить оптимизацию запроса         |
| Используйте head() для выборок    | Позволяет избежать полного сканирования таблицы |

***

<div id="decision">
  ## Краткое руководство по выбору
</div>

| Ваша рабочая нагрузка                         | Рекомендация                                            |
| --------------------------------------------- | ------------------------------------------------------- |
| GroupBy/агрегация                             | Используйте DataStore                                   |
| Сложный многоэтапный конвейер                 | Используйте DataStore                                   |
| Большие файлы с фильтрами                     | Используйте DataStore                                   |
| Простые операции со срезами                   | Подойдёт любой вариант (производительность сопоставима) |
| Пользовательские лямбда-функции Python        | Используйте pandas или отложите преобразование          |
| Очень маленькие наборы данных (\<1,000 строк) | Подойдёт любой вариант (разница пренебрежимо мала)      |

<Tip>
  Для автоматического выбора оптимального движка используйте `config.set_execution_engine('auto')` (по умолчанию).
  Для максимальной пропускной способности при рабочих нагрузках с агрегацией используйте `config.use_performance_mode()`.
  Подробности см. в разделах [Движок выполнения](/ru/products/chdb/configuration/execution-engine) и [Режим производительности](/ru/products/chdb/configuration/performance-mode).
</Tip>
