Zabbix DBが遅いとき:MySQLパーティションで解決する実務構築ガイド(第3編)

— file-per-tableへの切り替えとhistory・trendsパーティション構造の構成


概要

本記事では、前編で分離したTablespace構成を基に、
Zabbixの主要データ(history, trends)を日単位/月単位パーティションテーブルに変換する手順を扱う。

MySQL 8.0以降では、General Tablespace上にパーティションを構成することはできないため、
まず file-per-table 構造へ切り替えた後、パーティションを作成する必要がある。


1) 前提条件

  • OS:Ubuntu 22.04
  • Zabbix:7.4
  • MySQL:8.x
  • ディスク分離済み/data/history, /data/trends
  • 第1〜2編の手順(スキーマインポートおよびTablespace移動)が完了していること

⚠️ 注意:
稼働中の環境ではパーティション適用時にデータI/Oが急増するため、
必ずテスト環境で検証してから本番適用を行うこと。


2) General Tablespaceからfile-per-tableへ戻す

MySQL 8.0以降では、General Tablespaceに対してパーティションテーブルを作成できない。
そのため、各テーブルを必ず innodb_file_per_table 構造へ戻す必要がある。

mysql> ALTER TABLE zabbix.history       TABLESPACE = innodb_file_per_table;
mysql> ALTER TABLE zabbix.history_uint  TABLESPACE = innodb_file_per_table;
mysql> ALTER TABLE zabbix.trends        TABLESPACE = innodb_file_per_table;
mysql> ALTER TABLE zabbix.trends_uint   TABLESPACE = innodb_file_per_table;

3) パーティション作成前のポイント

🔹 history と trends の構造的な違い

テーブルデータ量用途一般的なパーティション周期
zabbix.history秒単位で数百万件以上リアルタイム短期保存日単位(1〜3日周期)
zabbix.trends平均/最大/最小などの集計データ中期〜長期保存月単位(30日周期)

4) Epoch Time計算の参考

パーティションの境界値はUTC基準のEpoch Timeを使用する。
これはタイムゾーンの混乱を防ぎ、cronスクリプトによる自動化を簡略化するためである。

Epoch Timeとは?

Epoch Time(UNIXタイムスタンプ)とは、
1970年1月1日00時00分00秒(UTC)からの経過秒数を整数で表した値である。
この値は世界中で共通の絶対時間基準
であり、
サーバーのローカルタイム(例:KST、JST、PSTなど)が異なっても
時間比較や自動化スクリプトで混乱しない。

✅ 初期パーティション作成時に必ず合わせるべき基準
(この基準を外すと、後続の Cron スクリプトが生成するパーティション境界値と衝突し → MySQL REORGANIZE エラーが発生)
MySQL パーティショニングは、時間境界(VALUES LESS THAN)が正確に一致していなければならない。
初期パーティションを誤って作成すると、自動スクリプトが計算する UTC Epoch 値と一致せず、
「パーティションが重複しています / パーティション境界が不正です」
あるいは文脈に合わない権限エラーが発生する場合がある。
以下の基準を必ず守って初期パーティションを作成すること。


🔥 HISTORY / HISTORY_UINT — 初期パーティション作成ルール(日単位)

History テーブルのパーティションは、**「今日 00:00:00 (UTC) から明日 00:00:00 (UTC) までの 24 時間」**を単位として区切る。
つまり各パーティションは 1 日分をカバーする。


① 今日の日付 (UTC) を確認

date -u +%Y-%m-%d

例:

2025-12-07

この日付がそのままパーティション名(pYYYYMMDD)として使用される。


② 明日(今日+1 日)の 00:00:00 UTC の Epoch を計算

VALUES LESS THAN() に指定する値は、
翌日 00:00:00 UTC の Epoch タイムスタンプでなければならない。

date -u -d '2025-12-08 00:00:00' +%s

出力例:

1765152000

この値がパーティション境界となる。


③ パーティション名の規則(自動スクリプトと同一)

  • パーティション名 = 今日の日付
  • 境界値 = 明日 00:00 UTC の Epoch 値

したがって:

  • パーティション名: p20251207
  • VALUES LESS THAN: 1765152000(2025-12-08 00:00 UTC)

④ パーティションの意味

p20251207 = clock < 2025-12-08 00:00:00 (UTC)

