メインコンテンツへスキップ

ClickHouse Connectを使ったデータの挿入: 高度な使い方

InsertContexts

ClickHouse Connect は、すべての挿入を InsertContext 内で実行します。InsertContext には、クライアントの insert メソッドに引数として渡すすべての値が含まれます。さらに、InsertContext の初回作成時には、効率的な Native format での挿入に必要な対象カラムのデータ型を ClickHouse Connect が取得します。複数回の挿入で InsertContext を再利用すると、この”事前クエリ”を省略できるため、挿入をより高速かつ効率的に実行できます。 InsertContext は、クライアントの create_insert_context メソッドを使って取得できます。このメソッドは、insert 関数と同じ引数を受け取ります。再利用時に変更すべきなのは、InsertContextdata プロパティだけである点に注意してください。これは、同じテーブルに新しいデータを繰り返し挿入するための再利用可能なオブジェクトを提供するという、本来の目的に沿ったものです。
test_data = [[1, 'v1', 'v2'], [2, 'v3', 'v4']]
ic = test_client.create_insert_context(table='test_table', data='test_data')
client.insert(context=ic)
assert client.command('SELECT count() FROM test_table') == 2
new_data = [[3, 'v5', 'v6'], [4, 'v7', 'v8']]
ic.data = new_data
client.insert(context=ic)
qr = test_client.query('SELECT * FROM test_table ORDER BY key DESC')
assert qr.row_count == 4
assert qr[0][0] == 4
InsertContextには、挿入処理中に更新される可変状態が含まれているため、スレッドセーフではありません。

書き込みフォーマット

現在、書き込みフォーマットが実装されている型は限られています。ほとんどの場合、ClickHouse Connect は最初の (NULL ではない) データ値の型を確認し、そのカラムに適した書き込みフォーマットを自動的に判定します。たとえば、DateTime カラムに挿入する際、そのカラムの最初の挿入値が Python の整数であれば、ClickHouse Connect はそれをエポック秒とみなし、その整数値を直接挿入します。 ほとんどの場合、データ型の書き込みフォーマットをオーバーライドする必要はありませんが、グローバルレベルで変更したい場合は、clickhouse_connect.datatypes.format パッケージ内の関連メソッドを使用できます。

書き込みフォーマットのオプション

ClickHouse Typeネイティブ Python 型書き込みフォーマットコメント
Int[8-64], UInt[8-32]int-
UInt64int
[U]Int[128,256]int
BFloat16float
Float32float
Float64float
Decimaldecimal.Decimal
Stringstring
FixedStringbytesstringstring として挿入した場合、余分なバイトはゼロで埋められます
Enum[8,16]string
Datedatetime.dateintClickHouse は Date を 01/01/1970 からの日数として保存します。int 型はこの「エポック日付」値とみなされます
Date32datetime.dateintDate と同じですが、より広い日付範囲に対応します
DateTimedatetime.datetimeintClickHouse は DateTime をエポック秒で保存します。int 型はこの「エポック秒」値とみなされます
DateTime64datetime.datetimeintPython の datetime.datetime はマイクロ秒精度に制限されています。生の 64 ビット int 値も使用できます
Timedatetime.timedeltaint, string, timeClickHouse は DateTime をエポック秒で保存します。int 型はこの「エポック秒」値とみなされます
Time64datetime.timedeltaint, string, timePython の datetime.timedelta はマイクロ秒精度に制限されています。生の 64 ビット int 値も使用できます
IPv4ipaddress.IPv4Addressstring適切な形式の文字列は IPv4 アドレスとして挿入できます
IPv6ipaddress.IPv6Addressstring適切な形式の文字列は IPv6 アドレスとして挿入できます
Tupledict or tuple
Mapdict
NestedSequence[dict]
UUIDuuid.UUIDstring適切な形式の文字列は ClickHouse UUID として挿入できます
JSON/Object(‘json’)dictstring辞書または JSON 文字列のどちらも JSON カラムに挿入できます (Object('json') は非推奨です)
Variantobject現時点では、Variant の値はすべて String として挿入され、ClickHouse サーバーで解析されます
Dynamicobject警告 — 現時点では、Dynamic カラムへの挿入はすべて ClickHouse String として永続化されます

専用の 挿入 メソッド

