> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Начало работы с chDB

> chDB — это встраиваемый SQL OLAP-движок на базе ClickHouse

В этом руководстве мы начнем работу с вариантом chDB для Python.
Сначала мы выполним запрос к JSON‑файлу в S3, затем создадим в chDB таблицу на основе этого JSON‑файла и выполним несколько запросов к данным.
Мы также рассмотрим, как получать результаты запросов в разных форматах, включая Apache Arrow и Pandas, и, наконец, узнаем, как выполнять запросы к DataFrame в Pandas.

## Настройка

Сначала создадим виртуальное окружение:

```bash theme={null}
python -m venv .venv
source .venv/bin/activate
```

А теперь установим chDB.
Убедитесь, что у вас установлена версия 2.0.3 или выше:

```bash theme={null}
pip install "chdb>=2.0.2"
```

А теперь установим [ipython](https://ipython.org/):

```bash theme={null}
pip install ipython
```

Для выполнения команд в оставшейся части руководства мы будем использовать `ipython`, который можно запустить командой:

```bash theme={null}
ipython
```

В этом руководстве мы также будем использовать Pandas и Apache Arrow, поэтому давайте установим и эти библиотеки:

```bash theme={null}
pip install pandas pyarrow
```

## Запросы к JSON‑файлу в S3

Теперь посмотрим, как выполнять запросы к JSON‑файлу, который хранится в S3 бакете.
[датасет YouTube dislikes](https://clickhouse.com/docs/ru/get-started/sample-datasets/youtube-dislikes.md) содержит более 4 миллиардов строк с данными о дизлайках к видео на YouTube по состоянию на 2021 год.
Мы будем работать с одним из JSON‑файлов из этого датасета.

Импортируйте chdb:

```python theme={null}
import chdb
```

Можно выполнить следующий запрос, чтобы описать структуру одного из JSON‑файлов:

```python theme={null}
chdb.query(
  """
  DESCRIBE s3(
    's3://clickhouse-public-datasets/youtube/original/files/' ||
    'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
    'JSONLines'
  )
  SETTINGS describe_compact_output=1
  """
)
```

```text theme={null}
"id","Nullable(String)"
"fetch_date","Nullable(String)"
"upload_date","Nullable(String)"
"title","Nullable(String)"
"uploader_id","Nullable(String)"
"uploader","Nullable(String)"
"uploader_sub_count","Nullable(Int64)"
"is_age_limit","Nullable(Bool)"
"view_count","Nullable(Int64)"
"like_count","Nullable(Int64)"
"dislike_count","Nullable(Int64)"
"is_crawlable","Nullable(Bool)"
"is_live_content","Nullable(Bool)"
"has_subtitles","Nullable(Bool)"
"is_ads_enabled","Nullable(Bool)"
"is_comments_enabled","Nullable(Bool)"
"description","Nullable(String)"
"rich_metadata","Array(Tuple(
    call Nullable(String),
    content Nullable(String),
    subtitle Nullable(String),
    title Nullable(String),
    url Nullable(String)))"
"super_titles","Array(Tuple(
    text Nullable(String),
    url Nullable(String)))"
"uploader_badges","Nullable(String)"
"video_badges","Nullable(String)"
```

Мы также можем подсчитать количество строк в этом файле:

```python theme={null}
chdb.query(
  """
  SELECT count()
  FROM s3(
    's3://clickhouse-public-datasets/youtube/original/files/' ||
    'youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst',
    'JSONLines'
  )"""
)
```

```text theme={null}
336432
```

Этот файл содержит чуть более 300 000 записей.

chdb пока не поддерживает передачу параметров запроса, но мы можем извлечь путь и передать его с помощью f-строки.

```python theme={null}
path = 's3://clickhouse-public-datasets/youtube/original/files/youtubedislikes_20211127161229_18654868.1637897329_vid.json.zst'
```

```python theme={null}
chdb.query(
  f"""
  SELECT count()
  FROM s3('{path}','JSONLines')
  """
)
```

> [!WARNING]
>
> Это допустимо делать с переменными, определёнными в вашей программе, но не делайте этого с пользовательским вводом, иначе ваш запрос будет уязвим для SQL-инъекции.

## Настройка формата вывода

Формат вывода по умолчанию — `CSV`, но его можно изменить с помощью параметра `output_format`.
chDB поддерживает форматы данных ClickHouse, а также [некоторые собственные](https://clickhouse.com/docs/ru/chdb/reference/data-formats.md), включая `DataFrame`, который возвращает DataFrame в Pandas:

```python theme={null}
result = chdb.query(
  f"""
  SELECT is_ads_enabled, count()
  FROM s3('{path}','JSONLines')
  GROUP BY ALL
  """,
  output_format="DataFrame"
)

print(type(result))
print(result)
```

```text theme={null}
<class 'pandas.core.frame.DataFrame'>
   is_ads_enabled  count()
0           False   301125
1            True    35307
```

Или, если мы хотим получить таблицу Apache Arrow:

```python theme={null}
result = chdb.query(
  f"""
  SELECT is_live_content, count()
  FROM s3('{path}','JSONLines')
  GROUP BY ALL
  """,
  output_format="ArrowTable"
)

print(type(result))
print(result)
```

```text theme={null}
<class 'pyarrow.lib.Table'>
pyarrow.Table
is_live_content: bool
count(): uint64 not null
----
is_live_content: [[false,true]]
count(): [[315746,20686]]
```

## Создание таблицы из JSON‑файла

Теперь рассмотрим, как создать таблицу в chDB.
Для этого нам понадобится другой API, поэтому сначала импортируем его:

```python theme={null}
from chdb import session as chs
```

Далее инициализируем сеанс.
Если мы хотим сохранить сеанс на диске, нужно указать имя каталога.
Если оставить его пустым, сеанс будет временным: chDB хранит данные во временном каталоге на диске и удаляет их при закрытии сеанса, поэтому данные не сохраняются.

```python theme={null}
sess = chs.Session("gettingStarted.chdb")
```

> [!NOTE]
>
> chDB запускает один встроенный движок на процесс, поэтому для каталога базы данных (его пути) действуют несколько правил:
>
> * **Один процесс на путь**: каталог данных chDB может быть открыт одновременно только одним процессом операционной системы. Второй процесс, открывающий тот же путь, завершится с ошибкой, пока первый не закроется.
> * **Один путь на процесс**: пока открыт сеанс или соединение, попытка открыть другой для *другого* пути завершится с ошибкой; сначала закройте открытые, чтобы избежать ошибки. Несколько сеансов или соединений на *одном и том же* пути могут сосуществовать.
> * **Параллелизм**: сеансы или соединения на одном пути могут выполнять запросы параллельно.
> * **Сеансы без пути являются общими**: без пути сеансы используют общую для всего процесса базу данных `:memory:` (поэтому пустые сеансы видят таблицы друг друга), а её временный каталог удаляется только после закрытия последнего сеанса.

Затем создадим базу данных:

```python theme={null}
sess.query("CREATE DATABASE IF NOT EXISTS youtube")
```

Теперь мы можем создать таблицу `dislikes` на основе схемы из JSON‑файла, используя приём `CREATE...EMPTY AS`.
Мы будем использовать настройку [`schema_inference_make_columns_nullable`](https://clickhouse.com/docs/ru/reference/settings/formats/schema-inference#schema_inference_make_columns_nullable), чтобы не все типы столбцов становились `Nullable`.

```python theme={null}
sess.query(f"""
  CREATE TABLE youtube.dislikes
  ORDER BY fetch_date 
  EMPTY AS 
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)
```

Затем можно использовать оператор `DESCRIBE`, чтобы просмотреть схему:

```python theme={null}
sess.query(f"""
   DESCRIBE youtube.dislikes
   SETTINGS describe_compact_output=1
   """
)
```

```text theme={null}
"id","String"
"fetch_date","String"
"upload_date","String"
"title","String"
"uploader_id","String"
"uploader","String"
"uploader_sub_count","Int64"
"is_age_limit","Bool"
"view_count","Int64"
"like_count","Int64"
"dislike_count","Int64"
"is_crawlable","Bool"
"is_live_content","Bool"
"has_subtitles","Bool"
"is_ads_enabled","Bool"
"is_comments_enabled","Bool"
"description","String"
"rich_metadata","Array(Tuple(
    call String,
    content String,
    subtitle String,
    title String,
    url String))"
"super_titles","Array(Tuple(
    text String,
    url String))"
"uploader_badges","String"
"video_badges","String"
```

Теперь заполним эту таблицу:

```python theme={null}
sess.query(f"""
  INSERT INTO youtube.dislikes
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)
```

Мы также можем выполнить оба шага сразу, используя конструкцию `CREATE...AS`.
Давайте создадим другую таблицу с помощью этой конструкции:

```python theme={null}
sess.query(f"""
  CREATE TABLE youtube.dislikes2
  ORDER BY fetch_date 
  AS 
  SELECT * 
  FROM s3('{path}','JSONLines')
  SETTINGS schema_inference_make_columns_nullable=0
  """
)
```

## Выполнение запросов к таблице

Напоследок выполним запрос к таблице:

```sql theme={null}
df = sess.query("""
  SELECT uploader, sum(view_count) AS viewCount, sum(like_count) AS likeCount, sum(dislike_count) AS dislikeCount
  FROM youtube.dislikes
  GROUP BY ALL
  ORDER BY viewCount DESC
  LIMIT 10
  """,
  "DataFrame"
)
df
```

```text theme={null}
                             uploader  viewCount  likeCount  dislikeCount
0                             Jeremih  139066569     812602         37842
1                     TheKillersMusic  109313116     529361         11931
2  LetsGoMartin- Canciones Infantiles  104747788     236615        141467
3                    Xiaoying Cuisine   54458335    1031525         37049
4                                Adri   47404537     279033         36583
5                  Diana and Roma IND   43829341     182334        148740
6                      ChuChuTV Tamil   39244854     244614        213772
7                            Cheez-It   35342270        108            27
8                            Anime Uz   33375618    1270673         60013
9                    RC Cars OFF Road   31952962     101503         49489
```

Допустим, затем мы добавим в DataFrame дополнительный столбец, чтобы вычислить соотношение лайков и дизлайков.
Можно написать следующий код:

```python theme={null}
df["likeDislikeRatio"] = df["likeCount"] / df["dislikeCount"]
```

## Выполнение запросов к DataFrame в Pandas

Затем мы можем выполнять запросы к этому DataFrame через chDB:

```python theme={null}
chdb.query(
  """
  SELECT uploader, likeDislikeRatio
  FROM Python(df)
  """,
  output_format="DataFrame"
)
```

```text theme={null}
                             uploader  likeDislikeRatio
0                             Jeremih         21.473548
1                     TheKillersMusic         44.368536
2  LetsGoMartin- Canciones Infantiles          1.672581
3                    Xiaoying Cuisine         27.842182
4                                Adri          7.627395
5                  Diana and Roma IND          1.225857
6                      ChuChuTV Tamil          1.144275
7                            Cheez-It          4.000000
8                            Anime Uz         21.173296
9                    RC Cars OFF Road          2.051021
```

Вы также можете подробнее прочитать о выполнении запросов к DataFrame в Pandas в [руководстве для разработчиков «Выполнение запросов к DataFrame в Pandas»](https://clickhouse.com/docs/ru/chdb/guides/querying-pandas.md).

## Следующие шаги

Надеемся, это руководство помогло вам получить общее представление о chDB.
Чтобы узнать больше о его использовании, см. следующие руководства для разработчиков:

* [Выполнение запросов к DataFrame в Pandas](https://clickhouse.com/docs/ru/chdb/guides/querying-pandas.md)
* [Выполнение запросов к Apache Arrow](https://clickhouse.com/docs/ru/chdb/guides/querying-apache-arrow.md)
* [Использование chDB в JupySQL](https://clickhouse.com/docs/ru/chdb/guides/jupysql.md)
* [Использование chDB с существующей базой данных clickhouse-local](https://clickhouse.com/docs/ru/chdb/guides/clickhouse-local.md)