つまり、

パーティション p202512072025-12-07 の 1 日分のデータをすべて含むということになる。


🔥 TRENDS / TRENDS_UINT — 初期パーティション作成ルール(月単位)

Trends テーブルは「基準月の全期間 < 翌月 1日 00:00:00 UTC」を境界とする。
trend は初期の手動パーティション作成時、UNIX_TIMESTAMP() 関数を使用する。

① パーティション名(pYYYYMM)のルール
→ スクリプトを初めて適用する時点の「現在の月」
例:
2025年12月に初めて適用 → p202512

② VALUES LESS THAN の境界値
→ 必ず UNIX_TIMESTAMP(‘翌月 1日 00:00:00 UTC’)

基準月: 2025-12
翌月: 2026-01-01 00:00:00 UTC

VALUES LESS THAN (UNIX_TIMESTAMP(‘2026-01-01 00:00:00’))

この値が「2025年12月の全データ区間」を定義する境界となる。


絶対にこの history / trends の初期パーティション作成手順をそのままコピー&ペーストしてはいけない。環境に合わせて応用する必要がある。


5) history / history_uint — 日単位パーティション作成

📌 当日を基準に最初のパーティションを作成し、
運用環境の日付に合わせて境界値(epoch)を調整する。

mysql> ALTER TABLE zabbix.history
PARTITION BY RANGE (clock) (
  PARTITION p20251024 VALUES LESS THAN (1761350400) DATA DIRECTORY='/data/history',
  PARTITION pMAX      VALUES LESS THAN (MAXVALUE)   DATA DIRECTORY='/data/history'
);

mysql> ALTER TABLE zabbix.history_uint
PARTITION BY RANGE (clock) (
  PARTITION p20251024 VALUES LESS THAN (1761350400) DATA DIRECTORY='/data/history',
  PARTITION pMAX      VALUES LESS THAN (MAXVALUE)   DATA DIRECTORY='/data/history'
);

6) trends / trends_uint — 月単位パーティション作成

📌 基準日は翌月1日 00:00:00 UTCとする。

mysql> ALTER TABLE zabbix.trends
PARTITION BY RANGE (clock)(
  PARTITION p202510 VALUES LESS THAN (UNIX_TIMESTAMP('2025-11-01 00:00:00')) DATA DIRECTORY='/data/trends',
  PARTITION pMAX    VALUES LESS THAN (MAXVALUE)                               DATA DIRECTORY='/data/trends'
);

mysql> ALTER TABLE zabbix.trends_uint
PARTITION BY RANGE (clock)(
  PARTITION p202510 VALUES LESS THAN (UNIX_TIMESTAMP('2025-11-01 00:00:00')) DATA DIRECTORY='/data/trends',
  PARTITION pMAX    VALUES LESS THAN (MAXVALUE)                               DATA DIRECTORY='/data/trends'
);

7) 作業後の確認

  • /data/history および /data/trends 下に
    p20251024.ibd, p202510.ibd 形式のパーティションファイルが作成されていることを確認
  • MySQLログ(/var/log/mysql/error.log)にパーティションエラーがないか確認
  • 既存データは自動的に新しいパーティションへ移行されず、
    今後収集されるデータのみが新パーティションに保存される。

8) まとめ

区分作業結果
Tablespace → file-per-table切替ALTER TABLE ... TABLESPACE = innodb_file_per_tableパーティション作成可能状態
historyパーティション作成日単位(UTC epoch)/data/history に日別パーティション生成
trendsパーティション作成月単位(UNIX_TIMESTAMP)/data/trends に月別パーティション生成
データ境界基準UTCcron自動化時のタイムゾーン混乱防止

9) 次回予告

第4編では、このパーティション構造を自動で管理するスクリプトを構成する。
zbx-part-history.sh および zbx-part-trends.sh の2つのcronスクリプトにより、
毎日・毎月の新規パーティション自動生成と古いデータの自動削除を実現する。

🛠 마지막 수정일: 2025.12.11

💡 お困りですか?
Zabbix、Kubernetes、各種オープンソースインフラの構築・運用・最適化・障害解析が必要であれば、いつでもご連絡ください。

📧 メール: jikimy75@gmail.com
💼 サービス: 導入支援 | 性能チューニング | 障害解析コンサルティング