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

# Understanding part types and storage formats

> Learn about the different part types (Wide vs Compact) and storage formats (Full vs Packed) in ClickHouse, and how they affect performance.

ClickHouse uses two independent concepts for organizing data within parts:

* **Part types** (Wide vs Compact): How column data is stored within a part
* **Storage formats** (Full vs Packed): How the part's files are stored on disk

<h2 id="part-types-wide-vs-compact">
  Part types: Wide vs Compact
</h2>

Part types determine how column data is organized within a data part.

| Type        | Description                                                                                                           | Best for                                              |
| ----------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| **Wide**    | Each column is stored in separate file(s), each with its own [marks file](/concepts/core-concepts/glossary#mark-file) | Queries selecting a subset of columns                 |
| **Compact** | All columns are stored in a single file with a single [marks file](/concepts/core-concepts/glossary#mark-file)        | Ingestion performance and queries needing all columns |

<h3 id="when-each-type-is-used">
  When each type is used
</h3>

The part type is controlled by the following table settings:

* [`min_bytes_for_wide_part`](/reference/settings/merge-tree-settings#min_bytes_for_wide_part): Minimum bytes for a part to use Wide format
* [`min_rows_for_wide_part`](/reference/settings/merge-tree-settings#min_rows_for_wide_part): Minimum rows for a part to use Wide format

If either the number of bytes or rows in a data part is less than the corresponding setting value, the part is stored in `Compact` format; otherwise, it uses `Wide` format.

<h3 id="performance-considerations">
  Performance considerations
</h3>

**Compact parts:**

* Better ingestion performance
* Optimal when queries need all columns
* More efficient for small parts

**Wide parts:**

* More efficient for queries selecting only a subset of columns
* Better for large datasets with selective column access

Compact-to-wide merges are slower than wide-to-wide merges because ClickHouse uses [vertical merge](/concepts/core-concepts/merges#memory-optimized-merges) algorithms for compact-to-wide conversions, while using horizontal algorithms for compact-to-compact merges. If you want to force the use of wide parts regardless of size, you can set `min_bytes_for_wide_part=0`.

This can be useful in the following scenarios:

1. When you have tables with many columns (e.g. over 600 columns) and are making large inserts, setting this to 0 can help with performance
2. For optimizing memory usage of system tables like `system.metric_log` and `system.text_log` that are consuming excessive memory during merges
3. When dealing with tables that have high insert volumes and you want to optimize storage and merge behavior
4. When you want consistent part format behavior and don't want the overhead of format transitions based on size thresholds

It's worth noting that while setting this to 0 can improve certain performance characteristics, it may generate more GET requests to S3 storage due to the wide parts format.

<h3 id="limitations">
  Limitations
</h3>

Column size statistics are not calculated for compact parts, which can affect monitoring and optimization efforts. When querying `system.parts_columns`, compact parts show `0` for `column_data_compressed_bytes` and `column_data_uncompressed_bytes`. For more information see ["Find counts and sizes of wide or compact parts"](/resources/support-center/knowledge-base/troubleshooting/count-parts-by-type).

<h2 id="storage-formats-full-vs-packed">
  Storage formats: Full vs Packed
</h2>

Storage formats determine how a part's files are physically stored on disk.

| Format     | Description                                            | Availability          |
| ---------- | ------------------------------------------------------ | --------------------- |
| **Full**   | Each file is stored individually in the part directory | Open source and Cloud |
| **Packed** | All files are bundled into a single archive file       | Open source and Cloud |

<h3 id="full-storage">
  Full storage
</h3>

In Full storage, each part consists of multiple separate files stored individually on disk. This is the default storage format.

<h3 id="packed-storage">
  Packed storage
</h3>

In Packed storage, all part files are bundled into a single archive. This significantly reduces the number of file operations, which is critical for remote storage like S3 where each request has associated latency and cost.

**Benefits of Packed storage:**

* Fewer S3/object storage API calls
* Reduced metadata pressure on the coordination service
* Lower storage costs (full storage can be significantly more expensive)
* Better performance for small parts on remote storage

<h3 id="when-packed-storage-is-used">
  When Packed storage is used
</h3>

A part uses Packed storage if **any** of these conditions are true:

* Uncompressed bytes \< [`min_bytes_for_full_part_storage`](/reference/settings/merge-tree-settings#min_bytes_for_full_part_storage)
* Row count \< [`min_rows_for_full_part_storage`](/reference/settings/merge-tree-settings#min_rows_for_full_part_storage)
* Merge level \< [`min_level_for_full_part_storage`](/reference/settings/merge-tree-settings#min_level_for_full_part_storage)

Packed storage is opt-in: all three settings default to `0`, so parts use Full storage unless you raise one of them.

<Info>
  **Downgrade compatibility**

  Once a part is written in Packed storage, ClickHouse versions that do not support Packed storage can no longer read it. Enabling Packed storage therefore prevents downgrading to such a version, so enable it only once you are confident you will not need to roll back.
</Info>

The `min_level_for_full_part_storage` setting can be used to optimize both performance and costs on object storage, particularly for tables that receive continuous inserts.
The setting is available starting in ClickHouse version 25.10 and works in conjunction with `min_level_for_wide_part` to provide comprehensive control over part storage strategies.

Changing it from the default value (0) could be considered in the following use cases:

* When tables receive regular data ingestion, initial parts will be merged away quickly, making it wasteful to store them in full part format initially
* Setting this parameter prevents expensive S3 PUT requests during inserts. For example, one analysis showed that inserts creating full parts averaged 31.3 PUT requests per insert, while those creating only packed parts averaged just 2.22 PUT requests per insert
* Insert operations become faster, especially for tables with many columns, since packed storage writes all data into one file rather than creating separate files for each column.

Recommended configuration:

Set `min_level_for_full_part_storage = 2` for object-storage deployments.
This ensures that:

* Level 0 parts (initial inserts) use packed storage
* Level 1 parts continue using packed storage
* Only parts at level 2 and above use full storage format

<Tip>
  Avoid this setting for tables that receive very large but infrequent writes where insufficient merges occur, as large initial writes may benefit from full part storage immediately.
</Tip>

<h2 id="combining-part-types-and-storage-formats">
  Combining part types and storage formats
</h2>

These two concepts are orthogonal and you can have any combination:

| Combination      | Use case                               |
| ---------------- | -------------------------------------- |
| Wide + Full      | Large parts on local storage (default) |
| Wide + Packed    | Large parts on object storage          |
| Compact + Full   | Small parts on local storage           |
| Compact + Packed | Small parts on object storage          |

<h2 id="querying-part-information">
  Querying part information
</h2>

You can inspect the part type and part storage type of existing parts using the [`system.parts`](/reference/system-tables/parts) table:

```sql theme={null}
SELECT
    part_type,
    part_storage_type,
    max(level),
    count(),
    formatReadableSize(max(data_uncompressed_bytes)),
    formatReadableSize(min(data_uncompressed_bytes))
FROM system.parts
WHERE (database != 'system') AND active
GROUP BY
    1,
    2
ORDER BY
    1 ASC,
    2 ASC
```

You will see something like this:

```response theme={null}
   ┌─part_type─┬─part_storage_type─┬─max(level)─┬─count()─┬─formatReadab⋯sed_bytes))─┬─formatReadab⋯sed_bytes))─┐
1. │ Compact   │ Full              │      12688 │    2456 │ 1023.87 MiB              │ 23.78 MiB                │
2. │ Compact   │ Packed            │      97383 │   13748 │ 127.77 MiB               │ 1.00 B                   │
3. │ Wide      │ Full              │       7642 │    2000 │ 1.38 TiB                 │ 30.18 MiB                │
4. │ Wide      │ Packed            │         10 │     187 │ 110.01 MiB               │ 1.30 KiB                 │
   └───────────┴───────────────────┴────────────┴─────────┴──────────────────────────┴──────────────────────────┘
```