ClickHouse Connect では、一般的なデータフォーマット向けに専用の 挿入 メソッドが用意されています。
  • insert_df — Pandas DataFrame を 挿入 します。Python の Sequence の Sequence である data 引数の代わりに、このメソッドの 2 番目のパラメータには、Pandas DataFrame インスタンスである必要がある df 引数を指定します。ClickHouse Connect は DataFrame をカラム指向のデータソースとして自動的に処理するため、column_oriented パラメータは不要で、使用することもできません。
  • insert_arrow — PyArrow Table を 挿入 します。ClickHouse Connect は Arrow table を変更せず、そのまま ClickHouse サーバー に渡して処理するため、tablearrow_table に加えて使用できる引数は databasesettings のみです。
  • insert_df_arrow — Arrow ベースの Pandas DataFrame または Polars DataFrame を 挿入 します。ClickHouse Connect は、その DataFrame が Pandas 型か Polars 型かを自動的に判別します。Pandas の場合は、各カラムの dtype backend が Arrow ベースであることを確認する検証が行われ、そうでないカラムがあるとエラーになります。
NumPy 配列は有効な Sequence の Sequence であり、メインの insert メソッドの data 引数として使用できるため、専用メソッドは必要ありません。

Pandas DataFrame の挿入

import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_df("users", df)

PyArrow Table を使った挿入

import clickhouse_connect
import pyarrow as pa

client = clickhouse_connect.get_client()

arrow_table = pa.table({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
})

client.insert_arrow("users", arrow_table)

ArrowベースのDataFrame挿入 (pandas 2.x)

import clickhouse_connect
import pandas as pd

client = clickhouse_connect.get_client()

# パフォーマンス向上のためArrowバックエンドのdtypesに変換する
df = pd.DataFrame({
    "id": [1, 2, 3],
    "name": ["Alice", "Bob", "Joe"],
    "age": [25, 30, 28],
}).convert_dtypes(dtype_backend="pyarrow")

client.insert_df_arrow("users", df)

タイムゾーン

Python の datetime.datetime オブジェクトを ClickHouse の DateTime または DateTime64 カラムに挿入する際、ClickHouse Connect はタイムゾーン情報を自動的に処理します。ClickHouse では、すべての DateTime 値が内部的にタイムゾーンを持たない Unix timestamp (epoch からの秒、またはその小数秒) として保存されるため、挿入時のタイムゾーン変換はクライアント側で自動的に行われます。

タイムゾーン情報を持つ datetime オブジェクト

タイムゾーン対応の Python の datetime.datetime オブジェクトを挿入すると、ClickHouse Connect は自動的に .timestamp() を呼び出して Unix timestamp に変換し、タイムゾーンのオフセットを正しく反映します。つまり、どのタイムゾーンの datetime オブジェクトでも挿入でき、UTC 相当のタイムスタンプとして正しく保存されます。
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()
client.command("CREATE TABLE events (event_time DateTime) ENGINE Memory")

# タイムゾーン対応のdatetimeオブジェクトを挿入する
denver_tz = pytz.timezone('America/Denver')
tokyo_tz = pytz.timezone('Asia/Tokyo')

data = [
    [datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)],
    [denver_tz.localize(datetime(2023, 6, 15, 10, 30, 0))],
    [tokyo_tz.localize(datetime(2023, 6, 15, 10, 30, 0))]
]

client.insert('events', data, column_names=['event_time'])
results = client.query("SELECT * from events")
print(*results.result_rows, sep="\n")
# 出力:
# (datetime.datetime(2023, 6, 15, 10, 30),)
# (datetime.datetime(2023, 6, 15, 16, 30),)
# (datetime.datetime(2023, 6, 15, 1, 30),)
この例では、3 つの datetime オブジェクトはそれぞれ異なる timezone を持つため、表す時点も異なります。各オブジェクトは対応する Unix timestamp に正しく変換され、ClickHouse に保存されます。
pytz を使用する場合、naive な datetime に timezone 情報を付与するには、localize() メソッドを使用する必要があります。tzinfo= を datetime コンストラクターに直接渡すと、過去のオフセットが誤って使われます。UTC については、tzinfo=pytz.UTC は正しく機能します。詳しくは pytz docs を参照してください。

タイムゾーン情報を持たない datetime オブジェクト

