> ## 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.

# Эффективность хранения — временные ряды

> Повышение эффективности хранения временных рядов

После того как мы рассмотрели запросы к нашему набору данных со статистикой Википедии, перейдём к оптимизации эффективности его хранения в ClickHouse.
В этом разделе показаны практические приёмы, позволяющие сократить потребность в хранилище без ущерба для производительности запросов.

<div id="time-series-type-optimization">
  ## Оптимизация типов
</div>

Общий подход к повышению эффективности хранения — использовать оптимальные типы данных.
Возьмём столбцы `project` и `subproject`. Эти столбцы имеют тип String, но содержат относительно небольшое количество уникальных значений:

```sql theme={null}
SELECT
    uniq(project),
    uniq(subproject)
FROM wikistat;
```

```text theme={null}
┌─uniq(project)─┬─uniq(subproject)─┐
│          1332 │              130 │
└───────────────┴──────────────────┘
```

Это означает, что мы можем использовать тип данных LowCardinality(), в котором применяется словарное кодирование. Благодаря этому ClickHouse хранит внутренний идентификатор значения вместо исходного строкового значения, что, в свою очередь, позволяет существенно экономить место:

```sql theme={null}
ALTER TABLE wikistat
MODIFY COLUMN `project` LowCardinality(String),
MODIFY COLUMN `subproject` LowCardinality(String)
```

Мы также использовали тип UInt64 для столбца `hits`, который занимает 8 байт, хотя его максимальное значение сравнительно невелико:

```sql theme={null}
SELECT max(hits)
FROM wikistat;
```

```text theme={null}
┌─max(hits)─┐
│    449017 │
└───────────┘
```

Учитывая это, вместо него можно использовать UInt32: он занимает всего 4 байта и позволяет хранить значения до \~4 млрд:

```sql theme={null}
ALTER TABLE wikistat
MODIFY COLUMN `hits` UInt32;
```

Это уменьшит размер этого столбца в памяти как минимум в два раза. При этом размер на диске не изменится благодаря сжатию. Но будьте внимательны: не выбирайте слишком маленькие типы данных!

<div id="time-series-specialized-codecs">
  ## Специализированные кодеки
</div>

При работе с последовательными данными, например временными рядами, можно дополнительно повысить эффективность хранения с помощью специальных кодеков.
Общая идея заключается в том, чтобы хранить изменения между значениями, а не сами абсолютные значения, что позволяет значительно сократить занимаемое место при работе с медленно меняющимися данными:

```sql theme={null}
ALTER TABLE wikistat
MODIFY COLUMN `time` CODEC(Delta, ZSTD);
```

Мы использовали кодек Delta для столбца `time`, который хорошо подходит для временных рядов.

Правильно выбранный ключ упорядочивания также может сэкономить место на диске.
Поскольку фильтрация обычно выполняется по пути, мы добавим `path` в ключ сортировки.
Для этого потребуется пересоздать таблицу.

Ниже показана команда `CREATE` для исходной и оптимизированной таблиц:

```sql theme={null}
CREATE TABLE wikistat
(
    `time` DateTime,
    `project` String,
    `subproject` String,
    `path` String,
    `hits` UInt64
)
ENGINE = MergeTree
ORDER BY (time);
```

```sql theme={null}
CREATE TABLE optimized_wikistat
(
    `time` DateTime CODEC(Delta(4), ZSTD(1)),
    `project` LowCardinality(String),
    `subproject` LowCardinality(String),
    `path` String,
    `hits` UInt32
)
ENGINE = MergeTree
ORDER BY (path, time);
```

И давайте посмотрим, сколько места занимают данные в каждой таблице:

```sql theme={null}
SELECT
    table,
    formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
    formatReadableSize(sum(data_compressed_bytes)) AS compressed,
    count() AS parts
FROM system.parts
WHERE table LIKE '%wikistat%'
GROUP BY ALL;
```

```text theme={null}
┌─table──────────────┬─uncompressed─┬─compressed─┬─parts─┐
│ wikistat           │ 35.28 GiB    │ 12.03 GiB  │     1 │
│ optimized_wikistat │ 30.31 GiB    │ 2.84 GiB   │     1 │
└────────────────────┴──────────────┴────────────┴───────┘
```

Оптимизированная таблица в сжатом виде занимает чуть более чем в 4 раза меньше места.
