> ## 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 の QBit データ型に関するドキュメント

# QBit データ型

`QBit` データ型は、より高速な近似検索のためにベクトルの格納方法を再構成します。各ベクトルの要素をまとめて格納するのではなく、すべてのベクトルにまたがって同じビット位置ごとにまとめて格納します。
これにより、ベクトルは元の精度のまま保持しつつ、検索時にきめ細かな量子化レベルを選択できます。ビットの読み取り量を減らせば I/O が減って計算が高速になり、より高い精度が必要な場合は多くのビットを読み取れます。量子化によるデータ転送量と計算量の削減による高速化のメリットを得ながら、必要に応じて元のデータをそのまま利用できます。

`QBit` 型のカラムを宣言するには、次の構文を使用します。

```sql theme={null}
column_name QBit(element_type, dimension[, stride])
```

* `element_type` – 各ベクトル要素の型。指定できる型は `Int8`、`BFloat16`、`Float32`、`Float64` です
* `dimension` – 各ベクトルの次元数
* `stride` – 任意。1 つのストリームグループにまとめて格納される次元数です。省略した場合のデフォルトは `dimension` (単一グループ) です。指定する場合、`dimension` は `stride` の倍数である必要があり、また `stride` が `dimension` より小さい場合は、`stride` は 8 の倍数でなければなりません。`dimension` 個の次元は、連続する `dimension / stride` 個のグループに分割され、各グループのビットプレーンはそれぞれ別のストリームに格納されます。これにより、先頭 `D` 次元 (`D` は `stride` の倍数) を対象とする検索では、それらの次元を含むグループのストリームだけを読み取ればよくなり、Matryoshka embeddings で有用です。

<div id="creating-qbit">
  ## QBit の作成
</div>

テーブルのカラム定義で `QBit` 型を使用する場合:

```sql theme={null}
CREATE TABLE test (id UInt32, vec QBit(Float32, 8)) ENGINE = Memory;
INSERT INTO test VALUES (1, [1, 2, 3, 4, 5, 6, 7, 8]), (2, [9, 10, 11, 12, 13, 14, 15, 16]);
SELECT vec FROM test ORDER BY id;
```

```text theme={null}
┌─vec──────────────────────┐
│ [1,2,3,4,5,6,7,8]        │
│ [9,10,11,12,13,14,15,16] │
└──────────────────────────┘
```

<div id="converting-arrays-to-qbit">
  ## 配列をQBitに変換する
</div>

配列の長さが`QBit`の次元と一致していれば、配列は`QBit`に変換されます。配列の要素型は、`QBit`の要素型と一致している必要はありません。数値型の要素であれば、どの型でも自動的に変換されます。これにより、既存の埋め込みカラムをそのまま`QBit`カラムへ移行できます。

```sql theme={null}
CREATE TABLE embeddings (id UInt32, embedding Array(Float32)) ENGINE = Memory;
INSERT INTO embeddings VALUES (1, [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]), (2, [0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]);

CREATE TABLE vectors (id UInt32, vec QBit(Float32, 8)) ENGINE = Memory;
INSERT INTO vectors SELECT id, embedding FROM embeddings;

SELECT * FROM vectors ORDER BY id;
```

```text theme={null}
┌─id─┬─vec───────────────────────────────┐
│  1 │ [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8] │
│  2 │ [0.8,0.7,0.6,0.5,0.4,0.3,0.2,0.1] │
└────┴───────────────────────────────────┘
```

この変換は、`CAST` を使って明示的に行うこともできます。たとえば、`CAST(embedding AS QBit(Float32, 8))` のように指定します。

<div id="converting-qbit-to-arrays">
  ## QBit を Array に変換する
</div>