タイムゾーン情報を持たない Python の datetime.datetime オブジェクト (tzinfo がないもの) を挿入すると、.timestamp() メソッドはそれをシステムのローカルタイムゾーンの日時として解釈します。曖昧さを避けるため、以下を推奨します。
  1. 挿入時は常にタイムゾーン対応の datetime オブジェクトを使用する、または
  2. システムのタイムゾーンが UTC に設定されていることを確認する、または
  3. 挿入前に手動でエポックタイムスタンプへ変換する
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# 推奨: 常にタイムゾーン対応の datetime を使用する
utc_time = datetime(2023, 6, 15, 10, 30, 0, tzinfo=pytz.UTC)
client.insert('events', [[utc_time]], column_names=['event_time'])

# 代替方法: epoch タイムスタンプに手動で変換する
naive_time = datetime(2023, 6, 15, 10, 30, 0)
epoch_timestamp = int(naive_time.replace(tzinfo=pytz.UTC).timestamp())
client.insert('events', [[epoch_timestamp]], column_names=['event_time'])

タイムゾーンメタデータを持つDateTimeカラム

ClickHouseのカラムは、タイムゾーンメタデータを指定して定義できます (例: DateTime('America/Denver') または DateTime64(3, 'Asia/Tokyo')) 。このメタデータはデータの保存方法には影響せず (引き続きUTCのタイムスタンプとして保存されます) 、ClickHouseからデータをクエリして取得する際に使用されるタイムゾーンを制御します。 このようなカラムに挿入する際、ClickHouse ConnectはPythonのdatetimeをUnixタイムスタンプに変換します (タイムゾーンがある場合はそれを考慮します) 。データをクエリして取得すると、ClickHouse Connectは、挿入時にどのタイムゾーンを使ったかにかかわらず、そのdatetimeをカラムのタイムゾーンに変換して返します。
import clickhouse_connect
from datetime import datetime
import pytz

client = clickhouse_connect.get_client()

# ロサンゼルスのタイムゾーンメタデータを持つテーブルを作成
client.command("CREATE TABLE events (event_time DateTime('America/Los_Angeles')) ENGINE Memory")

# ニューヨーク時間を挿入(EDT 午前10:30、UTC では 14:30)
ny_tz = pytz.timezone("America/New_York")
data = ny_tz.localize(datetime(2023, 6, 15, 10, 30, 0))
client.insert("events", [[data]], column_names=["event_time"])

# クエリで取得すると、時刻は自動的にロサンゼルスのタイムゾーンに変換される
# ニューヨーク午前10:30(UTC-4)= UTC 14:30 = ロサンゼルス午前7:30(UTC-7)
results = client.query("select * from events")
print(*results.result_rows, sep="\n")
# 出力:
# (datetime.datetime(2023, 6, 15, 7, 30, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>),)

ファイルの 挿入

clickhouse_connect.driver.tools パッケージには insert_file メソッドが含まれており、ファイルシステムから既存の ClickHouseテーブルへ直接データを 挿入 できます。パースは ClickHouseサーバーに委譲されます。insert_file は次のパラメーターを受け取ります。
ParameterTypeDefaultDescription
clientClientRequired挿入 の実行に使用する driver.Client
tablestrRequired挿入 先の ClickHouseテーブル。完全修飾テーブル名 (データベースを含む) も指定できます。
file_pathstrRequiredデータファイルのネイティブファイルシステム上のパス
fmtstrCSV, CSVWithNamesファイルの ClickHouse Input Format。column_names が指定されていない場合は、CSVWithNames が使用されます
column_namesSequence of strNoneデータファイル内のカラム名の一覧。カラム名を含むフォーマットでは不要です
databasestrNoneテーブルのデータベース。テーブルが完全修飾されている場合は無視されます。指定しない場合、挿入 には client のデータベースが使用されます
settingsdictNonesettings の説明 を参照してください。
compressionstrNoneContent-Encoding HTTP header に使用される、ClickHouse で認識される圧縮タイプ (zstd、lz4、gzip)
データに不整合があるファイルや、日付/時刻の値が通常とは異なる形式のファイルでは、データ取り込みに適用される settings (input_format_allow_errors_numinput_format_allow_errors_num など) も、このメソッドで使用できます。
import clickhouse_connect
from clickhouse_connect.driver.tools import insert_file

client = clickhouse_connect.get_client()
insert_file(client, 'example_table', 'my_data.csv',
            settings={'input_format_allow_errors_ratio': .2,
                      'input_format_allow_errors_num': 5})
最終更新日 2026年6月10日