逆方向の変換では、ビット転置された表現から元のベクトルを再構築するため、`QBit` を `Array` に CAST すると格納されている値が返されます。これは [Array を `QBit` に変換する](#converting-arrays-to-qbit) の逆です。

```sql theme={null}
SELECT [1, 2, 3, 4]::QBit(Float32, 4)::Array(Float32) AS vec;
```

```text theme={null}
┌─vec───────┐
│ [1,2,3,4] │
└───────────┘
```

再構成された配列では `QBit` の要素型が使用され、その後、各要素は指定された配列の要素型に変換されます。したがって、`QBit(Float32, N)` から `Array(Float64)` のように要素型も変更するキャストも可能です。

`Array` -> `QBit` -> `Array` のラウンドトリップは、`Int8`、`Float32`、`Float64` では情報損失なしで行えます。`BFloat16` の場合は、`BFloat16` への直接変換と同じ結果になり、失われる精度は `BFloat16` 自体に起因するものだけです。

`dimension` が 8 の倍数でない場合、内部表現に含まれる末尾のパディング要素は取り除かれるため、結果には常にちょうど `dimension` 個の要素が含まれます。

<div id="converting-between-qbit-types">
  ## QBit 型間の変換
</div>

`QBit` は、`dimension` (ベクトル要素数) が同じである限り、別の `QBit` にキャストできます。`element_type` と `stride` はどちらも変更できますが、`dimension` が異なる `QBit` にキャストするとベクトル自体が変わってしまうため、例外が発生します。

`element_type` を変更するとベクトルが再構築され、対応する `Array` の変換とまったく同じように、各要素が新しい型に変換されます。拡張変換 (たとえば `QBit(Float32, N)` から `QBit(Float64, N)`) は正確ですが、縮小変換では、`Array` の縮小キャストと同様に精度が失われます。

```sql theme={null}
SELECT [1, 2, 3, 4]::QBit(Float32, 4)::QBit(Float64, 4) AS vec;
```

```text theme={null}
┌─vec───────┐
│ [1,2,3,4] │
└───────────┘
```

[`stride`](#strides) のみを変更し (`element_type` は同じまま) 、値には一切手を加えずに保存済みの ビットプレーン を再グループ化するだけなので、これは常に非破壊です:

```sql theme={null}
SELECT range(16)::Array(Float32)::QBit(Float32, 16)::QBit(Float32, 16, 8)::Array(Float32)
     = range(16)::Array(Float32) AS is_lossless;
```

```text theme={null}
┌─is_lossless─┐
│           1 │
└─────────────┘
```

<div id="qbit-subcolumns">
  ## QBit サブカラム
</div>

`QBit` はサブカラムアクセスパターンを実装しており、保存されたベクトルの各ビットプレーンに個別にアクセスできます。各ビット位置には `.N` 構文でアクセスでき、`N` はビット位置を表します。

```sql theme={null}
CREATE TABLE test (id UInt32, vec QBit(Float32, 8)) ENGINE = Memory;
INSERT INTO test VALUES (1, [0, 0, 0, 0, 0, 0, 0, 0]);
INSERT INTO test VALUES (1, [-0, -0, -0, -0, -0, -0, -0, -0]);
SELECT bin(vec.1) FROM test;
```

```text theme={null}
┌─bin(tupleElement(vec, 1))─┐
│ 00000000                  │
│ 11111111                  │
└───────────────────────────┘
```

アクセス可能なサブカラム数は、要素型 (ストライド化されている場合は stride group の数) によって異なります。

* `Int8`: stride group ごとに 8 個のサブカラム (1-8)
* `BFloat16`: stride group ごとに 16 個のサブカラム (1-16)
* `Float32`: stride group ごとに 32 個のサブカラム (1-32)
* `Float64`: stride group ごとに 64 個のサブカラム (1-64)

サブカラムは グループ優先順 に従います。一般に、`vec.N` は stride group `(N-1) / element_size` のビットプレーン `(N-1) % element_size` を読み取ります。たとえば、`QBit(BFloat16, 4096, 1024)` では 4096 次元が 1024 ごとの 4 つのグループに分割されるため、サブカラムは 64 個あります。`vec.1` … `vec.16` は最初の stride group (次元 1–1024) のビットプレーン、`vec.17` … `vec.32` は 2 番目のグループ (次元 1025–2048) に対応し、以下同様です。

<div id="strides">
  ## Strides
</div>

デフォルトでは、`QBit` は各ビットプレーンを、すべての `dimension` 次元にまたがる単一ストリームとして格納するため、検索では常にベクトル全体のビットプレーンを読み取ることになります。省略可能な `stride` パラメータを使うと、`dimension` 次元が `dimension / stride` 個の連続したグループに分割され、各グループのビットプレーンは別々のストリームに格納されます。これにより、先頭から `D` 次元だけを対象に検索する場合 (`D` は `stride` の倍数) 、その次元を含むグループのストリームだけを読み取ればよくなります。これは、先頭の次元だけでも実用的な低次元の埋め込みとして使える [Matryoshka embeddings](https://arxiv.org/abs/2205.13147) で特に有用です。

```sql theme={null}
CREATE TABLE test (id UInt32, vec QBit(BFloat16, 4096, 1024)) ENGINE = MergeTree ORDER BY id;
```

ここでは、4096 個の次元が 1024 個ずつ 4 つのグループに分割されています。サブカラムはグループ優先順に並びます。`BFloat16` (16 個のビットプレーン) の場合、`vec.1` … `vec.16` は最初の stride group (次元 1–1024) の 16 個のビットプレーン、`vec.17` … `vec.32` は 2 番目の stride group (次元 1025–2048) に属し、以降も同様です。一般に、`vec.N` は stride group `(N-1) / element_size` のビットプレーン `(N-1) % element_size` を読み取ります。

reduced-dimension search を実行するには、転置された距離関数の第 4 引数として、読み取る次元数を渡します (下記参照) 。参照ベクトルには、少なくともその数の要素が含まれている必要があり (末尾に余分な要素があっても無視されます) 、この値は `stride` の倍数でなければなりません。

<div id="vector-search-functions">
  ## ベクトル検索関数
</div>

以下は、ベクトル類似度検索で `QBit` データ型を使用する距離関数です。

* [`L2DistanceTransposed`](/docs/ja/reference/functions/regular-functions/distance-functions#L2DistanceTransposed)
* [`cosineDistanceTransposed`](/docs/ja/reference/functions/regular-functions/distance-functions#cosineDistanceTransposed)
* [`dotProductTransposed`](/docs/ja/reference/functions/regular-functions/distance-functions#dotProductTransposed)

ストライド化された `QBit` の場合、これらの関数はオプションの第4引数 `used_dims` (読み取る先頭の次元数) を受け付け、指定した次元をカバーする stride group のみを読み取ります。参照ベクトルは少なくとも `used_dims` 個の要素を持っている必要があり (余分な末尾要素は無視されるため、フルサイズのクエリベクトルを事前にスライスしなくても reduced-dimension search に再利用できます)、`used_dims` は `stride` の倍数でなければなりません。
