# Machbase DBMS マニュアル — 全文 > 公開中の Machbase DBMS 8.7.0 日本語ページをナビゲーション順にまとめた Markdown コーパスです。 - language: `ja` - document_count: `242` - document_index: https://docs.machbase.com/ja/llms-chunks.json --- title: "Machbase DBMS マニュアル" url: https://docs.machbase.com/ja/dbms/ language: ja kind: section --- # Machbase DBMS マニュアル Machbase DBMS マニュアルへようこそ。本書は Machbase 8.7.0 を対象に、インストール、 テーブルタイプ別の利用方法、アプリケーション開発、運用、セキュリティ、リファレンスを説明します。 初めて利用する場合は、1章の SQL 演習を実行し、2章でデータモデルとストレージ・運用の原理を学びます。 システムを設計する場合は、4章のテーブル選択基準を確認してから、必要なテーブルの章に進んでください。 利用中の機能の正確な構文やサポート範囲は16章で確認できます。 ## マニュアルの構成 | 章 | タイトル | 内容 | |----|------|------| | 1 | [はじめに](./getting-started/) | 概要、接続確認、クイックスタート、基本コマンド | | 2 | [基本概念](./core-concepts/) | テーブルタイプ、時間モデル、ROLLUP、Retention Policy | | 3 | [インストール・デプロイ・アップグレード](./installation-deployment-upgrade/) | 事前準備、Standard Edition、Cluster Edition、アップグレード | | 4 | [テーブルタイプの選択とスキーマ設計](./data-modeling-table-design/) | タイプの選択、スキーマ、変更ポリシー、モデリングパターン | | 5 | [TAG テーブルの利用](./tag-table-usage/) | TAG 構造、メタデータ、入力、クエリ、補正、運用 | | 6 | [TAG テーブルの ROLLUP](./tag-rollup-usage/) | ROLLUP の設計、作成、クエリ、再構築、運用、性能チューニング | | 7 | [LOG テーブルの利用](./log-table-usage/) | LOG 構造、入力、テキスト検索 | | 8 | [TRANSACTION テーブルの利用](./rdb-table-usage/) | TRANSACTION スキーマ、DML、トランザクション、JOIN、バックアップ・リストア | | 9 | [LOOKUP テーブルの利用](./lookup-table-usage/) | 参照データ、PRIMARY KEY、JSON、一般的な述語を使う DML、JOIN | | 10 | [VOLATILE テーブルの利用](./volatile-table-usage/) | インメモリテーブル、UPSERT、状態キャッシュ、再起動とデータ消失 | | 11 | [開発とアプリケーション連携](./development-tools-integration/) | 連携方式、共通概念、言語別 SDK/API | | 12 | [性能チューニング](./performance-tuning/) | クエリ性能、取り込み性能、キャッシュ調整 | | 13 | [運用・設定・復旧](./operations-configuration-recovery/) | サーバー管理、バックアップ、Cluster 運用 | | 14 | [アカウント・権限・アクセス制御](./security-access-control/) | アカウント、権限、AUTH KEY、アクセス制御 | | 15 | [トラブルシューティング](./troubleshooting/) | エラーの診断と解決 | | 16 | [リファレンス](./reference/) | SQL 構文、関数、設定、システムカタログ | --- title: "1. はじめに" url: https://docs.machbase.com/ja/dbms/getting-started/ language: ja kind: section --- # 1. はじめに この章は、データベースを初めて扱う方や、他の DBMS から Machbase を利用する方の出発点です。 Machbase DBMS 8.7.0 がどのようなデータをどう保存するかを確認し、1件のイベントの入力とクエリを通じて 基本的な SQL の流れを学びます。 概要はデータベースをインストールする前でも読めます。演習には、稼働中の DBMS サーバーと 接続ツール `machsql` が必要です。インストールと接続の準備は [10分クイックスタート](./quick-start/)の前提条件で説明します。 ## この章で学ぶこと 1. テーブル、行、列、SQL の役割を理解します。 2. 時間とともに蓄積する履歴と現在の状態を区別します。 3. 計測値、イベント、参照データに適した Machbase のテーブルタイプを確認します。 4. サーバーに接続し、LOG テーブルを作成してデータを入力・検索します。 5. イベント発生時刻とサーバー受信時刻の違いを確認し、次に読む文書を選びます。 ## 読む順序 | 節 | 読んだ後にできること | |---|---| | [Machbase DBMS の概要](./overview/) | 時系列データベースの目的と各テーブルタイプの役割を説明できます。 | | [10分クイックスタート](./quick-start/) | 接続、データの入力・クエリ、演習用テーブルの削除を実行できます。 | | [基本コマンド早見表](./command-cheatsheet/) | シェルコマンドと SQL を区別し、よく使うコマンドを探せます。 | | [次に読む文書の選択](./choose-next-doc/) | データや開発・運用作業に合った文書に進めます。 | 演習では、動作を確認しやすい少量の SQL `INSERT` を使用します。継続的に到着する大量データの 入力方式とエラー処理は、[データの入力とエクスポート](/ja/dbms/development-tools-integration/data-input-load-export/) で続けて学べます。 --- title: "1.1 Machbase DBMS の概要" url: https://docs.machbase.com/ja/dbms/getting-started/overview/ language: ja kind: page --- # 1.1 Machbase DBMS の概要 Machbase DBMS は、センサー計測値、設備イベント、アプリケーションログなど、時間とともに蓄積する データを保存し、SQL で検索・分析する時系列データベースです。データの構造と変更・クエリ方式に 適したテーブルを選び、元の履歴と参照データを組み合わせて管理します。 ## Machbase DBMS の紹介 ### データベースと SQL の役割 データベースはアプリケーションが収集したデータを一定の構造で保存し、複数の処理で再利用できるようにします。 DBMS は、データの読み書き要求、ユーザー権限、保存領域を管理するソフトウェアです。 テーブルは、同じ構造を持つレコードの集まりです。行は1件のイベントや計測を表し、列は時刻、 設備名、計測値などの項目を表します。列には数値、文字列、日時などのデータ型を指定します。 このように定義した構造をスキーマと呼びます。 例えば、温度履歴は次のように表せます。以下の時刻と値は概念説明用です。 | 計測対象 | 計測時刻 | 温度 | |---|---|---:| | 設備 A の温度センサー | 09:00:00 | 23.1 | | 設備 A の温度センサー | 09:00:01 | 23.5 | | 設備 B の温度センサー | 09:00:01 | 18.0 | SQL はデータを操作する言語です。`CREATE` でテーブルを作成し、`INSERT` で行を追加し、 `SELECT` で必要な行と列を読み出します。`WHERE` は検索条件、`GROUP BY` は集計単位、 `ORDER BY` は結果の並び順を指定します。同じ SQL を使っても、サポートされる変更操作と 保存特性はテーブルタイプによって異なります。 ### 現在の状態と時系列履歴 「設備 A の現在の温度は何度か」と「過去1時間に温度がどう変化したか」は異なる問いです。 現在値だけを上書きし続けると、過去の変化は分かりません。各計測値に時刻を付けて新しい行として 保存すれば、推移、最大値、異常の発生時刻を分析できます。 時系列システムでは、この履歴が増え続けます。入力速度だけでなく、どの対象のどの時間範囲を 検索するか、元データをどれだけ保持するかも設計する必要があります。計測値が必ず一定間隔で 到着するとは限りません。ネットワーク遅延、設備停止、再送信によって遅延到着や欠測が生じます。 ### 計測値、イベント、参照データ 計測値は、ある対象がある時刻にどのような値を持っていたかを表します。イベントは、アラーム、 設備停止、サービス開始など、何かが発生した事実を記録します。設備名、設置場所、計測単位は、 その記録を解釈するための参照データです。 これらは1つのシステムで併用します。温度異常の分析には、温度履歴だけでなく、同じ時刻の アラームとセンサーの設置場所も必要です。SQL の結合(`JOIN`)は、設備コードなどの共通値を 使って履歴と参照データを関連付けます。 ## Machbase で解決する課題 Machbase の時系列機能は、次の処理を組み合わせる場合に利用できます。 | 作業 | 例 | 関連機能 | |---|---|---| | 元の履歴を収集 | センサー計測値と設備イベントを継続的に保存 | TAG・LOG、SQL 入力、SDK Append | | 必要な範囲を検索 | 設備 A の直近1時間の温度変化を確認 | タグ・時間条件、インデックス、実行計画 | | 統計を繰り返し取得 | 長期間の分・時間単位の推移を比較 | TAG ROLLUP | | データを解釈 | センサーコードに設備名と場所を関連付け | 参照データ、JOIN | | 保持期間を管理 | 保持期間を過ぎた元データを削除 | 対応テーブルの Retention Policy | | 障害に備えて保護 | バックアップと復旧手順を検証 | Edition 別のバックアップ・復旧機能 | ROLLUP は元データから区間統計を計算します。圧縮は保存に必要な領域を削減する技術、 Retention Policy は古いデータを削除するポリシーです。それぞれ目的が異なり、集計があるだけで 元データを削除してよいわけではありません。 必要な性能は、データ型、入力量、同時クエリ、保持期間、サーバーリソースによって変わります。 小さな演習で操作を学んだ後、実データと実際の検索条件でスループットと遅延を測定してください。 各機能の役割は[基本概念](/ja/dbms/core-concepts/)で詳しく説明します。 ## データに適したテーブルの選択 | テーブル | 主な用途 | 選択時の確認事項 | |---|---|---| | TAG | タグ名と時間・距離軸を持つ計測履歴 | 特定タグの範囲検索と集計が中心か確認します。 | | LOG | 複数項目を持つイベント・ログ履歴 | 新しい記録を追記し、時間条件や検索条件で読み出すか確認します。 | | LOOKUP | 設備コードやマッピングなどの永続的な参照データ | メモリに読み込むデータのサイズと変更方式を確認します。 | | TRANSACTION | 行単位の変更とトランザクションを必要とする業務データ | Standard Edition で関係型 DML とトランザクションが必要か確認します。 | | VOLATILE | 再起動後に再生成できる共有状態 | サーバー停止でデータが消えても復元できるか確認します。 | Machbase DBMS 8.7.0 では、LOG テーブルを `CREATE LOG TABLE` と明示して作成します。 タイプを省略した `CREATE TABLE` は TRANSACTION テーブルを作成します。TRANSACTION は Standard Edition でサポートされます。 業種だけでテーブルを決めることはできません。変更、結合、保持の要件を含む最終的な選択は、 [テーブルタイプの選択](/ja/dbms/data-modeling-table-design/table-types-selection-type/)で確認してください。 続いて、[10分クイックスタート](../quick-start/)でイベントを1件保存し、読み出してみましょう。 --- title: "1.2 10分クイックスタート" url: https://docs.machbase.com/ja/dbms/getting-started/quick-start/ language: ja kind: page --- # 1.2 10分クイックスタート 稼働中のサーバーに接続し、サービス開始イベントを1件保存して読み出します。 追記型のイベントに適した LOG テーブルを使用し、SQL の実行結果と2つの時刻列の意味を確認します。 インストール時間は、この演習の所要時間に含みません。 ## 前提条件 - Machbase DBMS サーバーが `127.0.0.1:5656` で稼働していること。 - `machsql` コマンドを使用できること。 - テーブルの作成・入力・検索・削除権限を持つ演習用アカウントで接続できること。 - 以下は初期演習用アカウント `SYS` とパスワード `MANAGER` を使用します。 変更済みの場合は実際のパスワードに置き換えてください。 - `/tmp` に SQL ファイルを保存でき、演習用の名前 `DBMS_GS_QUICK` を使用できること。 既存の業務テーブルと名前が重ならない演習環境を使用します。最後の `DROP TABLE` は、 演習用テーブルと入力したデータを削除します。 サーバーが未準備の場合は、[インストール・デプロイ・アップグレード](/ja/dbms/installation-deployment-upgrade/)と [Linux Standard Edition のインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux)を 先に参照してください。 ## 実行例 サービス開始イベントを1件 LOG テーブルに記録します。`CREATE LOG TABLE` でタイプを明示して作成すると、 `_arrival_time` 列が自動的に追加されます。 次のコマンドで SQL ファイルを保存し、実行します。 ```bash cat > /tmp/dbms_gs_quick.sql <<'SQL' CREATE LOG TABLE DBMS_GS_QUICK ( EVENT_ID INTEGER, EVENT_TIME DATETIME, LEVEL VARCHAR(10), MESSAGE VARCHAR(40) ); INSERT INTO DBMS_GS_QUICK (EVENT_ID, EVENT_TIME, LEVEL, MESSAGE) VALUES ( 1, TO_DATE('2026-07-02 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'INFO', 'service started' ); SELECT _arrival_time, EVENT_ID, EVENT_TIME, LEVEL, MESSAGE FROM DBMS_GS_QUICK ORDER BY EVENT_ID; DROP TABLE DBMS_GS_QUICK; SQL machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER -f /tmp/dbms_gs_quick.sql ``` ### 結果の確認 各 SQL ステップでエラーがないことを確認します。SELECT 結果は1行で、`EVENT_ID` が `1`、 `LEVEL` が `INFO`、`MESSAGE` が `service started` である必要があります。 `EVENT_TIME` はアプリケーションが保存したイベントの実際の発生時刻、`_arrival_time` は この例で DBMS が自動記録したサーバー受信時刻です。実行のたびに `_arrival_time` は変わり、 `EVENT_TIME` と一致する必要はありません。 `CREATE LOG TABLE` は構造を作成し、`INSERT` は1行を追加します。`SELECT` は読み出す列、 `ORDER BY EVENT_ID` は結果の順序を指定します。最後の `DROP TABLE` まで成功すると、 演習用テーブルは削除されます。データをさらに調べる場合は、実行前に最後の DROP 文を除き、 検索が終わってからその演習用テーブルだけを削除します。 再実行時に `DBMS_GS_QUICK` がすでに存在するエラーが出る場合、前の実行が `DROP TABLE` まで進まなかった可能性があります。`DESC DBMS_GS_QUICK;` で構造を確認し、前の演習で作成した テーブルである場合に限り `DROP TABLE DBMS_GS_QUICK;` を実行して再試行します。 接続エラーの場合は、まずサーバーアドレス、ポート、起動状態、アカウント情報を確認します。 ## この例で確認したこと | 項目 | 確認内容 | | --- | --- | | サーバー接続 | `machsql` で `127.0.0.1:5656` に接続 | | テーブル作成 | `CREATE LOG TABLE` で LOG テーブルを明示的に作成 | | データ入力 | `INSERT` と `TO_DATE` でイベントを保存 | | データ取得 | `SELECT` と `ORDER BY` で入力結果を確認 | | 自動列 | LOG テーブルの `_arrival_time` をサーバーが自動記録 | | 後片付け | `DROP TABLE` で演習用テーブルを削除 | --- title: "1.3 基本コマンド早見表" url: https://docs.machbase.com/ja/dbms/getting-started/command-cheatsheet/ language: ja kind: page --- # 1.3 基本コマンド早見表 接続コマンドは OS のターミナルで、SQL は接続済みの `machsql` で実行します。 サーバーアドレス、ポート、アカウントは実環境に合わせてください。以下の `MANAGER` は クイックスタートの初期演習用パスワードです。変更済みの場合は、そのアカウントの現在のパスワードを使います。 ## ターミナルで実行するコマンド | 作業 | コマンド | |---|---| | 対話接続 | `machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER` | | SQL ファイルの実行 | `machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER -f file.sql` | ## machsql で実行する SQL | 作業 | コマンド | |---|---| | テーブル一覧 | `SHOW TABLES;` | | 列と型の確認 | `DESC table_name;` | | TRANSACTION テーブルの作成 | `CREATE TRANSACTION TABLE table_name (...);` | | LOG テーブルの作成 | `CREATE LOG TABLE table_name (...);` | | データ入力 | `INSERT INTO table_name VALUES (...);` | | 条件に一致するデータの検索 | `SELECT ... FROM table_name WHERE ...;` | | 結果の並べ替え | `SELECT ... FROM table_name ORDER BY ...;` | | テーブルとデータの削除 | `DROP TABLE table_name;` | `table_name` と `...` は、実際の名前と定義に置き換えるプレースホルダーです。 そのまま実行できる SQL は[クイックスタート](../quick-start/)にあります。 `DROP TABLE` はデータも削除するため、削除対象が演習用テーブルであることを先に確認します。 Machbase DBMS 8.7.0 の `CREATE TABLE` は、タイプを省略すると TRANSACTION テーブルを作成します。 TRANSACTION は Standard Edition でサポートされます。タイプを明示すると例の意図が明確になります。 コマンドの詳細は [machsql リファレンス](../../reference/command-line-tools/machsql/)を参照してください。 --- title: "1.4 次に読む文書の選択" url: https://docs.machbase.com/ja/dbms/getting-started/choose-next-doc/ language: ja kind: page --- # 1.4 次に読む文書の選択 クイックスタートでは、1行を保存して検索しました。実際のシステムでは、データの形式に加えて、 変更方法、時刻の基準、クエリパターン、保持期間も決定します。 ## 設計前に確認すること - 同じ対象の値を時系列に蓄積しますか。それとも現在の状態を上書きしますか。 - 計測・発生時刻とサーバー受信時刻のどちらをクエリの基準にしますか。 - 特定タグの範囲検索、複数列の検索、キー検索、結合のうち、よく実行する処理は何ですか。 - 遅延到着、重複、誤った値をどう処理しますか。 - 元データと集計をそれぞれどれだけ保持しますか。再起動後も残す必要があるデータは何ですか。 - 必要な機能はどの Edition で利用できますか。 ## 次に読む文書 | 作業 | 次の文書 | |---|---| | 時系列履歴、保存、クエリの原理を理解する | [基本概念](../../core-concepts/) | | テーブルタイプと変更ポリシーを決める | [テーブルタイプの選択とスキーマ設計](../../data-modeling-table-design/) | | センサー・計測履歴を保存する | [TAG テーブルの利用](../../tag-table-usage/) | | イベントとログを収集・検索する | [LOG テーブルの利用](../../log-table-usage/) | | 長期間のタグ統計を取得する | [TAG テーブルの ROLLUP](../../tag-rollup-usage/) | | 参照データと業務データを管理する | [LOOKUP](../../lookup-table-usage/)、[TRANSACTION](../../rdb-table-usage/) | | 再生成できる状態を管理する | [VOLATILE テーブルの利用](../../volatile-table-usage/) | | アプリケーションから入力・クエリを行う | [開発とアプリケーション連携](../../development-tools-integration/) | | SQL 構文と型を確認する | [SQL リファレンス](../../reference/sql/) | | 運用・バックアップ・権限を設定する | [運用・設定・復旧](../../operations-configuration-recovery/)、[アカウントと権限](../../security-access-control/) | まず代表的なデータとよく使うクエリを決め、小規模に実行します。入力速度、クエリの遅延、 保存領域を測定してから、収集方式、インデックス、集計、保持ポリシーを調整します。 --- title: "2. 基本概念" url: https://docs.machbase.com/ja/dbms/core-concepts/ language: ja kind: section --- # 2. 基本概念 1章で SQL によるデータの保存と読み出しを確認した後、この章では設計と運用の観点から動作を理解します。 同じデータでも、時刻の意味、変更方式、クエリ範囲によって適切なテーブルと保存戦略は変わります。 例えば、設備の現在の温度と先月の温度履歴では、保持する行数が異なります。月平均温度と 瞬間的な異常値の検出では、必要なデータの解像度が異なります。この違いを理解すると、テーブル、 インデックス、ROLLUP、保持ポリシーを目的に合わせて選択できます。 ## この章の構成 | 節 | 扱う問い | |---|---| | [データモデルの概念](concepts/) | 1行に何を保存し、時刻・NULL・重複・変更をどう解釈するか。 | | [ストレージと実行の構造](storage-execution-architecture/) | 必要なデータをどう見つけ、ストレージ・インデックス・キャッシュがどのコストを削減するか。 | | [主要機能と用語の区別](features-concepts/) | 元データ・集計・保持・バックアップはそれぞれ何を担うか。 | | [Edition の概念](concepts-edition/) | 単一サーバーと分散構成をどう選び、どの機能差を確認するか。 | 例では概念説明用の小さなデータセットを使います。機能別の SQL、サポート範囲、運用手順は、 本文からリンクした詳細文書を参照してください。概念を理解したら、 [テーブルタイプの選択とスキーマ設計](../data-modeling-table-design/)で実データに適用します。 --- title: "2.1 データモデルの概念" url: https://docs.machbase.com/ja/dbms/core-concepts/concepts/ language: ja kind: page --- # 2.1 データモデルの概念 データモデルは、1件として何を保存し、どの値で識別し、どう変更・検索するかを定める規則です。 時系列モデルでは、計測対象、時刻、値の意味を併せて定義します。列名を決める前にこの規則を 確認すると、入力と分析結果を一貫して解釈できます。 ## 時系列データを理解する 時系列データは、時間に沿った観測やイベントの記録です。温度計測、約定履歴、サービスエラーログなどが 代表例です。一定間隔でもイベント発生時だけでも収集できます。保存順序と発生順序が同じとは限りません。 ### 1行の意味と識別子 温度履歴の1行を「1つのセンサーが特定時刻に測定した値」と定義した場合、センサー識別子、計測時刻、 値が必要です。識別子はデータの対象を区別し、時刻は対象の変化を解釈する基準になります。 複数センサーが同じ時刻に測定できるため、時刻だけでは行を一意に識別できません。同じセンサーの 同じ時刻のデータも再送されることがあります。重複を許すか、排除するか、別のイベント番号を設けるかを 決めてください。TAG の `PRIMARY KEY` はタグを識別し、関係型テーブルの行キーのように 各計測行の名前を一意にするものではありません。重複処理は [TAG テーブルの運用](../../tag-table-usage/operations-lifecycle/)で確認します。 ### 値、単位、品質 数値だけでは単位や意味が分かりません。同じ `23.5` でも温度、圧力、電圧は異なります。 タグ定義や参照データで単位と計測場所を管理し、1つの時系列で値の意味を一貫させます。 `NULL` と `0` も区別します。機器が0を計測したことと、計測に失敗して値が不明なことは異なります。 必要なら品質や状態を別の列に記録します。未収集の区間には行自体がないこともあり、 NULL の行が存在する場合とも区別する必要があります。 一般的な `AVG` などの集計は NULL 以外の値に適用されます。欠測をすべて0に置き換えたり、 異なる単位を一緒に集計したりすると結果が変わります。対応集計関数の正確な NULL 処理は [関数リファレンス](../../reference/sql/functions/functions-full/)を参照してください。 ### 時系列ワークロードの特徴 多くの時系列システムは、新しい行を継続的に入力し、特定対象の時間範囲を検索します。 最新値の監視と長期間の統計分析を併用することもあります。これらのパターンが、追記型の入力、 範囲検索、ROLLUP を使う理由です。 ただし、過去データが常に不変とは限りません。機器時計の誤り、センサー補正、重複収集で修正が 必要になることがあります。最新より古いデータを頻繁に読む業務もあります。実際の入力・検索・ 修正パターンを測定して設計してください。 ### テーブルタイプの役割 | テーブルタイプ | 概念上の役割 | |---|---| | TAG | 名前と時間・距離軸を持つ計測履歴 | | LOG | 新しい記録を追記し続けるイベントとログ | | TRANSACTION | トランザクションと行単位の変更を必要とする業務データ | | LOOKUP | メモリに読み込んで参照する永続的な参照データ | | VOLATILE | 再起動後に再生成できる共有インメモリ状態 | 履歴と参照データを分けると、全計測行に設備名や場所を繰り返し保存する必要が減ります。 ただし、最新の参照データを過去履歴に結合すると、結果にも現在の名前や場所が表示されます。 発生時点の情報が必要なら、イベントとともに保存するか、参照データの変更履歴を別途設計します。 ### 関係型業務モデルと時系列モデル 関係型モデルと時系列モデルは相互に排他的ではありません。関係型 DBMS でも時系列を保存し、 インデックス・パーティション・集計を利用できます。Machbase もテーブル、SQL、結合、関係型データの 変更機能を提供します。製品名ではなく主なワークロードを基準に比較してください。 | 観点 | 関係型業務データの例 | 時系列履歴の例 | |---|---|---| | 行の意味 | 1件の注文の現在の状態 | 1件のセンサー計測またはイベント | | 変更パターン | キーで見つけた行の更新・削除 | 新規レコードの追加と必要範囲の修正・削除 | | クエリパターン | キー検索、条件検索、業務テーブルの結合 | 対象・時間範囲の検索、推移、区間統計 | | 整合性要件 | 複数変更をまとめて確定または取り消す | 欠測・重複・遅延入力と参照可能時点を管理 | | 保持設計 | 業務ライフサイクルと変更履歴 | 元データの解像度、集計周期、保持期間 | LOG・TAG の保存・入力特性を TRANSACTION・LOOKUP・VOLATILE にそのまま適用しないでください。 最終的な選択は[テーブルタイプの選択](../../data-modeling-table-design/table-types-selection-type/)と [データ変更ポリシー](../../data-modeling-table-design/alter-data-mutation-policy/)で確認します。 ## 書き込み中心のワークロードと append-only モデル append は既存値を上書きせず、新しい行を追加する方式です。例えば設備状態が `RUNNING` から `STOPPED` に変わった際にイベントを追加すると、以前の状態と遷移時刻を保持できます。 現在状態を直接参照するテーブルと、変更履歴を保存するテーブルを分けて運用することもできます。 ### テーブルタイプと変更モデル LOG は追記型の履歴テーブルで、一般的な行 `UPDATE` をサポートしません。TAG は計測履歴を追加し、 対応する条件と Edition の範囲で DATA 値を補正できます。タグ名や時間軸まで任意に変更する 一般的な行更新とは異なります。 TRANSACTION は関係型 DML と明示的トランザクションを提供し、LOOKUP・VOLATILE は参照データや 状態の変更に使います。すべてのテーブルタイプが同じ変更機能を持つと考えず、 [データ変更ポリシー](../../data-modeling-table-design/alter-data-mutation-policy/)を確認してください。 追記型設計は、継続入力と過去行の任意更新を併用する場合の競合を減らせます。ただし DBMS 内部の 同期や障害復旧処理がすべてなくなるわけではありません。保存構造だけでロック不要や特定の スループットを保証することはできません。 ### SQL 入力と SDK Append SQL `INSERT` は SQL 文で値を入力し、実行結果を確認する経路です。SDK Append は継続収集のために 複数行を転送する入力 API です。バッファリング、転送、エラー確認、終了処理は各 SDK の仕様に従います。 アプリケーションのバッファへ入れた時点、サーバーが処理した時点、障害後も復旧できる時点は異なります。 LOG・TAG の Append は TRANSACTION テーブルの明示的トランザクションで `ROLLBACK` する対象ではありません。 TRANSACTION への Append のトランザクション参加とエラー処理は、使用する SDK の仕様を確認します。 入力確認と再試行は[データの入力とエクスポート](../../development-tools-integration/data-input-load-export/) を参照してください。 ### 修正、スキーマ変更、保持 誤った LOG イベントは、修正イベントを追記して履歴を残せます。削除して再入力する場合は、 LOG で許される時間ベースの削除範囲と入力順序を先に確認します。特定の1行だけを任意に削除できるとは 限りません。TAG の値補正は [TAG データ補正の設計](../../tag-table-usage/tag-data-update-correction/#design-correction-tag) に従います。 列の追加・削除と型変更も別の機能です。LOG・TAG のすべてのスキーマ変更が禁止されているわけではなく、 タイプと DATA・METADATA 領域によってサポート範囲が異なります。 [DDL 構文](../../reference/sql/syntax/ddl-syntax/)を確認してから実施します。 元データの追記を続けると保存領域が増えます。元データの保持期間と ROLLUP 統計の目的は別々に定めてください。 集計を作成しても元データは削除されません。 ## 時間モデルと _arrival_time ### 発生時刻と受信時刻 発生時刻は機器が計測した、またはイベントが発生した時刻です。受信時刻は DBMS がレコードを受け取った時刻です。 09:00 の計測値をネットワーク復旧後の09:05に受信すると、差は5分です。計測の推移には発生時刻、 収集遅延の分析には両方の時刻の比較が必要です。 時刻の精度、タイムゾーン、時計の正確さも区別します。ナノ秒を表現できても、センサーの時計が ナノ秒単位で正確とは限りません。DATETIME 文字列の解釈や表示に使うタイムゾーンは [タイムゾーン設定](../../reference/configuration/configuration-timezone/)を参照してください。 ### LOG テーブルの `_arrival_time` LOG には `_arrival_time` DATETIME 列が自動追加されます。値を省略する通常の入力ではサーバー受信時刻を 記録します。別途発生時刻が必要なら、一般の DATETIME 列を定義します。 ```sql CREATE LOG TABLE device_events ( device_id VARCHAR(20), event_time DATETIME, status VARCHAR(20) ); ``` `_arrival_time` を明示する入力経路もあるため、この列が常に実際の受信時刻を表すとは限りません。 明示入力の時刻順序と制約は [LOG の時間モデル](../../log-table-usage/arrival-time-model/)を確認します。 ```sql SELECT device_id, event_time, status FROM device_events WHERE _arrival_time >= TO_DATE('2026-07-03 09:00:00', 'YYYY-MM-DD HH24:MI:SS') AND _arrival_time < TO_DATE('2026-07-03 10:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY _arrival_time; ``` 開始を含み終了を含まない `[開始, 終了)` の範囲を使うと、連続区間の境界を二重集計する誤りを減らせます。 `BETWEEN` は両端を含むため、目的に合わせて選びます。LOG の `DURATION` は `_arrival_time` を基準に範囲を限定します。 ### TAG テーブルの BASETIME 列 時間軸 TAG テーブルでは、`BASETIME` 属性を持つ DATETIME 列へアプリケーションが時刻を入力します。 LOG の自動 `_arrival_time` 列は使用しません。 ```sql CREATE TAG TABLE sensor_values ( name VARCHAR(128) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); INSERT INTO sensor_values VALUES ('temp_sensor_01', TO_DATE('2026-07-03 08:55:00', 'YYYY-MM-DD HH24:MI:SS'), 23.1); ``` この例の `name` はセンサー、`time` は計測時刻、`value` は計測値です。`SUMMARIZED` は ROLLUP などの統計機能が使用する代表的な数値列を指定します。テーブルを作成するだけで 必要なすべての周期の集計が作られるわけではありません。 TAG には時間の代わりに数値軸を使う BASE DISTANCE モデルもあります。距離・位置に沿った計測では このモデルを検討しますが、時間軸専用の関数やポリシーをそのまま適用してはいけません。 [TAG スキーマ](../../tag-table-usage/table-structure-schema/)で軸別の規則を説明します。 ### 2つの時間モデルの比較 | 項目 | LOG | 時間軸 TAG | |---|---|---| | 特殊な時刻列 | 自動生成される `_arrival_time` | 宣言した `BASETIME` 列 | | 入力時刻の意味 | 通常はサーバー時刻、明示入力時は指定値 | アプリケーションが指定する時刻 | | 別の発生時刻 | 一般の DATETIME 列に保存可能 | BASETIME を発生時刻として使用可能 | | 主な設計課題 | どのイベントとフィールドを検索するか | どのタグのどの範囲を分析するか | 発生時刻が必要なだけで LOG を除外する必要はありません。時刻の意味に加え、タグ構造、検索・集計、 更新・削除条件でテーブルを選んでください。LOOKUP・VOLATILE・TRANSACTION の DATETIME は一般列であり、 LOG・TAG の特殊な時間軸機能は自動付与されません。 行の保存順序と結果の表示順序も区別します。順序が重要なら `ORDER BY` を明示し、 同じ時刻の行まで区別する場合は追加のソートキーを指定します。 --- title: "2.2 ストレージと実行の構造" url: https://docs.machbase.com/ja/dbms/core-concepts/storage-execution-architecture/ language: ja kind: page --- # 2.2 ストレージと実行の構造 クエリ時間は SQL 文の長さだけでは決まりません。読み出すデータ量、条件による範囲の絞り込み、 ソート・結合・集計に必要な処理が重要です。この節では、ストレージ、インデックス、キャッシュが それぞれどのコストを削減するかを説明します。 ## Machbase アーキテクチャの概要 ユーザーは `machsql` または SDK で入力・クエリ要求を送ります。サーバーは SQL 構文、オブジェクト、 権限を確認し、実行方法を決め、保存データにアクセスして結果を返します。保存・実行方式は テーブルタイプと Edition によって異なります。 ### Standard Edition の構造 Standard Edition は単一のデータベースサーバーで SQL 処理とデータ保存を行います。LOG・TAG の 時系列入力に加え、TRANSACTION の関係型データ変更、LOOKUP・VOLATILE の参照データや状態管理も、 各テーブルの特性に合った経路で処理します。 ```text クライアント: machsql または SDK │ 入力・クエリ要求 ▼ Machbase DBMS サーバー SQL 解析と実行計画 テーブル別ストレージ・インデックスアクセス メモリバッファとバックグラウンド処理 │ ▼ テーブルタイプに応じた保存データ ``` この図は役割を示す概念図です。すべての要求が同じ保存経路を通ることや、API 呼び出し直後に ディスクへ書き込まれることを意味しません。 ### Cluster Edition の構造 Cluster Edition は複数ノードで役割を分担します。通常のアプリケーション SQL 接続は Broker を経由し、 Warehouse が時系列データを保存してクエリを実行します。Coordinator はクラスターメタデータと ノード状態、Lookup は参照データ処理、Deployer はデプロイとノード管理を担当します。 複数グループへの分散はスループットと容量を分担するため、同一グループ内の複製は障害に備えるためです。 ノードを追加しても、すべてのクエリが同じ比率で高速化したり、すべての障害を自動回復できたりするわけではありません。 構成別の機能差は [Edition の概念](../concepts-edition/)、実際のデプロイと障害対応は [Cluster のインストール](../../installation-deployment-upgrade/cluster-edition/)と [Cluster の運用](../../operations-configuration-recovery/cluster/)で確認します。 ### 入力とクエリの流れ 入力は、対象テーブル・列の確認、値の変換と検証、データの転送・保存という段階で考えられます。 SQL と Append API は処理結果の確認方法が異なるため、アプリケーションは選択した経路の エラー処理と完了条件に従います。 クエリは、SQL 解析と実行計画の作成、対象データへのアクセス、条件評価と集計・結合・ソート、 結果の返却という処理で構成されます。常に同じ順序でデータを処理するわけではなく、 実際の実行計画によってアクセス順序は変わります。 ## 列指向ストレージと圧縮 ### 行指向と列指向 行指向ストレージは同じ行の値をまとめて扱い、列指向ストレージは同じ列の値をまとめて扱います。 次の図は両者の概念を比較する例で、実際のファイル配置そのものではありません。 ```text 論理的な行: (時刻1, センサーA, 23.1) (時刻2, センサーA, 23.5) (時刻3, センサーB, 18.0) 行指向: [時刻1, センサーA, 23.1] [時刻2, センサーA, 23.5] ... 列指向: [時刻1, 時刻2, 時刻3] [センサーA, センサーA, センサーB] [23.1, 23.5, 18.0] ``` Machbase の LOG・TAG 時系列ストレージは、列単位のアクセスと圧縮を利用します。多数の行から 一部の列だけを読む分析では、読み出すデータ量を削減できます。ただし温度平均のクエリでも、 センサー・時刻条件があれば、その評価に必要なデータも読みます。 行指向システムもインデックスやパーティションで必要な範囲だけを読めます。行指向は常に全行を読み、 列指向は常に速いと決めつけず、読む行数・列数とアクセス経路を確認してください。TRANSACTION の 関係型ストレージや LOOKUP・VOLATILE のメモリ特性も、LOG・TAG と同じ構造として解釈してはいけません。 ### 圧縮が効果的な条件 同じ列には同じ型の値が集まり、センサー値や時刻には繰り返しや類似パターンが現れることがあります。 これらは圧縮に有利です。一方、ノイズの大きな値、不規則な文字列、入力順序が混在するデータでは 結果が異なる場合があります。 時系列の時刻は必ずしも単調増加しません。遅れて到着する計測値や複数収集元の入力が混在するためです。 特定の圧縮方式や圧縮率を前提にせず、型、値の分布、入力順序、設定に応じて実際の圧縮率と性能を測定します。 ### パーティションと読み出し範囲 パーティションはデータを管理可能な部分に分割する単位です。検索条件と保存された範囲情報を使って 無関係な部分を読み飛ばすと、読み出しを削減できます。これをパーティションプルーニング (partition pruning)と呼びます。 LOG・TAG の保存単位は、ユーザーが指定する1日・1か月と一致するとは限りません。タグ・軸の条件、 データ分布、テーブル別の保存構造で実際のアクセス範囲は変わります。時間条件があるだけで 必要なデータしか読まないと判断せず、実行計画と測定結果を確認します。 ## インデックスの基本原理 インデックスは条件に一致するデータを見つけるアクセス経路です。対象が全体の一部なら有効ですが、 大半の行を読む集計では別の経路が有利な場合があります。インデックスには保存領域と、 入力・変更時の維持コストも必要です。 | テーブルタイプ | アクセス経路を考える基準 | |---|---| | TAG | タグ名と時間・距離軸の範囲 | | LOG | `_arrival_time` 条件と対応する検索インデックス | | TRANSACTION | PRIMARY KEY、UNIQUE、一般インデックス | | LOOKUP・VOLATILE | メモリ上のキーと対応するセカンダリインデックス | 「全センサーの1か月平均」と「センサー A の直近1分の値」では、読むデータの比率が異なります。 同じテーブルでも同じ性能は期待できません。結合では各入力の行数と結合条件も重要です。 対応インデックスと制約は[スキーマオブジェクトの定義](../../data-modeling-table-design/schema-objects-definition/)、 測定と調整は[インデックスのチューニング](../../performance-tuning/index-tuning/)で確認します。 ## キャッシュと実行計画 ### SQL の実行過程 サーバーは SQL 構文、型、オブジェクトを確認し、条件とインデックスなどから実行可能なアクセス経路を 決めてデータを処理します。実行計画はその処理方法を表します。計画を作るコストと、 計画に従ってデータを読むコストは異なります。 ### 実行計画の再利用と PVO Cache PVO Statement Cache は、再利用できる SQL の解析・検証・最適化結果と実行計画を再利用し、 準備処理の繰り返しを削減します。結果の行を保存するキャッシュではないため、計画を再利用しても データの読み出しと条件評価は必要です。 Min-Max Cache のように保存データの範囲情報を使うキャッシュは、読み出し対象を減らすためのものです。 実行計画キャッシュとデータアクセス用キャッシュを混同しないでください。どのキャッシュを増やすかは、 ヒット率とメモリ使用量を確認して判断します。 ### EXPLAIN による実行計画の確認 次の例は、[データモデルの概念](../concepts/#time-model-arrival-time)で作成した `sensor_values` テーブルを使用します。 ```sql EXPLAIN SELECT AVG(value) FROM sensor_values WHERE name = 'temp_sensor_01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD') AND time < TO_DATE('2026-07-03', 'YYYY-MM-DD'); ``` 実行計画でデータアクセスと条件適用を確認します。計画があるだけでは実際の応答時間やディスク読み出し量は 分からないため、代表データで実行時間も測定します。キャッシュが空の初回実行と再利用時の条件を 区別すると、結果を解釈しやすくなります。 PVO Cache のヒット・削除統計は `V$PVO_CACHE_STAT`、キャッシュ済み SQL は `V$PVO_CACHE_LIST` で 確認します。設定と診断は[キャッシュとメモリのチューニング](/ja/dbms/performance-tuning/cache-tuning-memory/#pvo-cache) を参照してください。 --- title: "2.3 主要機能と用語の区別" url: https://docs.machbase.com/ja/dbms/core-concepts/features-concepts/ language: ja kind: page --- # 2.3 主要機能と用語の区別 Machbase DBMS の長期データ運用に必要な ROLLUP、Retention Policy、Backup・Restore・Mount の 役割と選択基準を説明します。作成構文と運用手順は各機能の詳細文書で扱います。 元データは個々のイベントや計測値の再分析に、集計は多数の元データを要約した繰り返しクエリに使います。 保持ポリシーは何をいつ削除するかを決め、バックアップは障害後の復旧に必要なデータを用意します。 これらを区別すると、集計があるから必要な元データを削除する、複製があるからバックアップを省く、 といった誤りを避けられます。 - **[ROLLUP 統計の役割](#role-statistics-rollup)** — 繰り返し集計のクエリコストを削減する方法 - **[Retention Policy の役割](#role-retention-policy)** — 期間に応じてデータを自動削除する方法 - **[Backup・Restore・Mount の関係](#concepts-backup-restore-mount)** — 保護、復旧、参照の目的の区別 ## ROLLUP 統計の役割 TAG の長期間のデータを毎回元の行から集計すると、クエリ範囲が広がるほど処理コストも増えます。 ROLLUP は、時間軸 TAG の指定した数値列などを区間ごとに集計し、繰り返しクエリに使う機能です。 集計対象の列と集計方式は ROLLUP の定義で決まります。 基本 ROLLUP は秒(SEC)、分(MIN)、時間(HOUR)の階層を構成します。テーブル作成時に `WITH ROLLUP` を指定するか、通常の `CREATE ROLLUP` で必要な周期と条件を指定できます。 生成されるオブジェクト名や内部保存構造に依存せず、公開された ROLLUP SQL で管理してください。 ### 選択基準 | クエリパターン | 選択 | | --- | --- | | 長期間の分・時間単位の統計を繰り返し取得 | 基本 ROLLUP を検討 | | 集計周期やフィルター条件を指定 | 周期・条件を指定する通常の ROLLUP を検討 | | 独自の集計 SELECT の結果を別の TAG に保存 | Standard Edition の Custom ROLLUP を検討 | | 最初・最後の値が必要 | 拡張 ROLLUP を検討 | | 元の値のクエリが中心、または集計頻度が低い | ROLLUP なしで開始して実行時間を測定 | ROLLUP は元データの代わりとなる保持ポリシーではありません。元データの保持期間は Retention Policy で 別途設計し、TAG データを変更した場合は、その範囲の ROLLUP 再構築が必要かも確認します。 ### 集計結果の解釈 集計すると情報の解像度が下がります。1分平均だけでは、その1分間の瞬間的な異常値や個々の計測順序を 復元できません。最大・最小値を併せて保持すれば範囲は分かりますが、元の情報がすべて残るわけではありません。 複数区間の平均をさらに平均すると、全体平均と異なる場合があります。2件の平均が10、8件の平均が20なら、 全体平均は `(2 × 10 + 8 × 20) / 10 = 18` であり、2つの平均の単純平均15ではありません。 再集計には合計と有効件数などの必要な統計を使い、ROLLUP の対応クエリ関数に従います。 ROLLUP 処理は元データの入力と別に進むため、最新の元データと集計が反映される時点は異なることがあります。 遅延到着や値の補正がある場合は、元データの範囲、集計の進行状態、再構築の必要性を併せて確認します。 作成構文、クエリ関数、再構築手順は [TAG・ROLLUP の利用](/ja/dbms/tag-rollup-usage/)を参照してください。 ## Retention Policy の役割 Retention Policy は、LOG または TAG で保持期間を過ぎたデータを所定の周期で削除します。 データが流入し続けるテーブルの保存領域を、管理者が手動削除を繰り返さずに管理するために使います。 | 要件 | 選択 | | --- | --- | | 一定期間を過ぎたデータを継続的に自動削除 | Retention Policy | | 誤入力した範囲を直ちに削除 | テーブルタイプが対応する `DELETE` | | 対応テーブルの全データを削除 | `TRUNCATE TABLE` | Retention を適用しても、すべての古いデータが直ちに消えるわけではありません。実行周期、 対象テーブルのサポート範囲、実際の削除状態を確認します。LOOKUP、VOLATILE、TRANSACTION の データライフサイクルは、各テーブルが対応する明示的な DML で管理します。 保持期間は入力量とともに必要な保存容量を決めます。毎秒の入力件数に保持秒数を掛けると元の行数を 概算できますが、実際のディスク容量は型、圧縮、インデックス、複製、バックアップにも左右されます。 元データを削除する前に、集計の範囲・保持期間と、監査・再分析に必要な解像度を確認します。 ROLLUP を作成しても、元データの保持期間は自動的には変わりません。 ポリシーの作成・適用・解除構文と運用点検は、 [データ保持ポリシー](/ja/dbms/operations-configuration-recovery/policy-data-retention/)を参照してください。 ## Backup・Restore・Mount の関係 3つともバックアップデータに関わる機能ですが、結果は異なります。 | 機能 | 目的 | 運用サーバー | 結果 | | --- | --- | --- | --- | | Backup | 復旧用コピーの作成 | 稼働中に実行可能 | 別のパスにバックアップを作成 | | インスタンス Restore | バックアップからインスタンスを復旧 | オフライン手順が必要 | 運用データベースを復旧 | | Mount | バックアップ内容を読み取り専用で確認 | 稼働中に実行可能 | 別名でバックアップを検索 | インスタンスの復旧とは別に、論理データベースを復旧する `RESTORE DATABASE` SQL もあります。 稼働中のサーバーで実行するため、オフラインのインスタンス復旧とは対象と手順を区別します。 Backup の成功だけでは復旧手順を検証したことになりません。対応 Edition で Mount による内容確認、 または隔離環境での Restore を実施します。バックアップパスの権限と保持周期も管理してください。 Mount はバックアップを運用データへ戻す処理ではなく、マウントしたデータには書き込めません。 Restore と Mount は Standard Edition の機能なので、Cluster ではその Edition のバックアップ・障害復旧手順を確認します。 運用計画では、許容するデータ損失期間(RPO)とサービス復旧までの許容時間(RTO)を決めます。 前者はバックアップ・複製間隔、後者は復旧するデータ量と実際のリストア時間を検討する基準です。 特定の Edition やバックアップ周期だけで両方の目標が保証されるわけではありません。 誤った削除も複製先に反映されることがあるため、複製とバックアップの目的を区別します。 コマンド、権限、Edition 別サポート、復旧順序は [バックアップ・リストア・マウント](/ja/dbms/operations-configuration-recovery/backup-restore-mount/)を参照してください。 複数の論理データベースを運用する場合は、 [複数データベースの運用](/ja/dbms/operations-configuration-recovery/multi-database/)も確認します。 ## 入力経路の比較 小さな SQL 演習には `INSERT`、アプリケーションの継続収集には対応 SDK の Append、ファイルの 読み込みには `machloader` などを検討します。対応テーブル、入力形式、失敗の確認方法が異なるため、 名前が似ているだけでツールを置き換えることはできません。 SQL、SDK、ファイル入力ツールの選択基準は、 [データの入力とエクスポート](/ja/dbms/development-tools-integration/data-input-load-export/#machloader-vs-csvimport-csvexport-tagmetaimport) を参照してください。 --- title: "2.4 Edition の概念" url: https://docs.machbase.com/ja/dbms/core-concepts/concepts-edition/ language: ja kind: page --- # 2.4 Edition の概念 Edition はデプロイ構成と機能のサポート範囲を決定します。Standard は単一サーバーから始める構成、 Cluster は複数ノードで保存と処理を分担する構成です。現在のデータサイズだけでなく、必要な SQL 機能、 増加率、障害対応、運用体制を考慮して選びます。 ## Standard Edition と Cluster Edition の違い ### Standard Edition 1台の DBMS サーバーで SQL 処理とデータ保存を行います。分散ノード間のデプロイや通信を管理する 必要がなく、開発や単一サーバー運用の開始に適しています。TRANSACTION テーブルや Restore・Mount など、 Standard 専用機能が必要かも確認します。 単一サーバー構成だからといって、データ量が小さい必要はありません。入力量、クエリ負荷、保持期間が サーバーの CPU・メモリ・ストレージの容量に収まるかを測定して判断します。 ### Cluster Edition Coordinator、Deployer、Broker、Warehouse、Lookup の各ノードが役割を分担します。 | ノードタイプ | 役割 | |---|---| | Coordinator | クラスターメタデータとノード状態の管理 | | Deployer | パッケージの配布とノード管理 | | Broker | アプリケーションの SQL 接続とクエリ分配 | | Warehouse | 時系列データの保存とクエリ実行 | | Lookup | クラスターの参照データ処理 | 通常の SQL アプリケーションは Broker に接続します。管理ツールの接続先とポートは役割別に異なるため、 SQL 接続先と管理接続先を区別します。 複数の Warehouse グループにデータを分散することと、同じグループ内でデータを複製することは目的が異なります。 分散は容量・スループットの拡張、複製は障害対応に使います。ノード数、複製状態、クライアントの再接続、 障害時の運用手順をまとめて設計する必要があります。 ### 機能のサポート差 | 確認項目 | Standard Edition | Cluster Edition | |---|---|---| | 主なデプロイ構成 | 単一 DBMS サーバー | 役割を分担する複数ノード | | TRANSACTION テーブル | サポート | 非サポート | | Restore・Mount | サポート | 非サポート | | 容量・処理の拡張 | サーバーリソースとストレージ構成の拡張 | 分散グループとノード構成の拡張 | | 障害対応の設計 | バックアップ・復旧手順、サーバー運用計画 | ノード・グループの複製と状態、接続・復旧手順 | LOG・TAG・LOOKUP・VOLATILE、ROLLUP、Retention などの共通機能も、DML・DDL・運用の細かい制約が すべて同じとは限りません。全体のサポート範囲は [Edition 別サポート](../../reference/support-scope-constraints/edition/)と [テーブルタイプ別サポート](../../reference/support-scope-constraints/table-types-type/)で確認します。 ### 選択基準 1. 必須機能を確認します。TRANSACTION や Restore・Mount が必要なら、まず Standard のサポート範囲を確認します。 2. 代表的な入力とクエリを実行します。データ型、同時接続数、クエリ範囲、保持期間を実業務に近づけ、 単一サーバーの余力を確認します。 3. データ増加率と障害要件を考慮します。単一サーバーを超える分散が必要なら、Cluster のネットワーク、 複製、ノード運用コストも評価します。 4. 障害シナリオを試験します。ノード監視があることと無停止で復旧できることは別です。 復旧時間とアプリケーションの再接続・再試行動作を確認します。 運用中の Edition 変更も、サーバー数を増やすだけの作業ではありません。使用中の SQL・SDK と、 データ移行・バックアップ・復旧方法の互換性を先に確認します。 ## 関連文書 - [ストレージと実行の構造](../storage-execution-architecture/)で処理の流れを説明します。 - [インストール・デプロイ・アップグレード](../../installation-deployment-upgrade/)でデプロイ手順を説明します。 - [バージョンと互換性](../../reference/support-scope-constraints/compatibility-version/)でバージョン別のサポート範囲を確認します。 - [関係型業務モデルと時系列モデル](../concepts/#differences-rdbms)でデータモデルの選択基準を説明します。 --- title: "3. インストール、デプロイ、アップグレード" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/ language: ja kind: section --- # 3. インストール、デプロイ、アップグレード 本章ではMachbase DBMS 8.7.0をインストールし、データを入力・検索できる状態か確認します。 新しいサーバーの準備と、既存データを保持するアップグレードでは出発点が異なります。 まず必要な機能とデプロイ環境を決め、状況に合う手順を選択します。 第2章のデータモデルとEditionの違いはインストールにも影響します。TRANSACTIONテーブルやRestore・Mountが 必要ならStandard Editionのサポート範囲を確認します。分散保存とレプリケーションが必要なら、Clusterの ノードの役割、ネットワーク、障害対応も設計します。 ## インストール経路の選択 | Edition | デプロイ構造 | 選択時の確認事項 | |---|---|---| | Standard Edition | 1つのDBMSサーバーがSQL処理と保存を実行 | 必要な機能と入力・検索・保管の負荷をサーバーリソースで処理できるか | | Cluster Edition | Coordinator・Deployer・Lookup・Broker・Warehouseの役割を分離 | 分散グループ、レプリケーション、通信経路、ノード運用手順をまとめて準備できるか | 単一サーバーが小規模データしか扱えないという意味ではありません。必要な保存容量と性能を代表データで 測定して判断します。一方、Clusterもノード数を増やせば全クエリが比例して速くなるわけではありません。 詳しい選択基準は [Editionの違い](/ja/dbms/core-concepts/concepts-edition/#differences-standard-edition-cluster)を参照してください。 ### インストール前に区別する対象 | 対象 | 意味 | 確認例 | |---|---|---| | 配布パッケージ | 実行ファイル、ライブラリ、サンプル設定 | バージョン・Edition・OS・CPUアーキテクチャー | | インストールホーム | 1つのサーバーまたはノードが使用する実行・設定パス | `MACHBASE_HOME`、`conf/machbase.conf` | | データ保存パス | DBMSが実データを読み書きする場所 | `DBS_PATH`、空き容量、アクセス権 | | サーバーインスタンス・ノード | その設定で実行されるDBMSプロセス | 起動状態、ログ、接続ポート | | 論理データベース | 接続後にSQLオブジェクトを作成・使用する空間 | 現在のデータベース、ユーザー・権限・テーブル | パッケージの展開、新規インスタンスのデータベース作成、サーバー起動、テーブル作成は別々の段階です。 既存データがあるホームに新規インストール用の初期化コマンドを実行しないでください。 インストールホームと実際のデータパスが異なる場合もあるため、バックアップ・アップグレード前に両方を確認します。 SQLの論理データベースはインストールホームとは別の概念です。 複数データベース運用時の選択・作成・権限は [マルチデータベース運用](/ja/dbms/operations-configuration-recovery/multi-database/)で説明します。 ## インストール手順 ### Standard Edition 1. [インストール前の準備](./pre-install-preparation/)でパッケージ、サーバーアカウント、リソース、ポートを確認します。 2. OSに合う手順で専用ホームと環境変数を準備します。 - [Linux — Tarballインストール](./standard-edition/#linux-tarball) - [Linux — Dockerインストール](./standard-edition/#linux-docker) - [Windows — パッケージインストール](./standard-edition/#windows-package) 3. 設定とデータパスを確認し、別途ライセンスを使用する場合は初回起動前に [ライセンスのインストール](./pre-install-preparation/#license)を行います。 4. 選択した手順に従い、新しいデータベースを作成してサーバーを起動します。 5. [インストール検証チェックリスト](./validation-checklist/)でプロセス・ポート・接続・バージョン・ ライセンスと、少量データの入力・検索を確認します。 コンテナーでもパッケージのバージョン、データボリューム、実行アカウントの書き込み権限を確認します。 コンテナーの起動とDBMSの初期化・起動の関係はイメージにより異なるため、該当する手順に従います。 ### Cluster Edition 1. [インストール前の準備](./pre-install-preparation/)と [クラスター環境の準備](./cluster-edition/#preparation-environment-cluster-edition)を確認します。 2. ノード別のホスト、ホーム、SQL・管理・ノード間通信のポートとWarehouseレプリケーショングループを決めます。 3. 使用するパッケージとライセンスを準備し、デプロイ方式を選択します。 - [machclusterctlによるデプロイ](./cluster-edition/#machclusterctl): 設定ファイルでデプロイし、実行計画を確認 - [手動インストール](./cluster-edition/#manual-machcoordinatoradmin): 管理ツールで段階的に登録・起動 4. ノードの役割に応じた状態とレプリケーション構成を確認し、BrokerへSQLで接続します。 5. [インストール検証チェックリスト](./validation-checklist/)でデータの入力・検索とグループ内の レプリケーション状態を区別して確認します。 SQL接続の成功と全レプリカの正常状態は別の確認です。異なるWarehouseグループが必ず同じデータを 持つわけでもありません。障害対応は[Cluster運用](/ja/dbms/operations-configuration-recovery/cluster/)で 続けて確認してください。 ## アップグレード 既存システムには[アップグレード](./upgrade/)の手順を使用します。新パッケージの実行可否だけでなく、 データファイル、SQL・SDK、設定・ライセンス、バックアップ・復旧経路の互換性を確認します。 本番設定を新パッケージのサンプルで上書きしたり、実行ファイルを交換しただけで完了と判断したりしないでください。 アップグレード前の基準測定値とバックアップを確保し、隔離環境で復旧に必要な時間も確認します。 旧バージョンへ戻せるかの判断には、バイナリだけでなく旧バージョンで読めるデータと設定が必要です。 ## 次のステップ インストール検証は本番準備の始まりです。まず[クイックスタート](/ja/dbms/getting-started/quick-start/)で SQLの流れを学び、[テーブルタイプの選択とスキーマ設計](../data-modeling-table-design/)で実データを モデル化します。本番投入前に専用アカウント、収集エラー処理、保管・バックアップ、代表負荷テスト、 監視メトリクスを準備します。 [観測と診断](/ja/dbms/operations-configuration-recovery/diagnosis-observability/)と [性能チューニングの進め方](/ja/dbms/performance-tuning/performance-approach/)で、その過程を案内します。 --- title: "3.1 インストール前の準備" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/pre-install-preparation/ language: ja kind: page --- # 3.1 インストール前の準備 インストール前の準備では、実行ファイルのコピー先だけでなく、データの保存先、サーバーの実行アカウント、 クライアントの接続経路を確定します。パッケージとOSの互換性を確認してから、ストレージ、ネットワーク、 ライセンスを準備します。サポート範囲は提供されたパッケージのリリース情報と技術サポートポリシーで判断します。 ## 先に決めるデプロイ情報 | 項目 | 決定事項 | 必要な理由 | |---|---|---| | Editionとバージョン | StandardまたはCluster、サーバー・SDKバージョン | 使用するSQL機能とデプロイ方式の決定 | | OSアカウント | サーバー実行アカウントとファイル所有者 | 設定・データ・ログのパスのアクセス権を合わせる | | インストールホーム | 実行ファイルと設定がある絶対パス | 管理コマンドが操作するインスタンスを識別 | | データパス | 実際の`DBS_PATH`、ファイルシステム、空き容量 | 再起動・アップグレード時に保持するデータを識別 | | 接続情報 | サーバーアドレス、SQLポート、管理ポート、許可クライアント | ポート競合と誤ったインスタンスへの接続を防止 | | 復旧とライセンス | バックアップ保存先、復元手順、使用ライセンス | 障害対応と運用範囲の確認 | OSアカウント`machbase`とDBユーザー`SYS`は異なります。前者はプロセス・ファイルの権限、後者は SQL接続とデータベース操作の権限を決めます。サーバー起動が成功しても、ファイル権限やSQL権限が 適切でなければロード・バックアップなどが失敗する場合があります。 | 項目 | 説明 | |------|------| | [インストール前の要件](/ja/dbms/installation-deployment-upgrade/pre-install-preparation/#pre-install-requirements) | OSバージョン、ハードウェア最小要件、ネットワークポート | | [パッケージ構成の理解](/ja/dbms/installation-deployment-upgrade/pre-install-preparation/#package) | パッケージファイルの命名規則、ディレクトリ構造、主な実行ファイル | | [ライセンスのインストール](/ja/dbms/installation-deployment-upgrade/pre-install-preparation/#license) | license.datの配置方法、ライセンス状態の確認方法 | --- ## インストール前の要件 ### OSとパッケージ OSの種類とCPUアーキテクチャーはパッケージの表記と一致する必要があります。対応OSと最小バージョンは リリースごとに変わる場合があるため、固定的なバージョン表ではなく、パッケージ付属のリリース情報で 確認してください。 ### システムリソース CPU、メモリ、ディスク、ネットワークの必要量は、入力レート、保持期間、インデックス、ROLLUP構成により 異なります。インストール領域だけでなく、予想される生データ、バックアップ、運用上の空き容量を含めて 算定し、実際のワークロードで容量とスループットを検証してください。秒間行数と保持期間から元の行数を 予測し、代表データをロードして行サイズ・圧縮・インデックスの実際の保存コストを測定します。 Clusterではレプリカ領域も含めます。同じディスクの別ディレクトリは、別の障害ドメインや独立した I/Oデバイスではありません。 ### デフォルトポート | ポート | 用途 | |------|------| | **5656** | SQLクライアント接続(Native TCP) | SQLクライアントポートの変更には、`$MACHBASE_HOME/conf/machbase.conf`の`PORT_NO`を設定します。 `MACHBASE_PORT_NO`環境変数も使用するため、サーバーを起動するシェルやサービスの環境変数も確認します。 変更したポートはクライアントにも明示し、実行中のサーバーに新しい環境変数が遡及適用されるとは考えません。 ファイアウォール環境では上記ポートの受信を許可する必要があります。Cluster EditionではCoordinatorの link/adminポートと、Broker、Warehouse、Deployerのポートも追加で開く必要があります。 ### システムカーネルパラメーター(Linux) Linuxへのインストールでは、事前に以下を確認します。 #### ファイルディスクリプターの上限 多数のファイルを同時に開くワークロードでは、ファイルディスクリプターの上限が低いとボトルネックになる 場合があります。デフォルトの上限はOSとアカウント設定によって異なるため、サーバー実行アカウントで確認します。 ```bash # 現在値を確認 ulimit -Sn ``` このインストール例は65535を使用します。上限がこれより小さい場合は`/etc/security/limits.conf`を 変更し、新しいログインセッションで適用を確認します。 ``` * hard nofile 65535 * soft nofile 65535 ``` サーバー実行アカウントで再ログインして値を確認します。サービスマネージャーからサーバーを起動する場合は、 そのサービスのファイルディスクリプター上限も別途確認します。 ```bash ulimit -Sn # 出力: 65535 ``` #### ポートの予約 MachbaseサービスのポートがOSの一時ポートの自動割り当てに使われないよう予約します。 この設定は、別プロセスによる同じポートの明示的な使用までは防止しません。 ```bash current=$(cat /proc/sys/net/ipv4/ip_local_reserved_ports) ports=5656 sudo sysctl -w net.ipv4.ip_local_reserved_ports="${current:+$current,}$ports" ``` 既存の予約ポートがある場合は上書きせず、カンマで区切って統合します。永続化するには `/etc/sysctl.conf`の`net.ipv4.ip_local_reserved_ports`項目と次の値を統合します。 ``` net.ipv4.ip_local_reserved_ports = 5656 ``` ### 時刻同期 時系列データを処理するため、サーバー時刻は正確である必要があります。NTPまたは`chrony`で システム時刻を同期してください。Cluster Editionは全ノードの時刻を合わせる必要があります。 ```bash # タイムゾーンを確認 ls -l /etc/localtime date ``` --- ## パッケージ構成の理解 ### パッケージファイルの命名規則 パッケージのファイル名はEditionに応じて次の形式です。 ``` machbase-EDITION-VERSION-OS-CPU-BIT-MODE.EXT ``` | 項目 | 説明 | 例 | |------|------|------| | EDITION | Editionの区分 | `SDK`、`cluster` | | VERSION | バージョン(Major.Minor.Fix.AUX) | `8.7.0.official` | | OS | オペレーティングシステム | `LINUX`、`WINDOWS` | | CPU | CPUアーキテクチャー | `X86` | | BIT | アーキテクチャーのビット数 | `64` | | MODE | ビルドモード | `release` | | EXT | 拡張子 | `tgz`(Linux)、`zip`またはインストーラー実行ファイル(Windows) | Standard EditionのLinux tarballは`machbase-SDK-...tgz`という名前で生成されます。 例: - Standard Edition: `machbase-SDK-8.7.0.official-LINUX-X86-64-release.tgz` - Cluster Edition: `machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz` マイナーバージョンが異なると、DBファイルやプロトコルの互換性が変わる場合があります。 Fixバージョン変更も含む実際のアップグレード経路は、対象リリースの互換性情報と [アップグレード手順](../upgrade/)で確認します。 ### インストールディレクトリの構造 tarballを展開すると、`$MACHBASE_HOME`配下に次の構造が作成されます。 ``` $MACHBASE_HOME/ ├── bin/ 実行ファイル ├── conf/ 設定ファイル(machbase.confなど) ├── dbs/ データ保存領域 ├── doc/ ライセンス文書 ├── include/ C/C++ヘッダーファイル ├── install/ Makefile用mkファイル ├── lib/ 共有ライブラリ ├── package/ Cluster Editionの追加パッケージパス ├── sample/ サンプルファイル ├── trc/ サーバーログとトレースファイル ├── tutorials/ チュートリアル ├── utility/ ユーティリティファイル └── 3rd-party/ Grafanaプラグインなど ``` ### 主な実行ファイル | 実行ファイル | 説明 | |-----------|------| | `machbased` | サーバーデーモン | | `machadmin` | サーバー管理(起動・終了・DB作成) | | `machsql` | CLIクエリツール | | `machloader` | 大容量ファイルのロード・抽出ツール | | `csvimport` | CSVファイルのインポート | | `csvexport` | CSVファイルのエクスポート | | `tagmetaimport` | TAGメタデータの一括登録 | Cluster Editionパッケージには`machcoordinatoradmin`、`machdeployeradmin`などの管理ツールが追加されます。 `machclusterctl`は、そのツールを含めてビルドされたパッケージで使用できます。 ### 設定ファイル `$MACHBASE_HOME/conf/`配下にはEdition別のサンプル設定があります。 ```bash ls $MACHBASE_HOME/conf/ # machbase.conf # machbase.conf.sample.standard # machbase.conf.sample.edge # machloader.conf.sample ``` 実際に使用するファイルは`machbase.conf`です。Standard fullパッケージはビルド時に `machbase.conf.sample.standard`をコピーし、`machbase.conf`を含めます。実ファイルがないパッケージでは、 Editionに合うサンプルをコピーして変更します。 Standard/Edgeのサンプルには、TRANSACTIONの書き込み競合と耐久性ポリシーを制御する `TRANSACTION_BUSY_TIMEOUT_MS`、`TRANSACTION_SYNCHRONOUS`、`TRANSACTION_JOURNAL_MODE`が含まれます。 TRANSACTIONテーブルを使用する場合はまずデフォルト値を使用し、同時書き込みと耐久性の要件を検討してから 調整します。 --- ## ライセンスのインストール ライセンスファイルがない場合、サーバーはデフォルトの`COMMUNITY`ライセンス情報を使用します。 インストール前に、この範囲が予定する機能・容量に合うか確認します。別のライセンスが必要な環境では、 初回サーバー起動前にファイルを準備します。起動できるだけで本番に必要なライセンス条件を満たしたと 判断しないでください。 ### ライセンス状態の確認 インストールしたライセンスの状態と制限違反の有無は、`V$LICENSE_INFO`の`VIOLATE_STATUS`と `VIOLATE_MSG`で確認します。ライセンスファイルの本文は変更しないでください。 ### インストール方法 #### 方法1: ファイルのコピー(サーバー起動前) `license.dat`を`$MACHBASE_HOME/conf/`にコピーします。サーバー起動時に自動認識されます。 ```bash cp license.dat $MACHBASE_HOME/conf/license.dat ``` #### 方法2: machadminコマンド `machadmin`でライセンスファイルを検証してインストールします。サーバーが実行中の場合は、 ライセンス再読み込み要求も送信します。 ```bash machadmin -t /path/to/license.dat ``` #### 方法3: SQLクエリ(サーバー実行中) サーバーが実行中の場合は、machsqlのクエリでインストールします。 ```sql ALTER SYSTEM INSTALL LICENSE = '/path/to/license.dat'; ``` ### インストールの確認 #### machadminで確認 ```bash machadmin -f ``` #### V$LICENSE_INFOビューの検索 ```sql SELECT ID, ISSUE_DATE, TYPE, CUSTOMER, VIOLATE_STATUS, VIOLATE_MSG FROM V$LICENSE_INFO; ``` `VIOLATE_STATUS`が0なら正常です。 machsqlでは次のコマンドでもライセンス情報を確認できます。 ```sql SHOW LICENSE; ``` --- title: "3.2 Standard Editionのインストール" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/standard-edition/ language: ja kind: page --- # 3.2 Standard Editionのインストール Standard Editionは1台のサーバーでSQL処理とデータ保存を実行します。インストールは、パッケージの準備、 サーバー実行環境の設定、データベース作成、ライセンス確認、起動、SQL検証の順に進めます。 単一サーバーでも少量データだけを扱うわけではなく、スループットと保持期間に必要なリソースを 実際のワークロードで確認する必要があります。 ## インストール経路 OSに応じて次の経路から選択します。 | OS | インストール方式 | リンク | |----|-----------|------| | Linux | Tarball (.tgz) | [Tarballインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux-tarball) | | Linux | Dockerコンテナー | [Dockerインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux-docker) | | Windows | ZIPまたはインストーラー実行ファイル | [Windowsパッケージインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#windows-package) | 事前に[Linux環境の準備](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux-preparation-environment-linux)または [Windows環境の準備](/ja/dbms/installation-deployment-upgrade/standard-edition/#windows-preparation-environment-windows)を確認してください。 --- ## Linuxへのインストール LinuxでStandard Editionをインストールする方法は2つあります。 | 方式 | 適している状況 | |------|------------| | [Tarballインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux-tarball) | 実サーバー環境、データディレクトリを直接管理する場合 | | [Dockerインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#linux-docker) | 開発・テスト環境、すぐに起動する必要がある場合 | Tarballのインストールは[インストール前の準備](../pre-install-preparation/)を先に完了します。 DockerではDocker Engineとボリューム・ポートの権限を準備してください。 --- ### Linux環境の準備 ファイルディスクリプター上限、時刻同期、ポート予約、ファイアウォール設定はEdition共通です。 [インストール前の準備](../pre-install-preparation/)でサーバー実行アカウントと運用環境に合わせて 設定してから、次の手順に進みます。 --- ### Tarballインストール Linux環境にtarball(.tgz)を展開してStandard Editionをインストールする手順です。 #### 1. ユーザーの作成 Machbase専用のOSユーザーを作成します。 ```bash sudo useradd -m -d /home/machbase machbase sudo passwd machbase ``` 以降は`machbase`アカウントでログインして作業します。 #### 2. パッケージのダウンロードと展開 例ではパッケージを`/home/machbase/packages/`にダウンロード済みとします。以下のパッケージ名を 実際の配布物に置き換え、インスタンスがまだない新しいインストールディレクトリに展開します。 既存インストールの更新は[アップグレード](../upgrade/)手順を使用します。 ```bash machbase_package=/home/machbase/packages/machbase-SDK-8.7.0.official-LINUX-X86-64-release.tgz test -r "$machbase_package" && mkdir /home/machbase/machbase_home && tar zxf "$machbase_package" -C /home/machbase/machbase_home && cd /home/machbase/machbase_home ``` 展開後にディレクトリ構造を確認します。 ```bash ls -l # bin/ conf/ dbs/ doc/ include/ lib/ trc/ ... ``` #### 3. 環境変数の設定 `~/.bashrc`に環境変数を追加します。 ```bash export MACHBASE_HOME=/home/machbase/machbase_home export PATH="$MACHBASE_HOME/bin:$PATH" export LD_LIBRARY_PATH="$MACHBASE_HOME/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ``` 適用します。 ```bash source ~/.bashrc ``` #### 4. データベースの作成 `machadmin -c`は物理インスタンスのデータベースファイルを作成します。SQLの`CREATE DATABASE`で 論理データベースを追加する操作とは区別してください。実行前に`MACHBASE_HOME`、`conf/machbase.conf`、 実際の`DBS_PATH`が新規インストールの対象か確認します。既存データベースがあるというエラーの場合は、 削除・再作成せず、まず対象パスを確認します。 ```bash machadmin -c # Database created successfully. ``` #### サーバー起動前の設定とライセンス確認 `conf/machbase.conf`の`PORT_NO`と`DBS_PATH`を確認します。別途ライセンスを使用する場合は、 [ライセンスのインストール](../pre-install-preparation/#license)のファイルコピーまたは`machadmin -t`で インストールし、`machadmin -f`で確認してから起動します。 #### 5. サーバーの起動 ```bash machadmin -u # Machbase server started successfully. ``` プロセスの確認: ```bash machadmin -e ``` #### 6. 接続テスト `machsql`でサーバーに接続します。デフォルトの管理者アカウントは`SYS / MANAGER`です。 ```bash machsql # Machbase server address (Default:127.0.0.1) : # Machbase user ID (Default:SYS) # Machbase User Password : # MACHBASE_CONNECT_MODE=INET, PORT=5656 EDITION=STANDARD # Mach> ``` 簡単なテストを行います。 ```sql CREATE LOG TABLE install_check (id INTEGER, val DOUBLE); INSERT INTO install_check (id, val) VALUES (1, 3.14); SELECT id, val FROM install_check; DROP TABLE install_check; ``` `id=1`、`val=3.14`の1行が返り、最後のDROPが成功することを確認します。 `install_check`がすでに存在する場合は削除せず、未使用の実習用名に置き換えます。 #### サーバーの終了 インストール確認後、サーバーを停止する必要がある場合のみ実行します。 ```bash machadmin -s # Machbase server shut down successfully. ``` #### ポートの変更 デフォルトポート(5656)を変更するには、`$MACHBASE_HOME/conf/machbase.conf`の`PORT_NO`を変更するか、 環境変数を設定します。 ```bash export MACHBASE_PORT_NO=7878 ``` サーバーを終了した状態で設定を適用し、再起動します。この環境変数は現在のシェルだけに適用されるため、 サービスとして起動する場合はサービスの環境にも反映します。接続には `machsql -s 127.0.0.1 -P 7878 -u SYS`のように変更したポートを指定します。 --- ### Dockerインストール Dockerイメージではサーバーと実行環境をコンテナーとしてデプロイできます。開発・テスト環境でも、 ホストのDocker Engine、保存ボリューム、ポート、ファイルディスクリプター上限を準備する必要があります。 Dockerを事前にインストールしてください。デプロイチュートリアルは`machbase/machbase`イメージを使用します。 ソースからDockerイメージを直接ビルドした場合は、ローカルイメージ名(`machbase:latest`など)に置き換えます。 #### イメージの確認 ```bash docker pull machbase/machbase docker image ls machbase/machbase ``` #### コンテナーの実行 ```bash docker create \ --name machbase \ --ulimit nofile=65535 \ -p 5656:5656 \ -v /data/machbase:/home/machbase/machbase/dbs \ machbase/machbase ``` | オプション | 説明 | |------|------| | `-p 5656:5656` | ホストSQLポート:コンテナーSQLポートのマッピング | | `--ulimit nofile=65535` | コンテナー内のサーバーのファイルディスクリプター上限 | | `-v /data/machbase:...` | データディレクトリをホストに保持するボリュームマウント | データがコンテナーの書き込み層だけにあると、コンテナー削除時に一緒に削除されます。 実際のデータパスがボリュームに接続されているか確認し、ボリューム自体の削除やディスク障害に備えて バックアップも準備します。 `docker create`はまだサーバーを起動しません。`/data/machbase`にはコンテナーのサーバー実行アカウントが 書き込める必要があります。既存DBファイルがある場合は、バージョンとインスタンスが合うか確認します。 イメージの実バージョンと`MACHBASE_HOME`パスを確認し、本番では検証済みのイメージタグまたはダイジェストを 固定します。タグなしの公開イメージが常に8.7.0とは考えないでください。 別途ライセンスを使用する場合は、起動前に準備したファイルを次のようにコピーします。 ```bash docker cp /path/to/license.dat machbase:/home/machbase/machbase/conf/license.dat ``` 準備ができたらコンテナーを起動します。 ```bash docker start machbase ``` #### コンテナー状態の確認 ```bash docker ps docker logs machbase ``` #### 接続テスト ##### machsql(コンテナー内部) ```bash docker exec -it machbase machsql # Mach> ``` ##### ホストからの接続 ホストにmachsqlがインストールされている場合: ```bash machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER ``` #### コンテナーの終了と再起動 ```bash docker stop machbase docker start machbase ``` #### ライセンスのインストール 実行中にライセンスを更新する場合は、コンテナーにファイルをコピーしてからライセンスインストールコマンドを 実行します。コンテナーの設定ファイルとライセンスはデータボリュームとは別のため、コンテナー再作成時にも 再適用できるよう元のファイルを保持します。 ```bash docker cp /path/to/license.dat machbase:/tmp/license.dat docker exec machbase machadmin -t /tmp/license.dat docker exec machbase machadmin -f ``` --- ## Windowsへのインストール ### インストール前の確認 - **対応OS**: 提供されたWindowsパッケージのリリース情報で対応バージョンを確認します。 - **アーキテクチャー**: パッケージのビット数とOSのアーキテクチャーが一致する必要があります。 先に[Windows環境の準備](/ja/dbms/installation-deployment-upgrade/standard-edition/#windows-preparation-environment-windows)を 完了してください。 ### インストール方式 | 方式 | 説明 | |------|------| | [Windowsパッケージインストール](/ja/dbms/installation-deployment-upgrade/standard-edition/#windows-package) | インストールウィザードで環境変数とショートカットを作成 | --- ### Windows環境の準備 Windowsにインストールする前にファイアウォール設定を確認します。 #### ファイアウォールのポートを開く Machbaseが使用するポートを、Windowsファイアウォールの受信規則に追加します。 | ポート | プロトコル | 用途 | |------|---------|------| | 5656 | TCP | SQLクライアント接続 | ##### 設定方法 1. **コントロールパネル → Windows Defenderファイアウォール → 詳細設定**を開きます。 2. 左ペインの**受信の規則**を選び、右ペインで**新しい規則**をクリックします。 3. 規則の種類に**ポート**を選び、**次へ**をクリックします。 4. **TCP**を選び、**特定のローカルポート**に`5656`を入力して**次へ**をクリックします。 5. **接続を許可する**を選び、**次へ**をクリックします。 6. 接続を許可するネットワークプロファイル(**ドメイン**、**プライベート**、**パブリック**)だけを選び、**次へ**をクリックします。 7. 規則名(例: `Machbase`)を入力し、**完了**をクリックします。 規則の作成後、プロパティのリモートアドレス範囲も実際のクライアントアドレスに制限します。 リモート接続を使用しない環境では、受信許可規則は不要です。 ##### PowerShellで設定(管理者権限) GUIの代わりにPowerShellですばやく設定します。 ```powershell New-NetFirewallRule -DisplayName "Machbase SQL" -Direction Inbound -Protocol TCP -LocalPort 5656 -Action Allow ``` #### Visual C++再頒布可能パッケージ 実行にはVisual C++ Redistributableが必要です。インストーラーでは自動処理される場合がありますが、 問題が発生した場合はMicrosoft公式サイトから最新バージョンを手動インストールしてください。 --- ### Windowsパッケージインストール Windows版はZIPパッケージまたはインストーラー実行ファイルで提供されます。ZIPはアーカイブルートに `bin\`、`conf\`、`dbs\`、`trc\`などを含み、インストーラーはインストールパス配下に`machbase_home\`を 作成して環境変数と実行ショートカットを生成します。 #### インストール手順 1. Windows配布パッケージをダウンロードします。 2. ZIPパッケージの場合は、目的のインストールディレクトリに展開します。 ```cmd mkdir C:\machbase tar -xf machbase-SDK-8.7.0.official-WINDOWS-X86-64-release.zip -C C:\machbase ``` 3. インストーラーが提供された場合は実行します。開始画面が表示されたら**Next**をクリックします。 4. インストールパスを選びます。デフォルトは`C:\machbase-\`形式です。 変更が必要ならパスを修正して**Next**をクリックします。 5. インストールが進み、完了したら**Next** → **Close**をクリックします。 #### ZIPパッケージの初期化 ZIPを展開した場合は、コマンドプロンプトでそのディレクトリをインストールホームに指定します。 以下は`C:\machbase`へ新規インストールした例です。実際の設定ファイルとライセンスを先に確認し、 既存DBのない新規インスタンスだけで`-c`を実行します。 ```cmd set "MACHBASE_HOME=C:\machbase" set "PATH=%MACHBASE_HOME%\bin;%PATH%" machadmin.exe -c machadmin.exe -f machadmin.exe -u machadmin.exe -e ``` 上記の`set`は現在のウィンドウに適用されます。他のウィンドウやサービスから実行する場合も、 同じインストールホームと実行ファイルパスを使用する必要があります。インストーラーがすでにデータベースを 作成した場合は、ZIP用の作成コマンドを繰り返さないでください。 #### サーバーの起動と終了 インストーラーを使用すると、デスクトップとスタートメニューにショートカットが作成されます。 - **start Machbase**: `machadmin.exe -u`でサーバーを起動します。 - **stop Machbase**: `machadmin.exe -s`でサーバーを終了します。 - **machsql**: SQLコンソールを起動します。 #### コマンドライン接続 インストール後、コマンドプロンプトで`machsql`を実行してサーバーに接続します。インストーラーを使用した 場合は`<インストールパス>\machbase_home\bin`がシステムの`PATH`に追加されます。ZIPの場合は展開先の `bin\`を`PATH`に追加するか、フルパスで実行します。 ```cmd machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER ``` デフォルトの管理者アカウント: `SYS` / `MANAGER` #### インストールパスの構造 ZIPパッケージは展開先直下に`bin\`、`conf\`、`dbs\`、`trc\`などを配置します。 インストーラーはインストールパス配下の`machbase_home\`に同じ構成を作成します。 [パッケージ構成](/ja/dbms/installation-deployment-upgrade/pre-install-preparation/#package)を参照してください。 --- title: "3.3 Cluster Editionのインストールとデプロイ" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/cluster-edition/ language: ja kind: page --- # 3.3 Cluster Editionのインストールとデプロイ Cluster EditionはSQL接続、データ保存、レプリケーション、ノード管理を複数の役割に分けます。 インストール前に各役割をどのホストへ配置するか、どのポートと保存パスを使うかを決めます。 通常のSQL接続はBrokerへ、運用コマンドは該当する管理ノードへ送る必要があります。 ## ノードの役割 | ノード | 役割 | |------|------| | **Coordinator** | クラスターメタ情報の管理、ノード状態の監視 | | **Deployer** | パッケージの配布とノード初期化の中継 | | **Lookup** | 参照データと検索処理 | | **Broker** | SQLの解析とクエリの分配、クライアントの接続先 | | **Warehouse** | 実データの保存とクエリ実行 | 以下のYAML例は、3ホストにCoordinator 2台、Deployer 3台、Lookup 2台(master 1台、monitor 1台)、 Broker 2台、Warehouse 2台(1つのレプリケーショングループ)を配置します。 実際のノード数と配置は、可用性、スループット、障害時に残す必要がある容量に基づいて決めます。 ## デプロイ方式 | 方式 | 説明 | 適している場合 | |------|------|------------| | [machclusterctl](/ja/dbms/installation-deployment-upgrade/cluster-edition/#machclusterctl) | cluster.yamlによる自動デプロイ | 推奨。新規構築 | | [手動(machcoordinatoradmin)](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin) | Coordinatorコマンドによるノード登録・デプロイ | 細かい制御が必要な場合 | ## インストール手順 1. [Cluster Editionの構成概要](/ja/dbms/installation-deployment-upgrade/cluster-edition/#overview)を理解 2. [環境の準備](/ja/dbms/installation-deployment-upgrade/cluster-edition/#preparation-environment-cluster-edition)(SSH鍵、カーネルパラメーター、NTP) 3. パッケージ・パスと[ライセンス](../pre-install-preparation/#license)の適用方式を準備 4. デプロイ方式を選択してインストール・起動し、ライセンスを確認 5. [インストール検証](/ja/dbms/installation-deployment-upgrade/validation-checklist/) --- ## Cluster Editionの構成概要 役割を分離したCoordinator、Deployer、Lookup、Broker、Warehouseノードで構成されます。 各ノードの役割と相互関係を理解してからデプロイ計画を立ててください。 ### ノードの役割の詳細 #### Coordinator クラスターメタデータ、ノード登録、状態監視を担当します。Primary/Secondaryによる冗長化を検討してください。 稼働中のデータ処理経路と管理経路は分かれていますが、Coordinator障害時に全SQLの継続動作が保証される わけではありません。他ノードの状態とクライアントへの影響も確認し、検証済みの障害対応手順を使用します。 - 設定ファイル: `$MACHBASE_COORDINATOR_HOME/conf/machbase.conf` - 管理ツール: `machcoordinatoradmin` - 主なポート: `CLUSTER_LINK_PORT_NO`、`HTTP_ADMIN_PORT` デフォルトは`CLUSTER_LINK_PORT_NO=3868`、`HTTP_ADMIN_PORT=5779`です。本章の例では運用中の ポート競合を避けるため、Coordinatorのlink/adminポートに`5101`/`5102`を明示します。 #### Deployer Coordinatorの指示に従い、各ノードへパッケージを配布して初期化を中継します。 各ノードホストに1台ずつ配置するか、専用のデプロイサーバーで運用します。 - 管理ツール: `machdeployeradmin` #### Lookup 参照データと検索処理のためのノードです。構成に応じて`master`、`monitor`、`slave`の役割を指定します。 #### Broker クライアントのSQL要求を受け取り、解析して適切なWarehouseへ分配します。通常のアプリケーションは Brokerのアドレスに接続します。Warehouseへの直接接続はレプリケーション状態の比較など管理診断手順だけで 使用し、アプリケーションの接続経路と区別します。Brokerの冗長化を推奨します。 - クライアント接続ポート: デフォルト5656 #### Warehouse 実データを保存してクエリを実行します。同じグループのWarehouse間でデータを複製し、高可用性を提供します。 グループごとに2台以上を推奨します。 ### 構成例 ``` [クライアント] │ (SQL, 5656) ▼ [Broker ×2] ────────────────────────────────────────── │ (クエリ分配) ├─► [Warehouse group1-node1] ◄──レプリケーション──► [Warehouse group1-node2] └─► [Warehouse group2-node1] ◄──レプリケーション──► [Warehouse group2-node2] [Coordinator Primary] ◄──HA──► [Coordinator Secondary] │ (メタ情報管理、ノード監視) [Deployer] │ [Lookup master / monitor] ``` ### Editionの比較 Standard Editionとの詳細比較は [Editionの違い](/ja/dbms/core-concepts/concepts-edition/#differences-standard-edition-cluster)を参照してください。 --- ## Cluster Editionのインストール環境の準備 デプロイ前に全ノードで次の環境を準備します。 ### ファイルディスクリプターの上限 全ノードに次の設定を適用します。 ```bash sudo vi /etc/security/limits.conf ``` ``` * hard nofile 65535 * soft nofile 65535 ``` サーバー実行アカウントで新しいログインセッションを開き、確認します。サービスマネージャーから起動する場合は、 サービス自体のファイルディスクリプター上限も確認します。 ```bash ulimit -Sn # 65535 ``` ### OSユーザーの作成 全ノードに`machbase`アカウントを作成します。 ```bash sudo useradd -m machbase --home-dir /home/machbase sudo passwd machbase ``` ### SSH鍵認証 `machclusterctl`を使用する場合は、デプロイサーバーから全ノードへパスワードなしでSSH接続できる必要があります。 ```bash # デプロイサーバーでSSH鍵を生成(既存なら省略) ssh-keygen -t rsa -b 4096 # 各ノードに公開鍵を登録 ssh-copy-id machbase@192.168.1.11 ``` 登録後、パスワードなしで接続できるか確認します。 ```bash ssh machbase@192.168.1.11 'hostname' ``` ### ネットワークのカーネルパラメーター 以下はネットワークバッファの調整例であり、全サーバーに適用する必須値ではありません。 現在のカーネル設定、メモリ使用量、ネットワークのボトルネックを先に測定します。値を増やした後は スループットだけでなくメモリと遅延も比較し、効果を確認した項目だけを永続化します。 ```bash sudo sysctl -w net.core.rmem_default=33554432 sudo sysctl -w net.core.wmem_default=33554432 sudo sysctl -w net.core.rmem_max=268435456 sudo sysctl -w net.core.wmem_max=268435456 sudo sysctl -w 'net.ipv4.tcp_rmem=262144 33554432 268435456' sudo sysctl -w 'net.ipv4.tcp_wmem=262144 33554432 268435456' sudo sysctl -w 'net.ipv4.tcp_mem=8388608 8388608 8388608' ``` 永続化するには`/etc/sysctl.conf`に追加します。 ### 時刻同期(NTP) 全ノードのシステム時刻が一致する必要があります。NTPまたは`chrony`で同期してください。 ```bash # chronyの使用例 sudo systemctl enable chronyd sudo systemctl start chronyd chronyc tracking ``` タイムサーバーを使用できない隔離されたインストール環境では、初期時刻を直接設定できます。 次の値は書式例なので実際の現在時刻に置き換えてください。手動設定だけではノード間の時刻差を継続的に 補正できないため、本番投入前に時刻同期経路を用意します。 ```bash sudo date -s "2025-01-02 12:34:56" ``` ### ポートの予約 各ノードでMachbaseが使用するポートを予約します。 ```bash current=$(cat /proc/sys/net/ipv4/ip_local_reserved_ports) ports=5101-5110,5201-5202,5301-5302,5401,5500-5503,5656 sudo sysctl -w net.ipv4.ip_local_reserved_ports="${current:+$current,}$ports" ``` 既存の予約ポートは上書きせず、カンマで区切って統合します。クラスター構成に応じてポート範囲を調整してください。 Cluster link、Coordinator/Deployerの管理、サービス、Warehouseのレプリケーション管理ポートなどを すべて含める必要があります。 --- ## machclusterctlによるデプロイ `machclusterctl`は1つの`cluster.yaml`でクラスター全体を自動デプロイ・管理するツールです。 SSHで各ノードにリモート接続し、パッケージ配布、初期化、起動・終了を一括処理します。 ### 前提条件 - Primary Coordinatorをインストールするホストでコマンドを実行し、そのホストからパッケージと SSH秘密鍵を読み取れる必要があります。 - Primaryホストから全対象ホストへSSH鍵認証が設定されている必要があります。 - 各ノードの`home_path`と`dbs_path`の親パスに作成・書き込み権限が必要です。 - 別のライセンスが必要な場合は、自動起動前に配布パッケージとライセンス適用手順を準備します。 YAMLに任意のライセンスプロパティは追加しません。 - [Cluster Editionのインストール環境の準備](/ja/dbms/installation-deployment-upgrade/cluster-edition/#preparation-environment-cluster-edition)の完了 ### 作業手順 | 段階 | ドキュメント | |------|------| | 1. cluster.yamlの作成 | [cluster.yamlの作成](/ja/dbms/installation-deployment-upgrade/cluster-edition/#machclusterctl-cluster-yaml) | | 2. YAMLの妥当性検査 | [YAMLの検証](/ja/dbms/installation-deployment-upgrade/cluster-edition/#machclusterctl-validation-yaml) | | 3. 初回インストールと起動 | [初回インストール](/ja/dbms/installation-deployment-upgrade/cluster-edition/#machclusterctl-initial) | | 4. 状態確認 | [初回インストールと状態確認](/ja/dbms/installation-deployment-upgrade/cluster-edition/#machclusterctl-initial) | | 5. 以降の構成変更 | [Cluster運用](/ja/dbms/operations-configuration-recovery/cluster/) | | 6. 障害時の復旧 | [Clusterのトラブルシューティング](/ja/dbms/troubleshooting/cluster/) | --- ### cluster.yamlの作成 `cluster.yaml`はインストールするノード構成とパスを宣言します。以下のアドレスは例のため実ホストに 置き換えます。`origin_path`はコマンドを実行するPrimary Coordinatorホストから読み取るアーカイブ、 `home_path`と`dbs_path`は該当ノードホスト上のパスです。`deployer`はそのノードを配置・制御する Deployerを参照します。 #### ファイル構造の例 ```yaml version: "1" cluster: name: mc-prod hosts: node1: address: machbase@192.168.1.10 node2: address: machbase@192.168.1.11 node3: address: machbase@192.168.1.12 package: name: machbase origin_path: /home/machbase/packages/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz ssh: key_file: /home/machbase/.ssh/id_rsa defaults: coordinator: home_path: /home/machbase/coordinator cluster_link_port: 5101 http_admin_port: 5102 deployer: home_path: /home/machbase/deployer cluster_link_port: 5201 http_admin_port: 5202 lookup: home_path: /home/machbase/lookup cluster_link_port: 5301 broker: home_path: /home/machbase/broker cluster_link_port: 5401 service_port: 5656 warehouse: home_path: /home/machbase/warehouse cluster_link_port: 5501 service_port: 5500 coordinators: - alias: coord-primary-1 host: node1 role: primary - alias: coord-secondary-1 host: node2 role: secondary deployers: - alias: deployer-1 host: node1 - alias: deployer-2 host: node2 - alias: deployer-3 host: node3 lookup: - alias: lookup-master-1 host: node1 deployer: deployer-1 type: master - alias: lookup-monitor-1 host: node2 deployer: deployer-2 type: monitor brokers: - alias: broker-1 host: node1 deployer: deployer-1 dbs_path: /data/machbase/broker-1/dbs - alias: broker-2 host: node2 deployer: deployer-2 warehouse_groups: - name: group1 nodes: - alias: warehouse-group1-1 host: node2 deployer: deployer-2 dbs_path: /data/machbase/warehouse-group1-1/dbs - alias: warehouse-group1-2 host: node3 deployer: deployer-3 dbs_path: /data/machbase/warehouse-group1-2/dbs ``` #### 主な項目の説明 | 項目 | 説明 | |------|------| | `version` | YAMLスキーマバージョン。現在は`"1"`を使用します。 | | `cluster.name` | クラスター名。`destroy`の確認などで使用します。 | | `cluster.hosts` | ノードから参照するホスト別名とSSH接続先。`address`は`user@host`形式です。 | | `cluster.package.name` | Coordinatorへ登録するパッケージ名。 | | `cluster.package.origin_path` | `install`、`apply`、`upgrade`の入力に使用するパッケージアーカイブのパス。 | | `cluster.package.registered_path` | `export`が記録するCoordinatorのパッケージ保存先の観測パス。実行入力には使用しません。 | | `cluster.ssh.key_file` | 対象サーバーへの接続に使用する秘密鍵パス。パスワードフィールドは使用しません。 | | `cluster.defaults` | ノードタイプ別の`home_path`、`cluster_link_port`、`service_port`のデフォルト値。 | | `cluster.coordinators` | Coordinatorノード一覧。`role`は`primary`または`secondary`。 | | `cluster.deployers` | Deployerノード一覧。 | | `cluster.lookup` | Lookupノード一覧。`type`は`master`、`monitor`、`slave`。 | | `cluster.brokers` | Brokerノード一覧。クライアントSQL接続ポートは`service_port`。 | | `cluster.warehouse_groups` | Warehouseグループとグループ別ノード一覧。 | #### 推奨構成 - Coordinator: 2台(Primary + Secondary HA) - Deployer: 1台以上 - Lookup: `master` 1台、`monitor` 1台以上 - Broker: 2台以上(負荷分散) - Warehouseグループ: グループごとに2台(レプリケーションによる高可用性) 同じサーバーに同タイプのノードを2台以上配置する場合は、2台目以降の`home_path`とポートを明示し、 競合を避けます。 CoordinatorとDeployerの管理ポートには`http_admin_port`を使用します。 BrokerとWarehouseには任意で`dbs_path`を指定します。`dbs_path`はノードがインストールされるサーバーの データファイルパスで、省略時は`machcoordinatoradmin --add-node`のデフォルト`DBS_PATH`動作に従います。 既存の`cluster.package.path`は後方互換入力として使用できますが、新しいYAMLでは`origin_path`を使用します。 `http_admin_port`はCoordinatorとDeployerだけに使用します。Broker、Lookup、Warehouseには HTTPポートフィールドを指定しません。 作成後に妥当性を検査します。 --- ### YAMLの検証 `cluster.yaml`を実際のインストールに使用する前に妥当性を検査します。`validate`はYAML構文、必須値、 別名、ポート競合、トポロジーの関係を静的に検査します。 #### 検証コマンド ```bash machclusterctl validate -f cluster.yaml ``` #### 検証項目 | 項目 | 説明 | |------|------| | YAML構文 | ファイルの解析エラー | | 環境変数の置換 | `${VAR}`または`${VAR:-default}`式を解釈できるか | | 必須フィールド | クラスター名、ホスト、パッケージ、ノード別の必須値の欠落 | | 別名 | ノード別名の重複 | | ポート競合 | 同じホスト内の宣言ポートの競合 | | トポロジー | Primary Coordinator、Lookup master/monitor、Deployerの参照関係 | #### 出力例 ```text Validation passed. ``` エラーがあれば、メッセージの項目を修正して再検証します。 #### インストール前の実行計画確認 新規インストール前にSSH接続、パッケージの存在、リモートディレクトリ権限まで確認するには、 `install --dry-run --verbose`を使用します。 ```bash machclusterctl install -f cluster.yaml --dry-run --verbose ``` インストール後の構成変更を検証する場合は`apply --dry-run`を使用します。現在のクラスター状態とYAMLの 差を計算して実行計画を表示し、実際のリモート変更は行いません。 ```bash machclusterctl apply -f cluster.yaml --dry-run --verbose ``` #### 一般的なエラーと解決方法 | エラー | 原因 | 解決方法 | |------|------|------| | `field ... not found` | 非サポートのYAMLキー | 現行スキーマの`cluster.*`項目に修正 | | `required field ...` | 必須値の欠落 | メッセージのフィールドを追加 | | `duplicate alias` | ノード別名の重複 | 全ノードの別名を一意に変更 | | `port conflict` | 同一ホストで同じポートを使用 | 競合ポートを別に指定。ホームパスだけの変更では解決しない | | `deployer ... not found` | Lookup/Broker/Warehouseが存在しないDeployerを参照 | `deployer`値をDeployerの別名またはホスト:ポートに修正 | --- ### 初回インストール `cluster.yaml`の作成と検証が完了したら、インストール計画を確認してクラスターをインストールします。 #### 1. クラスターのインストール 各ノードへのパッケージ配布と初期化の前に、実行計画と事前検査の結果を確認します。 ```bash machclusterctl install -f cluster.yaml --dry-run --verbose ``` 問題がなければ実際にインストールします。 ```bash machclusterctl install -f cluster.yaml --yes --verbose ``` このコマンドは次の処理を自動実行します。 1. 各ノードへのパッケージコピーと展開 2. 各ノードの`machbase.conf`作成とポート設定 3. Coordinatorデータベースの初期化 4. ノード登録(Coordinatorに各ノードを追加) #### 2. クラスターの起動 `install`はCoordinator、Deployer、Lookup、Broker、Warehouseを準備して起動します。 インストール後にクラスター全体を再起動する必要がある場合だけ、次のコマンドを使用します。 ```bash machclusterctl start ``` #### 3. 状態確認 ```bash export MACHBASE_COORDINATOR_HOME=/home/machbase/coordinator machclusterctl status ``` 1台のサーバーで複数のCoordinatorホームを切り替えて確認する場合は、直接指定します。 ```bash machclusterctl status --coordinator /home/machbase/coordinator ``` 出力は`machcoordinatoradmin --cluster-status-full --verbose`形式です。以下は出力列を示す一部の行の例で、 YAMLの全ノード一覧ではありません。CoordinatorとBrokerは`primary`、`leader`など役割別の状態を取るため、 全行が`normal`かではなく、登録ノード数と役割別の目標・実際の状態が一致するかを確認します。 ``` +-------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------+-----------------+----------+ | Node Type | Node Name | Group Name | Group State | Desired & Actual State | RP State | Disk(%) (00/00) | Ping(μs) | +-------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------+-----------------+----------+ | coordinator | coord-1(192.168.1.10:5101) | Coordinator | normal | primary | primary | ----------- | --------------- | 214 | | deployer | deployer-1(192.168.1.10:5201) | Deployer | normal | running | running | ----------- | --------------- | 100 | | broker | broker-1(192.168.1.11:5401) | Broker | normal | leader | leader | ----------- | --------------- | 100 | | warehouse | wh-g1-1(192.168.1.13:5501) | group1 | normal | normal | normal | running | 26.9 | 100 | +-------------+--------------------------------+--------------------------------+--------------------------------+-------------------------------+-------------+-----------------+----------+ ``` #### 4. クライアント接続テスト BrokerノードのIPとポートに接続します。 ```bash machsql -s 192.168.1.11 -P 5656 -u SYS -p MANAGER # Mach> ``` #### クラスターの終了 ```bash machclusterctl stop ``` --- ### インストール後の運用 初回インストールと接続検証後のノード構成変更、追加・削除、状態復旧は [Cluster運用](../../operations-configuration-recovery/cluster/)に従います。障害原因の分類と 復旧判断は[Clusterのトラブルシューティング](../../troubleshooting/cluster/)を参照してください。 ## machcoordinatoradminによる手動デプロイ `machclusterctl`を使用できない場合はCoordinatorとDeployerを直接準備し、パッケージとノードを登録します。 自動デプロイ済みの環境で以下の作成コマンドを再実行しないでください。手動例はYAMLとは別構成です。 役割別に実行場所を変えてコマンドを実行します。 | ホスト | 役割 | |---|---| | `192.168.1.10` | Primary Coordinator、Deployer、Lookup master | | `192.168.1.11` | Deployer、Lookup monitor、Broker | | `192.168.1.13` | Deployer、Warehouse group1の最初のノード | | `192.168.1.14` | Deployer、Warehouse group1のレプリカノード | | `192.168.1.20` | 任意のSecondary Coordinator | 同一ホストの役割ごとにホームとポートを分けます。Deployerはデータ処理ノードをインストールする各ホストで 準備し、以下の`--deployer`アドレスも対象ホストに合わせます。 ### 手動デプロイの手順 1. [パッケージの準備と登録](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin-package) — 完全パッケージのインストールと軽量パッケージの登録準備 2. [Coordinator / Deployerのインストール](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin-coordinator-deployer) — 主要な管理ノードを起動 3. [パッケージ登録](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin-package) — 稼働中のCoordinatorへ軽量パッケージを登録 4. [Lookup / Broker / Warehouseのインストール](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin-lookup-broker-warehouse) — データ処理ノードを登録・起動 5. [全体状態の確認](/ja/dbms/installation-deployment-upgrade/cluster-edition/#manual-machcoordinatoradmin-lookup-broker-warehouse) — 登録・起動後の初回状態検証 ### machclusterctlとの違い | 項目 | machclusterctl | 手動デプロイ | |------|---------------|----------| | 設定方式 | cluster.yamlの単一ファイル | 各ノードのmachbase.confを直接編集 | | パッケージ配布 | 自動リモートコピー | Coordinator/Deployerは直接インストール、Broker/WarehouseはDeployerが配布 | | ノード登録 | 自動 | `machcoordinatoradmin --add-node`を手動実行 | | 一括起動・終了 | `machclusterctl start/stop` | ノードごとに個別実行 | 手動デプロイは柔軟ですが、ミスの可能性も高くなります。新規構築には`machclusterctl`を推奨します。 --- ### パッケージの準備と登録 Cluster Editionの手動デプロイでのパッケージ準備・登録手順です。CoordinatorとDeployerには完全パッケージを インストールして環境変数を設定します。BrokerとWarehouse用の軽量パッケージはCoordinatorの起動後に登録します。 #### パッケージの種類 Cluster Editionには2種類のパッケージがあります。 | パッケージ | 対象ノード | 特徴 | |--------|-----------|------| | 完全パッケージ | Coordinator、Deployer | 全実行ファイルを含む | | 軽量パッケージ(lightweight) | Broker、Warehouse | データ処理に必要なファイルだけを含み、小容量 | ファイル名の例: - 完全: `machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz` - 軽量: `machbase-cluster-8.7.0.official-LINUX-X86-64-release-lightweight.tgz` #### CoordinatorとDeployerへのパッケージ配布 完全パッケージをCoordinatorとDeployerノードにコピーして展開します。 ##### Coordinatorノード ```bash # Coordinatorノードで実行 mkdir -p /home/machbase/coordinator scp machbase@package-host:/path/to/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz /home/machbase/ tar zxf /home/machbase/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz -C /home/machbase/coordinator ``` ##### Deployerノード ```bash mkdir -p /home/machbase/deployer scp machbase@package-host:/path/to/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz /home/machbase/ tar zxf /home/machbase/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz -C /home/machbase/deployer ``` この段階ではBrokerとWarehouseへ軽量パッケージを直接展開しません。Coordinatorへ軽量パッケージを登録すると、 後で`--add-node`で指定したDeployerが対象ノードの`--home-path`へパッケージを配布します。 #### Coordinatorへのパッケージ登録 CoordinatorからBrokerとWarehouseを起動するには、Coordinatorへの軽量パッケージ登録が必要です。 CoordinatorとDeployerをインストールし、Coordinatorが稼働中の状態で次のコマンドを実行します。 ```bash $MACHBASE_COORDINATOR_HOME/bin/machcoordinatoradmin --add-package=machbase \ --file-name="/home/machbase/machbase-cluster-8.7.0.official-LINUX-X86-64-release-lightweight.tgz" ``` 登録したパッケージは、後でBrokerとWarehouseを`--add-node`で登録する際に`--package-name=machbase`で 参照します。 #### 環境変数の設定 `package-host`と`/path/to/`は実際のパッケージ保存場所に置き換えます。CoordinatorとDeployerを同じホストで 管理する場合も、別々のシェルで役割に合う環境を使用します。以下は各シェルに適用する値で、サービスや ログイン初期化ファイルにも同じ値を反映します。 ```bash # Coordinatorノード export MACHBASE_COORDINATOR_HOME=/home/machbase/coordinator export MACHBASE_HOME=$MACHBASE_COORDINATOR_HOME export PATH=$MACHBASE_HOME/bin:$PATH export LD_LIBRARY_PATH=$MACHBASE_HOME/lib:$LD_LIBRARY_PATH ``` ```bash # 別のDeployer管理シェル export MACHBASE_DEPLOYER_HOME=/home/machbase/deployer export MACHBASE_HOME=$MACHBASE_DEPLOYER_HOME export PATH="$MACHBASE_HOME/bin:$PATH" export LD_LIBRARY_PATH="$MACHBASE_HOME/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ``` --- ### Coordinator / Deployerのインストール パッケージ配布後、Coordinatorを先にインストール・起動してからDeployerを登録します。 #### Coordinatorのインストール ##### 1. machbase.confの設定 `$MACHBASE_COORDINATOR_HOME/conf/machbase.conf`を編集します。 ```bash vi $MACHBASE_COORDINATOR_HOME/conf/machbase.conf ``` 主な設定: ``` CLUSTER_LINK_HOST = 192.168.1.10 # このノードのIP CLUSTER_LINK_PORT_NO = 5101 HTTP_ADMIN_PORT = 5102 ``` ##### 2. メタデータベースの作成とサービス起動 ```bash machcoordinatoradmin -c machcoordinatoradmin -u ``` ##### 3. 自身をCoordinatorノードとして登録 ```bash machcoordinatoradmin --add-node="192.168.1.10:5101" \ --node-type=coordinator \ --http-admin-port=5102 ``` ##### 4. 登録の確認 ```bash machcoordinatoradmin --cluster-status ``` #### Secondary Coordinatorのインストール(任意) 高可用性のためSecondary Coordinatorを追加します。 Secondaryノードにパッケージを配布して`machbase.conf`を設定し、先に**Primary Coordinatorで**ノードを 登録します。 ```bash # Primary Coordinatorで先に登録 machcoordinatoradmin --add-node="192.168.1.20:5101" \ --node-type=coordinator \ --http-admin-port=5102 # 次にSecondaryノードで起動(--primaryでPrimaryを指定) machcoordinatoradmin -u --primary=192.168.1.10:5101 ``` Secondaryの起動前に、必ずPrimaryでノード登録を完了する必要があります。 #### Deployerのインストール 手動構成表の各Deployerホストでこの手順を行います。以下の設定の`CLUSTER_LINK_HOST`は、そのホスト自身の IPに置き換えます。他ホストのアドレスをそのままコピーすると、ノードの通信アドレスと実際の実行場所が 異なってしまいます。 ##### 1. machbase.confの設定 ``` CLUSTER_LINK_HOST = 192.168.1.10 # DeployerノードのIP CLUSTER_LINK_PORT_NO = 5201 HTTP_ADMIN_PORT = 5202 ``` ##### 2. 起動 ```bash machdeployeradmin -c machdeployeradmin -u ``` ##### 3. CoordinatorへのDeployerノード登録 全Deployerが起動したら、Primary Coordinatorの管理シェルで登録します。 ```bash machcoordinatoradmin --add-node="192.168.1.10:5201" \ --node-type=deployer \ --http-admin-port=5202 machcoordinatoradmin --add-node="192.168.1.11:5201" \ --node-type=deployer --http-admin-port=5202 machcoordinatoradmin --add-node="192.168.1.13:5201" \ --node-type=deployer --http-admin-port=5202 machcoordinatoradmin --add-node="192.168.1.14:5201" \ --node-type=deployer --http-admin-port=5202 ``` --- ### Lookup / Broker / Warehouseのインストール CoordinatorとDeployerの準備後、Lookup、Broker、WarehouseをCoordinatorに登録して起動します。 BrokerとWarehouseの登録前に、軽量パッケージをCoordinatorへ`--add-package`で登録する必要があります。 #### Lookupノード Lookup masterとmonitorをそれぞれ登録して起動します。次の例はPrimaryホストとBrokerホストへ配置し、 各ホストのDeployerを使用します。同じホームが既存のLookupで使用中でないことを確認します。 ```bash machcoordinatoradmin --add-node="192.168.1.10:5301" \ --node-type=lookup \ --lookup-type=master \ --deployer="192.168.1.10:5201" \ --home-path="/home/machbase/lookup" machcoordinatoradmin --add-node="192.168.1.11:5301" \ --node-type=lookup \ --lookup-type=monitor \ --deployer="192.168.1.11:5201" \ --home-path="/home/machbase/lookup" machcoordinatoradmin --startup-node="192.168.1.10:5301" machcoordinatoradmin --startup-node="192.168.1.11:5301" ``` #### Brokerのインストール ##### 1. 登録パラメーターの確認 Broker設定ファイルは`--add-node`時に生成され、Deployer経由で対象ノードへ配布されます。 登録前にクラスター通信ポートとサービスポートを確定します。BrokerにHTTP管理ポートは指定しません。 ``` CLUSTER_LINK_HOST = 192.168.1.11 # BrokerノードのIP CLUSTER_LINK_PORT_NO = 5401 PORT_NO = 5656 # クライアント 接続ポート ``` ##### 2. Coordinatorへのノード登録 Coordinatorノードで実行します。 ```bash machcoordinatoradmin --add-node="192.168.1.11:5401" \ --node-type=broker \ --deployer="192.168.1.11:5201" \ --package-name=machbase \ --home-path="/home/machbase/broker" \ --dbs-path="/data/machbase/broker_dbs" \ --port-no=5656 ``` | パラメーター | 説明 | |---------|------| | `--add-node` | 登録するノードのIP:CLUSTER_LINK_PORT_NO | | `--node-type` | `broker` / `warehouse` / `lookup` | | `--deployer` | そのノードをインストール・制御するDeployerのIP:CLUSTER_LINK_PORT_NO | | `--package-name` | Coordinatorに登録したパッケージ名 | | `--home-path` | ノードのホームディレクトリ | | `--dbs-path` | Broker/Warehouseのデータファイルパス。省略時はデフォルト`DBS_PATH` | | `--port-no` | クライアントまたはノードのサービスポート | | `--replication` | Warehouseのレプリケーション管理アドレス。`host:port`形式 | ##### 3. ノードの起動 Coordinatorで該当ノードを起動します。 ```bash machcoordinatoradmin --startup-node="192.168.1.11:5401" ``` #### Warehouseのインストール Warehouseノードはグループ単位で構成します。同じグループ内のノード間でデータを複製します。 ##### 1. 登録パラメーターの確認 Warehouse設定ファイルは`--add-node`時に生成され、Deployer経由で対象ノードへ配布されます。 登録前にクラスター通信ポート、サービスポート、レプリケーション管理アドレスを確定します。 ``` CLUSTER_LINK_HOST = 192.168.1.13 CLUSTER_LINK_PORT_NO = 5501 PORT_NO = 5500 ``` ##### 2. ノードの登録 ```bash machcoordinatoradmin --add-node="192.168.1.13:5501" \ --node-type=warehouse \ --deployer="192.168.1.13:5201" \ --package-name=machbase \ --home-path="/home/machbase/warehouse_g1_1" \ --dbs-path="/data/machbase/warehouse_g1_1_dbs" \ --port-no=5500 \ --replication=192.168.1.13:5502 \ --group=group1 \ --no-replicate machcoordinatoradmin --add-node="192.168.1.14:5501" \ --node-type=warehouse \ --deployer="192.168.1.14:5201" \ --package-name=machbase \ --home-path="/home/machbase/warehouse_g1_2" \ --dbs-path="/data/machbase/warehouse_g1_2_dbs" \ --port-no=5500 \ --replication=192.168.1.14:5502 \ --group=group1 ``` 別途`--add-group`コマンドは使用しません。Warehouseグループ名は各Warehouseノードの登録時に `--group`で指定します。 ##### 3. ノードの起動 ```bash machcoordinatoradmin --startup-node="192.168.1.13:5501" machcoordinatoradmin --startup-node="192.168.1.14:5501" ``` #### 全体状態の確認 全ノードの登録後に状態を確認します。 ```bash machcoordinatoradmin --cluster-status ``` Coordinator、Lookup、Broker、Warehouseが各役割に合う正常状態で表示されれば、クラスターは正常に 稼働しています。Coordinatorは`primary`、Brokerは`leader`、Warehouseは`normal`、`sync-active`、 `sync-standby`などで表示されます。 #### 初回接続の確認 Brokerのネイティブポートに接続し、`SELECT CURRENT_DATABASE();`とサンプル検索を実行します。 初回インストール検証後の個別ノードの起動・終了と状態復旧は [Cluster運用](../../operations-configuration-recovery/cluster/)と [Clusterのトラブルシューティング](../../troubleshooting/cluster/)を使用してください。 --- title: "3.4 アップグレード" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/upgrade/ language: ja kind: page --- # 3.4 アップグレード アップグレードは実行ファイルの交換だけでなく、既存のデータ、設定、アプリケーションが新バージョンで 同じ意味で動作するかを確認する作業です。まず対応するバージョン間の経路を確認し、復元可能なバックアップと サービス再開基準を準備します。以下の8.7.0パッケージ名とパスは、提供された実際の配布物に合わせます。 ## アップグレード前の確認事項 - 現在と対象のバージョンの互換性を確認します。マイナーバージョンが異なるとDBファイル形式が変わる場合があります。 - アップグレード前にバックアップします。[バックアップ方法](/ja/dbms/operations-configuration-recovery/backup-restore-mount/#backup)を参照してください。 - 実行中のINSERT・APPENDクライアントを確認します。 ### 8.7.0アップグレードの事前確認 8.5から8.7.0にアップグレードする場合は、バイナリ交換前に次の依存関係を調査し、対応する方式へ移行します。 1. 廃止された`HTTP_AUTH`、`HTTP_ENABLE`、`HTTP_MAX_MEM`、`HTTP_PORT_NO`、`RS_CACHE_*`、 `STREAM_THREAD_COUNT`、`STREAM_WAIT_MS`設定を現在のファイルで探し、サポート一覧と照合します。 廃止設定は削除し、継続設定は保持します。特にClusterの`HTTP_ADMIN_PORT`は現行の管理ポートのため、 `HTTP_*`という理由で一緒に削除しないでください。 2. `/machbase`、`/machiot`を呼ぶアプリケーションは、対応SDKを使用するバックエンドへ移行します。 3. `STREAM_*`プロシージャと`FLUSH RESULT_CACHE`を実行するSQL・運用スクリプトを変更します。 4. `machcli.h`と`MachCLI*()`を使用するC/C++アプリケーションをMachbase SQLCLIまたはODBCに移行します。 SQLCLIとODBCは異なるAPI集合です。 5. WebAdmin/MWAに依存する運用手順・ダッシュボードは、コマンドラインツールまたは別アプリケーションへ移行します。 全廃止項目と継続機能は [バージョンと互換性](/ja/dbms/reference/support-scope-constraints/compatibility-version/#removed-features-870)を参照してください。 ## アップグレード経路 | Edition | 方式 | リンク | |--------|------|------| | Standard Edition | サーバー終了後にパッケージを交換 | [Standard Editionのアップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#standard-edition) | | Cluster Edition | Broker/Warehouseを順次アップグレード | [オンラインアップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#cluster-edition-online) | | Cluster Edition | 全体停止 | [全体停止アップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#cluster-edition-full-stop) | Cluster Editionではデータ可用性の要件に応じてオンライン方式または全体停止方式を選びます。 --- ## Standard Editionのアップグレード サーバーを終了し、パッケージを交換して再起動します。物理DBファイルをそのまま開くことがサポートされる バージョン間経路だけに適用します。データ変換やエクスポート・インポートが必要な経路は、 該当リリースの移行手順を先に実行します。 ### アップグレード前の準備 1. **バックアップ**: 対応するBACKUPコマンドでバックアップを作成し、別環境で復元可能か確認します。 実行中のデータディレクトリを単純にコピーしただけで復旧可能なバックアップを確保したとは判断しません。 2. **クライアント接続の終了**: 実行中のAppendまたはINSERTをすべて完了します。 3. **現在のバージョン確認**: ```bash machbased -v ``` ### アップグレード手順 #### 1. サーバーの終了 ```bash machadmin -s # Machbase server shut down successfully. ``` #### 2. 既存パッケージと設定の保管 実行ファイルとライブラリだけでなく、現在の設定とライセンスも別の場所に保管します。 以下のパスに以前のバックアップがないことを確認して実行します。 ```bash cp -a "$MACHBASE_HOME/bin" "$MACHBASE_HOME/bin.bak" cp -a "$MACHBASE_HOME/lib" "$MACHBASE_HOME/lib.bak" cp -a "$MACHBASE_HOME/conf" "$MACHBASE_HOME/conf.bak" ``` **データディレクトリ(`dbs/`)と別途指定した`DBS_PATH`は保持します。** 上記のコピーは実行ファイルと 設定の保管であり、DBバックアップの代わりにはなりません。新バージョンがデータを変更した後に旧実行ファイルを 戻すだけで復旧できるとは考えず、検証済みのバックアップ復元経路を使用します。 #### 3. 新パッケージの展開 新パッケージは別の作業ディレクトリに展開し、構成と設定の変更点を先に確認します。 ```bash upgrade_stage=$(mktemp -d) tar zxf machbase-SDK-8.7.0.official-LINUX-X86-64-release.tgz -C "$upgrade_stage" ``` 展開だけでは既存インストールの実行ファイルは変わりません。以下は`bin/`、`lib/`、`include/`を含む Standard tarballから実行ファイル・ライブラリ・ヘッダーを反映する例です。先にサーバー終了を確認し、 コマンドが失敗した場合は次の起動段階に進まないでください。 ```bash ( set -e test -n "$MACHBASE_HOME" test -x "$upgrade_stage/bin/machbased" test -d "$upgrade_stage/lib" test -d "$upgrade_stage/include" test -d "$MACHBASE_HOME/bin" test -d "$MACHBASE_HOME/lib" test -d "$MACHBASE_HOME/include" cp -a "$upgrade_stage/bin/." "$MACHBASE_HOME/bin/" cp -a "$upgrade_stage/lib/." "$MACHBASE_HOME/lib/" cp -a "$upgrade_stage/include/." "$MACHBASE_HOME/include/" "$MACHBASE_HOME/bin/machbased" -v ) ``` 既存の`conf/machbase.conf`、ライセンス、実際の`DBS_PATH`のデータは保持し、新設定項目を既存設定に マージします。コピーは同名の配布ファイルを交換しますが、旧バージョンにしかないファイルは自動削除しません。 SDKやプラグインは新バージョンに合うファイルを明示的に選び、追加の交換対象と削除項目はリリース情報で確認します。 出力されたバイナリバージョンと設定の確認が完了してからサーバーを起動します。 #### 4. サーバーの起動 ```bash machadmin -u # Machbase server started successfully. ``` #### 5. バージョンの確認 ```bash machbased -v # サーバーへ接続 machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER ``` ```sql SELECT EDITION, BINARY_DB_MAJOR_VERSION, BINARY_DB_MINOR_VERSION FROM V$VERSION; ``` ### 注意事項 - `dbs/`ディレクトリを削除・初期化(`machadmin -d`)しないでください。 - マイナーバージョン間のアップグレードではDBファイルの移行が必要な場合があります。必ずリリースノートを確認してください。 - Windowsでは新パッケージまたはインストーラー適用前にMachbaseサービスを停止します。 --- ## Cluster Editionのアップグレード サービス停止の可否に応じて2つの方式から選びます。 | 方式 | サービス停止 | 適している状況 | |------|-----------|------------| | [オンラインアップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#cluster-edition-online) | Broker/Warehouseを順次再起動 | BrokerとWarehouseだけを交換する本番環境 | | [全体停止アップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#cluster-edition-full-stop) | あり | メンテナンス時間帯を確保できる場合、メジャーバージョン変更 | ### 共通の事前注意事項 - アップグレード中はDDLまたはDELETEを実行しないでください。 - アップグレード中にノードの追加・起動・終了・削除を並行して行わないでください。 - オンラインアップグレードはBrokerとWarehouseが対象です。Coordinator、Deployer、Lookupも交換する場合は全体停止方式を使用します。 - アップグレード前のバックアップを推奨します。 --- ### オンラインアップグレード 稼働中のクラスターでBrokerとWarehouseを順次アップグレードします。Coordinator、Deployer、Lookupを 含む全バイナリの交換が必要な場合は [全体停止アップグレード](/ja/dbms/installation-deployment-upgrade/upgrade/#cluster-edition-full-stop)を使用します。 #### アップグレード手順 ##### 1. cluster.yamlのパッケージ変更 `cluster.package.name`と`cluster.package.origin_path`を新パッケージに変更します。 パッケージ内容が変わる場合は、パッケージ名とアーカイブ名も一意な新しい名前に変更します。 ```yaml cluster: package: name: machbase-v8.7.0 origin_path: /home/machbase/packages/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz ``` `registered_path`は`machclusterctl export`が記録するCoordinatorのパッケージ保存先パスです。 アップグレードするアーカイブの指定には`origin_path`を使用します。 ##### 2. 実行計画の確認 ```bash machclusterctl upgrade -f cluster.yaml --online --dry-run --verbose ``` ##### 3. オンラインアップグレードの実行 ```bash machclusterctl upgrade -f cluster.yaml --online --yes --verbose ``` `--online`を省略してもオンラインモードになりますが、運用手順を明確にするため明示を推奨します。 ##### 4. 全体状態の確認 ```bash machclusterctl status ``` #### 手動アップグレードの補足 `machcoordinatoradmin --upgrade-node`を直接使用する場合は、対象ノードとパッケージ名をともに指定します。 ```bash machcoordinatoradmin --upgrade-node=192.168.1.11:5401 --package-name=machbase-v8.7.0 ``` オンラインの対象はBrokerとWarehouseに限定します。Brokerが1台しか残っていないときにそのBrokerを アップグレードすると、その間クライアント接続が切れる場合があります。 オンラインモードはクラスター全体の停止を省略する方式であり、無停止を保証するHA対応のローリング アップグレードではありません。Warehouseグループが一時的に読み取り専用になる場合があるため、 アプリケーションの再接続・再試行と書き込み遅延を検証する必要があります。プロトコル互換性が変わる場合や、 全役割のバイナリを合わせる必要がある場合は全体停止方式を使用します。 全対象ノードの役割状態とバージョンを確認してから、代表的な検索・入力とレプリケーション状態まで検証します。 --- ### 全体停止アップグレード クラスターを完全に終了し、全ノードを一括アップグレードします。Coordinator、Deployer、Lookupを含む 全バイナリの交換が必要な場合や、DBファイル形式の変更を伴う場合に使用します。 #### アップグレード手順 ##### 1. クライアント接続の終了 全INSERT・APPEND・SELECT操作が完了したことを確認します。 ##### 2. cluster.yamlのパッケージ変更 `cluster.package.name`と`cluster.package.origin_path`を新パッケージに変更します。 アップグレード前にノード追加・削除・ポート変更などのトポロジー変更を残してはいけません。 変更がある場合は先に`apply`で反映してからアップグレードします。 `machclusterctl upgrade --full-stop`はCoordinatorとDeployerを含む全ノードホームに同じパッケージを 交換反映します。そのため`origin_path`には`machcoordinatoradmin`と`machdeployeradmin`を含む 完全なClusterパッケージを指定します。 ##### 3. 実行計画の確認 ```bash machclusterctl upgrade -f cluster.yaml --full-stop --dry-run --verbose ``` ##### 4. 全体停止アップグレードの実行 ```bash machclusterctl upgrade -f cluster.yaml --full-stop --yes --verbose ``` `machclusterctl`はクラスター全体の停止を前提に、パッケージを一時準備パスへ展開してから ノードホームへ交換反映します。 #### 手動デプロイの補足 手動デプロイ環境で直接交換する場合は、Coordinatorに新パッケージを登録します。 ```bash machcoordinatoradmin --add-package=machbase-v8.7.0 \ --file-name=/home/machbase/packages/machbase-cluster-8.7.0.official-LINUX-X86-64-release.tgz ``` Warehouse → Broker → Lookup → Deployer → Coordinatorの順で終了します。 ```bash machcoordinatoradmin --shutdown-node=192.168.1.13:5501 machcoordinatoradmin --shutdown-node=192.168.1.14:5501 machcoordinatoradmin --shutdown-node=192.168.1.11:5401 machcoordinatoradmin --shutdown-node=192.168.1.10:5301 machdeployeradmin --shutdown machcoordinatoradmin --shutdown ``` 各ノードホームを新パッケージに交換する際は、既存の`conf/machbase.conf`、`dbs/`、`meta/`、`package/`を 保持します。別の作業パスに新パッケージを展開し、保持対象パスを除いて交換します。 Coordinator → Deployer → Lookup → Broker → Warehouseの順で起動します。 ```bash machcoordinatoradmin --startup machdeployeradmin --startup machcoordinatoradmin --startup-node=192.168.1.10:5301 machcoordinatoradmin --startup-node=192.168.1.11:5401 machcoordinatoradmin --startup-node=192.168.1.13:5501 machcoordinatoradmin --startup-node=192.168.1.14:5501 ``` 再起動後、BrokerとWarehouseのパッケージメタデータを新パッケージ名に同期します。 ```bash machcoordinatoradmin --upgrade-node=192.168.1.11:5401 --package-name=machbase-v8.7.0 machcoordinatoradmin --upgrade-node=192.168.1.13:5501 --package-name=machbase-v8.7.0 machcoordinatoradmin --upgrade-node=192.168.1.14:5501 --package-name=machbase-v8.7.0 ``` ##### 5. 状態の確認 ```bash machclusterctl status ``` ノード状態に加え、Broker接続、代表データの検索・入力、レプリケーション、ライセンス、設定値を確認してから サービスを再開します。[インストール検証](../validation-checklist/)の結果を変更前の記録と比較し、 検証完了まで旧パッケージ・設定とバックアップを保持します。 #### 注意事項 - メジャーバージョンのアップグレードではDBファイル形式が変わる場合があります。必ずリリースノートを確認し、事前にバックアップしてください。 - `conf/machbase.conf`、`dbs/`、`meta/`、`package/`を削除・初期化しないでください。 --- title: "3.5 インストール検証チェックリスト" url: https://docs.machbase.com/ja/dbms/installation-deployment-upgrade/validation-checklist/ language: ja kind: page --- # 3.5 インストール検証チェックリスト インストール検証はプロセスの生存確認だけでは完了しません。正しいバージョンと設定のサーバーに 実際のクライアントが接続し、権限の範囲内でデータを書き込み・検索できる必要があります。 以下をサーバー状態 → 接続 → バージョン・ライセンス → SQL → Clusterのレプリケーションの順に確認します。 各結果に実行ホスト、インストールホーム、接続先アドレス・ポート、時刻、エラーを記録します。 アップグレードの場合は変更前の記録と比較してください。`SYS`/`MANAGER`は初期実習の接続例であり、 実際のアカウントに置き換えます。実習テーブル名が既存業務オブジェクトと重複しないことも先に確認します。 ## Standard Editionのチェックリスト ### 1. サーバープロセスの確認 ```bash machadmin -e # Machbase server is running with PID(). ``` プロセスを直接確認することもできますが、別のインストールホームで実行されたサーバーと区別する必要があります。 `MACHBASE_HOME`が検査対象インスタンスを指すことを確認します。 ```bash ps -ef | grep machbased | grep -v grep ``` ### 2. ポートのリスニング確認 ```bash ss -tlnp | grep 5656 # LISTEN 0 128 0.0.0.0:5656 ... ``` 現在のOSに合うポート確認ツールを使用します。例の`5656`は実際のSQLポートに置き換え、受信アドレスが 意図したインターフェースか確認します。リスナー確認とリモートクライアントの接続成功は別の検査のため、 アプリケーションを実行するホストでも接続を試します。 ### 3. machsqlの接続テスト ```bash machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER # MACHBASE_CONNECT_MODE=INET, PORT=5656 EDITION=STANDARD # Mach> ``` ローカル接続が成功してリモート接続だけ失敗する場合は、アドレス・ポート、リスナー設定、ファイアウォールを 確認します。認証エラーはユーザー名・認証方式・有効期限を確認し、接続成功後のオブジェクトアクセスエラーは 現在のデータベースとSQL権限を別途確認します。 ### 4. バージョンの確認 ```sql SELECT * FROM V$VERSION; SELECT CURRENT_DATABASE(); ``` ### 5. ライセンスの確認 ```sql SELECT ID, ISSUE_DATE, TYPE, VIOLATE_STATUS FROM V$LICENSE_INFO; ``` `VIOLATE_STATUS`が0か確認し、インストールしたライセンスの種類・期間が運用計画に合うか確認します。 違反状態の場合は`VIOLATE_MSG`とサーバーログで原因を確認します。 ### 6. 基本クエリのテスト ```sql CREATE LOG TABLE check_test (id INTEGER, ts DATETIME); INSERT INTO check_test (id, ts) VALUES (1, NOW); SELECT id, ts FROM check_test; DROP TABLE check_test; ``` 入力した`id=1`の1行と時刻が返り、DROPが成功することを確認します。この検査は基本的なLOG入力経路だけを 確認します。実際のサービスでTAG・TRANSACTION・Appendなどを使用する場合は、該当テーブルとSDKでも 代表的な入力・検索を実行します。 ## Cluster Editionの追加チェックリスト ### 7. クラスターノードの状態確認 ```bash machcoordinatoradmin --cluster-status # デプロイ記録のノード数と役割別状態を比較 ``` ### 8. Brokerの接続テスト ```bash machsql -s 192.168.1.11 -P 5656 -u SYS -p MANAGER ``` ```sql SELECT * FROM V$NODE_STATUS; ``` Coordinatorの`primary`、Brokerの`leader`、Warehouseのレプリケーション状態など、正常状態の表示は 役割ごとに異なります。全ノードを単一の文字列と比較せず、目標状態と実際の状態、グループ構成、アドレスが デプロイ記録と合うか確認します。 ### 9. データレプリケーションの確認 まずBroker経由の入力・検索を確認し、次にWarehouseグループのレプリケーション状態を確認します。 Brokerで1行が検索できるだけでは、全レプリカの同期を証明できません。 ```sql -- Broker経由でデータを入力 CREATE LOG TABLE cluster_check_test (id INTEGER, ts DATETIME); INSERT INTO cluster_check_test (id, ts) VALUES (1, NOW); -- Brokerで入力結果を確認 SELECT COUNT(*) FROM cluster_check_test; ``` Warehouseへの直接SQL接続は通常のアプリケーション経路ではなく、レプリケーション診断用の管理手順です。 `machcoordinatoradmin --cluster-status`で同じレプリケーショングループのactive・standbyピアを確認し、 必要な場合のみ各ピアのネイティブポートへ管理アカウントで接続して同じ検索結果を比較します。 異なるWarehouseグループの全ノードが同じ行を持つとは考えないでください。 検証後はBroker接続でテーブルを削除します。 ```sql DROP TABLE cluster_check_test; ``` --- ## 完了基準と問題発生時の対応 サーバー・接続・権限・代表SQLと必要なレプリケーション検査がすべて通れば、サービスの引き継ぎを進めます。 永続性の検証が必要な場合は、専用の検証環境にデータを残し、正常な再起動の前後で結果を比較します。 業務データのあるサーバーを、単純なインストール確認のために再初期化しないでください。 失敗時は最初のエラーと関連ログを保持し、失敗した段階から原因を絞り込みます。 - サーバーログ: `$MACHBASE_HOME/trc/machbase.trc` - [運用・障害診断](/ja/dbms/operations-configuration-recovery/diagnosis-observability/)を参照 --- title: "4. テーブルタイプとスキーマ設計" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/ language: ja kind: section --- # 4. テーブルタイプとスキーマ設計 この章では、保存するデータの意味と変更・クエリ要件を、Machbase DBMS のテーブルと列へ具体化します。 稼働を確認したら、まず1行に何を保存するかを決めます。慣れたタイプを先に選んですべてのデータを 当てはめると、履歴、更新範囲、保持ポリシーの要件が衝突することがあります。 各タイプの役割を初めて学ぶ場合は、[データモデルの概念](/ja/dbms/core-concepts/concepts/)を先に読んでください。 この章では概念を実際のスキーマと検証可能な設計に結び付けます。 ## 設計の出発点 テーブル名より先に、1行の意味を文章で定義します。「1つのセンサーの1回の計測」、 「設備状態の変化イベント」、「1台の機器の現在の設置情報」は異なる単位です。 同じ設備のデータでも、保存上の役割は異なります。 次の問いに答えると、テーブルを選ぶ根拠が得られます。 | 設計上の問い | 決定事項 | |---|---| | 1行は何を表すか | 計測、イベント、現在状態、参照データのどれを保存するか | | 対象をどう識別するか | タグ名、業務キー、重複収集の識別基準 | | 時刻や軸は何を意味するか | 計測時刻、受信時刻、距離・位置 | | 値をどう解釈するか | 単位、型の範囲、精度、NULL・欠測処理 | | どの変更が必要か | 追記、過去値の補正、キー変更、削除範囲 | | どのクエリが多いか | タグ・時間範囲、条件検索、キー検索、集計、結合 | | どれだけ保持するか | 元データ・集計・参照履歴の期間と再起動後の復旧 | | 失敗時に何を戻すか | テーブル・API 別のトランザクション範囲と再試行・再構築手順 | データサイズや入力頻度だけでタイプを決めないでください。同じ行の値が同じ観測やイベントを表すことを 確認し、関連データは共通識別子で結合できるようにします。結合キーがあることと、DBMS がすべての 業務上の関係を自動的に強制することは別です。対応する制約をタイプ別に確認します。 ## この章の構成 | 順序 | 節 | 設計結果 | |-----:|---|---| | 4.1 | [テーブルタイプの選択](./table-types-selection-type/) | 変更・クエリ・永続性・Edition の要件に合うタイプ | | 4.2 | [スキーマオブジェクトの定義](./schema-objects-definition/) | 列と型、識別子、デフォルト・制約、インデックス、VIEW | | 4.3 | [データ変更ポリシー](./alter-data-mutation-policy/) | 許可する補正・削除と失敗処理の範囲 | | 4.4 | [アンチパターン](./table-types-patterns-type-anti/) | 要件に合わない選択を修正する根拠 | | 4.5 | [モデリングパターン](./patterns-modeling/) | 履歴・状態・参照データを組み合わせる具体例 | 4.1でタイプを選び、4.2と4.3で構造と変更方針を定義します。4.4のアンチパターンを点検し、 4.5のパターンを実データに適用します。比較表は出発点です。実際の SQL と条件は、 リンクしたテーブル別の文書とリファレンスで確認します。 ## 設備監視の例 温度、アラーム、機器情報、画面表示用の状態をすべて同じ方式で保存する必要はありません。 | データ | 1行の意味 | 検討する保存方法 | |---|---|---| | 温度履歴 | 1センサーが特定時刻に測定した値 | タグ・時間範囲クエリと集計用の TAG | | アラーム履歴 | 特定時刻のアラームイベント | 追記型イベント用の LOG | | 機器の参照データ | 機器の名前・場所・許容基準 | LOOKUP、または複数変更をトランザクションにまとめる場合の TRANSACTION | | 画面用の現在状態 | 再計算できる最新状態 | 元データと再構築経路がある場合の VOLATILE | この表は例であり、固定の正解ではありません。複数項目が1イベントに含まれる場合や、更新・保持要件が 異なる場合は、別の設計が適切なこともあります。TRANSACTION は Standard Edition の対応も確認します。 温度履歴に最新の機器情報を結合すると、結果は現在の名前や場所で解釈されます。計測時点の場所や 許容基準が必要なら、元データに保存するか参照データの変更履歴を設計します。現在状態キャッシュも 更新する場合、元データ入力とキャッシュ更新を1トランザクションと考えず、失敗後の再構築方法を用意します。 ## 小さなデータで設計を検証 運用規模へ拡大する前に、代表データと頻出クエリで次を確認します。 1. 正常値だけでなく NULL、欠測、境界値、重複・遅延データを入力します。 2. 元データと集計のクエリが同じ時刻基準・単位・NULL 方針を使うか確認します。 3. 補正・削除・再入力後の結果と、他の行や集計への影響を比較します。 4. 再起動後も保持するデータと再生成する状態を分け、復旧順序を確認します。 5. 入力量、クエリ範囲、同時実行数を増やし、スループット・遅延・保存領域を測定します。 入力エラー、旧スキーマを使うアプリケーション、再起動後の復旧も、通常経路と併せて設計します。 スキーマ変更前には既存データとビュー・ROLLUP・クライアントの依存関係を確認し、 必要なら新テーブルへ移行して検証後に切り替えます。 実装は[テーブル別利用ガイド](/ja/dbms/)と[開発とアプリケーション連携](/ja/dbms/development-tools-integration/)、 測定は[性能チューニング](/ja/dbms/performance-tuning/)に進みます。 --- title: "4.1 テーブルタイプの選択" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/table-types-selection-type/ language: ja kind: page --- # 4.1 テーブルタイプの選択 タイプの選択を誤ると性能低下や機能制限につながるため、設計初期にデータの性質に合うタイプを決めます。 - **[タイプ選択ガイド](/ja/dbms/data-modeling-table-design/table-types-selection-type/#selection-decision)** - **[タイプ比較表](/ja/dbms/data-modeling-table-design/table-types-selection-type/#comparison-tag-log-rdb-volatile-lookup)** - **[TRANSACTION と LOOKUP の比較](/ja/dbms/data-modeling-table-design/table-types-selection-type/#comparison-rdb-vs-lookup)** 役割と保存の概念は[データモデルの概念](../../core-concepts/concepts/#time-series)を参照してください。 同じデータでも、履歴を蓄積するか現在状態を更新するかで適切なタイプが変わります。 変更・クエリ・永続性の要件を併せて検討します。 ### 選択前に記述するデータの説明 テーブル名より先に、1行が表す事実を1文で記述します。同じ設備でも、1回の温度計測、 現在の運転状態、1件の保守作業は異なる単位であり、キーと変更方法も異なります。 | 設計上の問い | 設備監視で決める内容 | |---|---| | 1行は何か | センサーの1回の計測か、設備の現在状態か | | 何で検索するか | センサー名と発生時刻、設備 ID、保守作業番号 | | 値はどう変わるか | 履歴の追加、誤値の補正、現在行の上書き | | 同時に確定する変更があるか | 保守作業登録と部品数量変更を1トランザクションにまとめるか | | どれだけ保持するか | 元データ・集計の期間と、再起動後の再生成可否 | | 規模はどの程度か | タグ数、毎秒行数、行サイズ、参照データとインデックスのメモリ | 例えば温度履歴は TAG、アラームイベントは LOG、設備コード表は LOOKUP が候補です。 部品在庫変更と作業登録を同時に確定するなら Standard Edition の TRANSACTION を検討します。 現在状態キャッシュは元データから再構築できる場合に VOLATILE へ分離できます。 1テーブルへ統合する前に、行の意味と失敗時の復旧方法を整合させます。 ## タイプ選択ガイド 次の流れで候補を絞り、比較表で DML、トランザクション、メモリ、Edition の要件を確認します。 参照データでも複数変更を1トランザクションへまとめる場合は、LOOKUP ではなく TRANSACTION を検討します。 ### 選択フロー ``` センサー/機器の計測値か? ├── YES → 時間軸か? YES → TAG TABLE (BASETIME) │ 距離軸か? YES → TAG TABLE (BASEDISTANCE) └── NO ↓ イベント/ログ/パケットか?(追記専用) ├── YES → LOG TABLE └── NO ↓ コード表/参照データか?(繰り返し検索・更新) ├── YES → LOOKUP TABLE └── NO ↓ 再起動時に破棄できるインメモリ状態/キャッシュか? ├── YES → VOLATILE TABLE └── NO ↓ 一般的なリレーショナル業務データ(UPDATE/DELETE/SELECT/INSERT がすべて必要) └── TRANSACTION TABLE ``` ### 主な判断基準 | 問い | タイプ | |------|------| | 時間または距離に基づく計測値か | TAG | | 元イベントを追記し、古い範囲だけを削除するか | LOG | | PRIMARY KEY が必要な参照データを繰り返し検索・更新するか | LOOKUP | | 再起動でデータが消えてもよいか | VOLATILE | | 一般的なリレーショナル業務(INSERT/UPDATE/DELETE/SELECT)か | TRANSACTION | ### 注意事項 - イベントごとに一意なタグ名を付けると、タグ数とメタデータが増え続けます。 繰り返し計測する対象がないイベントには LOG を検討します。 - LOG は UPDATE と一般条件 DELETE ができないため、更新が必要なデータには不適切です。 保持・整理用の `BEFORE`、`OLDEST`、`EXCEPT` DELETE を使用します。 - TRANSACTION は Standard Edition 専用です。Cluster では小規模 LOOKUP または外部 RDBMS を使用します。 - VOLATILE のデータは再起動で消失します。 ## タイプ比較表 ### 機能比較 | 項目 | TAG | LOG | TRANSACTION | VOLATILE | LOOKUP | |------|-----|-----|-----|----------|--------| | DDL | `CREATE TAG TABLE` | `CREATE LOG TABLE` | `CREATE TABLE` / `CREATE TRANSACTION TABLE` / `CREATE TXN TABLE` | `CREATE VOLATILE TABLE` | `CREATE LOOKUP TABLE` | | 主用途 | センサー・計測 | イベント・ログ | リレーショナル業務 | 一時集計 | コード・参照データ | | INSERT | O | O | O | O | O | | UPDATE | O(Standard、タグ/BASETIME 条件) | X | O | O | O | | DELETE | O(BEFORE/条件/全体) | O(BEFORE/OLDEST/EXCEPT/全体) | O | O(PK 一致/全体) | O(一般条件/全体) | | PRIMARY KEY | 必須 | X | 任意 | 任意 | 必須 | | BASETIME | 必須(時間軸) | X | X | X | X | | _arrival_time | X | 自動追加 | X | X | X | | インデックス | タグ・軸アクセス、対応するセカンダリ | BITMAP/KEYWORD/LSM | BTREE PK + セカンダリ | キー・セカンダリ | キー・セカンダリ | | 永続性 | O | O | O | X(メモリ) | O | | Cluster Edition | O | O | X | O | O | Append API の対応は、テーブルだけでなく SDK と入力経路でも変わります。 [SDK Append 対応表](../../development-tools-integration/sdk-support-scope/#append-table-type-matrix)で 使用するドライバーとテーブルの組み合わせを確認します。 ### ストレージ特性 | 項目 | TAG | LOG | TRANSACTION | VOLATILE | LOOKUP | |------|-----|-----|-----|----------|--------| | ストレージ | 列指向 | 列指向 | 行指向(リレーショナル) | メモリ | 永続保存 + 全行がメモリに常駐 | | 容量検討基準 | タグ数・元データ・ROLLUP・保持期間 | 元データ・検索インデックス・保持期間 | 行・インデックス・トランザクション負荷 | 全行とインデックスのメモリ | 全行とインデックスのメモリ、再起動時のロード時間 | インメモリテーブルが小さいとは、固定の行数を意味しません。行幅、可変長値、セカンダリインデックスを 含めて実メモリ使用量を測定します。ディスク型でも圧縮率やサーバー仕様だけで性能は保証されないため、 代表的な入力とクエリを同時に実行します。 ### TRANSACTION の制約 TRANSACTION には次の制約があります。 - **Cluster Edition 非対応**: Standard Edition 専用。 - **最小列数**: 1列以上。 ## TRANSACTION と LOOKUP の比較 両方ともリレーショナルデータを保存しますが、対象規模と機能が異なります。 ### 比較表 | 項目 | TRANSACTION | LOOKUP | |------|-----------|--------------| | DDL | `CREATE TRANSACTION TABLE` | `CREATE LOOKUP TABLE` | | PRIMARY KEY | 任意 | 必須 | | INSERT | O | O | | UPDATE(WHERE あり) | O | O | | UPDATE(WHERE なし) | O(全行) | X | | DELETE | O | O | | 明示的トランザクション | 複数文を COMMIT/ROLLBACK で制御 | 参加せず、文ごとに変更 | | インデックス | BTREE PK + セカンダリ | メモリ上のキー・セカンダリ | | データ規模 | ディスク容量とトランザクション負荷で検証 | 参照データの検索・更新負荷で検証 | | JOIN 対象 | O | O | | Cluster Edition | X | O | ### 選択ガイド **TRANSACTION を選ぶ場合** - 明示的トランザクションとリレーショナル DML が必要。 - UPDATE・DELETE・INSERT・SELECT がすべて必要な一般的ワークロード。 - PRIMARY KEY なしで多様な列の組み合わせを検索。 - Standard Edition 環境。 **LOOKUP を選ぶ場合** - コード表と参照データ。 - PRIMARY KEY 検索と単一行 UPDATE/DELETE が必要。 - Cluster Edition でも使用。 - 参照データをリアルタイムに更新。 ### 例 ```sql -- LOOKUP: 国コード表(PK 検索と条件付き UPDATE) CREATE LOOKUP TABLE country_code ( code VARCHAR(4) PRIMARY KEY, name VARCHAR(64) ); INSERT INTO country_code VALUES ('KR', 'Republic of Korea'); UPDATE country_code SET name = 'Korea' WHERE code = 'KR'; SELECT code, name FROM country_code WHERE code = 'KR'; -- TRANSACTION: 注文履歴(大規模、一般 UPDATE/DELETE 対応) CREATE TRANSACTION TABLE order_history ( order_id LONG PRIMARY KEY, item_id INTEGER, qty INTEGER, amount DECIMAL(18,2) ); INSERT INTO order_history VALUES (12345, 501, 1, 12000.00); UPDATE order_history SET qty = 10 WHERE order_id = 12345; SELECT order_id, qty, amount FROM order_history WHERE order_id = 12345; DELETE FROM order_history WHERE order_id = 12345; SELECT COUNT(*) FROM order_history WHERE order_id = 12345; ``` 最初の SELECT は変更後の国名、注文 SELECT は数量 `10`、最後の COUNT は `0` を返します。 この例の `amount` は数量変更と別に維持する金額で、自動再計算されません。実際の注文モデルでは 単価・数量・合計の関係と、一緒に変更する列を明示します。終了後、例で作ったテーブルだけを `DROP TABLE` で削除します。 --- title: "4.2 スキーマオブジェクトの定義" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/schema-objects-definition/ language: ja kind: page --- # 4.2 スキーマオブジェクトの定義 テーブル、列、インデックス、VIEW の設計時に決定する事項をまとめます。SQL 構文とオプションは 重複掲載せず、[SQL 構文リファレンス](/ja/dbms/reference/sql/syntax/)を正本とします。 - **[テーブルの作成と削除](#create-delete)** - **[テーブル変更](#alter)** - **[列とデータ型の選択](#selection-type-column-data-types)** - **[制約とデフォルト値](#constraints-defaults-condition)** - **[インデックス設計](#index-create-delete)** - **[VIEW 設計](#create-view)** ## テーブルの作成と削除 先に[テーブルタイプの選択](../table-types-selection-type/)を完了します。そのタイプに応じて テーブル名、列、キー、制約、インデックス、VIEW を定義します。 ### 行の単位と列の役割 1テーブル内で行の単位を統一します。設備の日次要約と秒単位の元データを同じ意味の行として 混在させると、`COUNT` や `AVG` を解釈しにくくなります。元データと集計には、それぞれ明確な 行の単位とクエリ名を定めます。 | 列の役割 | 例 | 設計原則 | |---|---|---| | 対象の識別 | `sensor_id`, `equipment_id` | 表示名とは別の安定した値 | | 発生基準 | `measured_at`, `event_time` | 発生時刻か受信時刻かを明示 | | 計測値 | `temperature_c`, `pressure_kpa` | 単位、有効範囲、補正方法を定義 | | 品質 | `quality_code` | 欠測、計測失敗、有効な0を区別 | | 参照属性 | 場所、設備タイプ | タグメタデータか別の参照表で管理するか選択 | 外部設備コードなど既存の業務キーは自然キー、別途発行する番号はサロゲートキーです。コード変更や 複数収集元での再利用がある場合は識別範囲を明確にするか、サロゲートキーを検討します。自動増分番号は 生成順序の値であり、発生時刻や重複のない収集を自動保証しません。TAG の名前は計測行ではなくタグを識別します。 テーブル名は英字で始め、英字・数字・アンダースコアを使います。予約語やシステムオブジェクトと 紛らわしい名前は避けてください。削除前に依存する VIEW、インデックス、ROLLUP、保持ポリシーを確認します。 タイプ別の作成例は次を参照してください。 - [TAG テーブル作成](/ja/dbms/tag-table-usage/create-alter-drop/) - [LOG テーブル作成](/ja/dbms/log-table-usage/create-alter-drop/) - [TRANSACTION テーブル](/ja/dbms/rdb-table-usage/) - [LOOKUP テーブル](/ja/dbms/lookup-table-usage/) - [VOLATILE テーブル](/ja/dbms/volatile-table-usage/) ## テーブル変更 列の追加・削除・名前変更・型変更の対応は、タイプとデータ有無によって異なります。 運用テーブルを変える前に、次の順で判断します。 1. 対象 Edition とタイプが該当 `ALTER TABLE` に対応するか確認します。 2. 既存データ、インデックス、VIEW、アプリケーションの列順序依存を確認します。 3. 運用と同じスキーマ・データ量で実行時間とロックの影響を測定します。 4. 戻すのが難しい場合、新テーブルを作成し、検証後に切り替えます。 列追加後は、既存行と新規入力行をそれぞれ検索し、NULL・DEFAULT の結果を確認します。 すべてのテーブルで既存行が DEFAULT になるわけではありません。VOLATILE の既存行や TAG メタデータの 自動登録行には別の規則があります。[ARRAY の DEFAULT 規則](/ja/dbms/reference/sql/types/array/#default와-기존-row) を含め、対象タイプの DDL 仕様を確認してください。 アプリケーションのデプロイとスキーマ変更の順序も定めます。対応経路では列リストを明示し、 位置に依存する Append・バインドを新スキーマと照合します。移行時は行数だけでなく、キー別件数、 時間範囲、NULL 比率、代表集計も比較し、切り替え中の新規行の欠落・重複への対応を定めます。 正確な対応と構文は [ALTER TABLE リファレンス](/ja/dbms/reference/sql/syntax/)と [テーブルタイプ別サポート](/ja/dbms/reference/support-scope-constraints/table-types-type/)を参照してください。 ## 列とデータ型の選択 実際の値範囲と演算に基づき、適切な最小の型を選びます。表示形式と保存型を混同しないでください。 | データ | 検討する型 | 注意点 | | --- | --- | --- | | 整数の計測値・コード | `SHORT`・`INTEGER`・`LONG` 系 | NULL 予約値と範囲 | | 浮動小数点の計測値 | `FLOAT`・`DOUBLE` | 精度、集計誤差、NULL 予約値 | | 正確な小数計算が必要な値 | `DECIMAL` | precision・scale・丸め規則を先に定義 | | 時刻 | `DATETIME` | 表現範囲とタイムゾーンをクライアント・セッション方針と設計 | | 短い文字列 | `VARCHAR` | 最大長とエンコーディング | | 長い本文 | `TEXT` | 対応タイプ、ソート・集計制約、インデックスコスト | | ネットワークアドレス | `IPV4`・`IPV6` | 文字列ではなくアドレス型を検討 | | 構造化文書 | `JSON` | サイズ、列への昇格基準、タイプ別対応 | | バイナリ | `BINARY` | タイプによって可変長・固定長が異なる | | 固定個数の数値 | 数値 `ARRAY` | 要素の型・長さ、要素 NULL と全体 NULL の区別 | `VARCHAR(n)` の長さはバイト数で、韓国語や絵文字では文字数と異なります。整数型は一部の境界値を NULL 用に予約するため、プログラミング言語の整数範囲をそのまま使えません。FLOAT・DOUBLE も 正の最大値を NULL と認識します。型の小ささより、有効範囲と演算の意味を優先します。 ### 正確な小数が必要な値: DECIMAL 金額、税率、精算値など10進の正確さが必要なら `DECIMAL` を使います。誤差を許容し広い指数範囲を 必要とする計測には `FLOAT`・`DOUBLE` を使います。違いは保存サイズではなく値の意味です。 丸め結果を業務にそのまま使う値には DECIMAL を選びます。 設計時に次を決めます。 | 決定事項 | 内容 | |---|---| | precision | 有効数字の総桁数、1~65 | | scale | 小数桁数、0~30、precision 以下 | | 省略時 | `DECIMAL` は `DECIMAL(10,0)`、`DECIMAL(M)` は `DECIMAL(M,0)` | scale を超える小数は、入力時に最も近い値へ丸め、ちょうど半分なら0から遠ざかる方向へ丸めます。 保存時に確定するため業務規則と一致するか確認します。precision を超える値は切り詰めや浮動小数点変換ではなく エラーになるため、桁数には余裕を持たせます。 `SUM`、`AVG`、`MIN`、`MAX`、`GROUP BY`、`ORDER BY`、`DISTINCT` は正確な計算経路を使います。 一方、パーセンタイルや高度な統計など、exact DECIMAL 経路がない演算は DOUBLE へ変換し、近似値となります。 正確さが必要な集計と参考用の統計を区別します。 アプリケーション側で浮動小数点を経由すると、保存型に関係なく精度を失います。JDBC は `BigDecimal`、 Python は `decimal.Decimal`、ODBC は `SQL_NUMERIC` など、10進表現または文字列で渡します。 宣言、インデックス、クライアントの対応は [DECIMAL と NUMERIC 固定小数点型](/ja/dbms/reference/sql/types/decimal-numeric-fixed-point/)を参照してください。 ### 構造化文書: JSON 収集元でキーが異なる、または項目が増える追加属性には `JSON` が適しています。スキーマ変更なしに 項目を追加できるためです。一方、`WHERE` や `GROUP BY` に頻繁に使う値は別の列に昇格します。 JSON は主キーにできず、LOOKUP は JSON パスインデックスをサポートしません。 1文書は最大32,768バイト、JSON パスは最大512バイトです。元のペイロード全体を保存するより、 クエリに必要な属性を格納するために使います。 | テーブルタイプ | JSON 列 | 確認事項 | |---|:---:|---| | TAG・LOG・TRANSACTION | O | JSON 関数とパスクエリに対応 | | LOOKUP | O | 一般列として対応、JSON パスインデックスは非対応 | | VOLATILE | X | JSON 列を作成不可 | クエリには `->` と `JSON_EXTRACT_*` を使います。`JSON_SET` 系は変更後の文書を返す関数であり、 列へ保存するには対象テーブルの `UPDATE` 制約に従います。LOG は行の `UPDATE` に対応しません。 TAG METADATA では既存の JSON 列を参照して更新できますが、Standard Edition の TAG DATA UPDATE では既存行の列を参照する SET 式を使用できません。入力時に文書を完成させるか、 対象に適した更新方法を選択します。関数別の対応は [JSON のテーブルタイプ別サポート](/ja/dbms/reference/sql/types/table-types-type-support-scope-json/)を参照してください。 ### 型の選択前に確認する制約 | 型 | 設計時の確認事項 | |---|---| | `TEXT` | LOG と Standard Edition の TRANSACTION だけで対応。LOG の TEXT は `ORDER BY`・`GROUP BY` に使えず、`MODIFY COLUMN` で VARCHAR に変換できない。ソート・集計値は別の VARCHAR・数値列に保存。 | | `BINARY` | LOG は可変長で最大64MB、TAG は固定長 `BINARY(n)` で1~32,767バイト。LOOKUP・VOLATILE は非対応。 | | `DATETIME` | 1970-01-01~2262-04-11をナノ秒精度で保存。期限や無期限を表すため任意の遠い未来時刻を入れない。 | | `ARRAY` | 固定長の1次元数値配列。要素数は1~1024。全体 NULL と要素 NULL を区別。 | 全範囲とタイプ別対応は[データ型リファレンス](/ja/dbms/reference/sql/types/)を基準に確認します。 ## 制約とデフォルト値 `PRIMARY KEY`、`NOT NULL`、`DEFAULT` の対応はタイプごとに異なります。TAG の `PRIMARY KEY` は タグ識別子、LOOKUP・VOLATILE・TRANSACTION の `PRIMARY KEY` は行識別と更新経路を決定します。 NULL は未知または欠けた値で、0や空の区間とは異なります。計測失敗を DEFAULT 0 に置き換えると 平均や正常判定が歪みます。`COUNT(*)` は行数、`COUNT(value)` はその列が非 NULL の行数なので、 サンプル数を報告する際に区別します。 デフォルト値は省略入力への方針であり、妥当性検証の代わりではありません。テーブルにない制約は 収集・業務アプリケーションで検証します。外部キーなど他 DBMS の制約を名前だけで対応と判断せず、 [TRANSACTION のサポート範囲](/ja/dbms/reference/support-scope-constraints/rdb/)を確認します。 `_ARRIVAL_TIME` や `_RID` などのシステム列を業務キーに使わないでください。公開されたクエリ上の 意味が必要な場合だけ参照し、保存構造や生成方式には依存しません。 ## インデックス設計 インデックスはクエリコストを下げますが、入力・保存コストを増やします。 代表クエリを記述し、条件に一致する行の比率(選択性)を確認します。全設備の月平均と、1台の設備の 特定注文検索ではアクセスが異なります。すべてのフィルター・結合列を索引化せず、`EXPLAIN` と 実測時間を比較して有効なインデックスを残します。 - 時間範囲とタグ識別子で十分な TAG クエリには、最初から追加インデックスを作りません。 - LOG の頻出フィルター列は、計画と選択性を測定してから索引化を検討します。 - LOOKUP・VOLATILE・TRANSACTION はキー検索と結合条件を基準に設計します。 - 長いテキストの単語検索には、そのタイプが対応する `KEYWORD` を検討します。 作成・削除構文と対応タイプは[インデックス SQL リファレンス](/ja/dbms/reference/sql/syntax/)を参照してください。 ## VIEW 設計 VIEW は繰り返すクエリに名前を付けますが、結果自体は保存しません。意図しない時間範囲の固定や 不要な全列の読み出しを避け、元テーブル・列の変更前に依存 VIEW を確認します。 頻出の列リストや単位変換を VIEW で一貫して提供できます。ただし作成だけでデータがコピーされたり、 クエリコストが下がったりするわけではありません。過去イベントと最新参照表を結合した VIEW では、 参照表変更で過去の結果も変わる場合があります。発生時点の属性が必要なら、バージョン別参照情報や 元の行に記録した属性を使います。 VIEW の作成・クエリ・削除と制約は[VIEW SQL リファレンス](/ja/dbms/reference/sql/syntax/)を参照してください。 --- title: "4.3 データ変更ポリシー" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/alter-data-mutation-policy/ language: ja kind: page --- # 4.3 データ変更ポリシー `UPDATE`、`DELETE`、`TRUNCATE` のサポートはタイプごとに異なります。このページではモデル選択に 必要な方針をまとめます。正確な構文と制約はリンク先の SQL リファレンスを基準にしてください。 変更ポリシーは、更新できるかだけでなく、誰がどの範囲を変え、失敗時にどこまで戻せるかを定めます。 現在状態の更新、元の計測値の補正、スキーマ変更、保持期限による削除を別々の処理として区別します。 ## テーブルタイプ別の変更サポート | テーブルタイプ | UPDATE | DELETE | TRUNCATE | |------------|--------|--------|----------| | TAG | Standard の DATA 補正: タグ選択と BASETIME の条件が必要 | `BEFORE`、タグ/軸条件、または全削除 | X | | LOG | X | `BEFORE`、`OLDEST`、`EXCEPT`、全削除 | O | | TRANSACTION | O | O | O | | VOLATILE | 主キー条件 | 主キー条件または全削除 | X | | LOOKUP | 一般条件式、PK 変更不可 | 一般条件式または全削除 | X | LOG は入力したイベントを更新しない構造です。頻繁に変更する状態や設定は VOLATILE、LOOKUP、 TRANSACTION に保存してください。 ## 変更単位と失敗処理 | 操作 | モデルで決める事項 | |---|---| | 現在の設定値の更新 | キー、許容値、同時更新者の処理 | | 誤った計測値の補正 | タグ・時間範囲、補正理由、ROLLUP 再計算 | | LOG イベントの訂正 | 原文を残して補正イベントを関連付けるか | | 参照キーの置き換え | 参照データの切り替え順序と途中失敗の処理 | | 期間削除 | 保持基準時刻、削除範囲、必要なバックアップ | 複数の TRANSACTION DML は明示的トランザクションにまとめられます。LOOKUP・VOLATILE の変更や LOG・TAG 入力も同じトランザクションに参加すると考えないでください。TAG 履歴の保存後に VOLATILE キャッシュ更新が失敗しても履歴は残る場合があり、再構築や再試行が必要です。Append の参加範囲は API と対象タイプで異なるため、[SDK サポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/)で確認します。 複数行を変更する前に、同じ条件で件数と代表行を確認します。この事前検索は行をロックせず、 後の変更範囲を固定するものでもありません。同時入力・更新がある場合は作業時間と対象範囲も制御し、 結果の影響行数と変更後の値を確認します。 ## UPDATE ポリシー ### TRANSACTION, VOLATILE, LOOKUP - TRANSACTION は一般的なリレーショナル `UPDATE` とトランザクションをサポートします。 - VOLATILE は主キーの一致条件で対象を指定します。 - LOOKUP は一般条件式を使えますが、主キー列そのものは変更できません。 LOOKUP UPDATE には WHERE が必要です。LOOKUP・VOLATILE の主キー変更は削除と新キー入力を 別々の文で行うため、元データの保護と参照の切り替え順序を先に定めます。 両方をまとめてロールバックする必要がある場合は TRANSACTION を検討します。 LOOKUP の対応述語と式は [LOOKUP 述語 UPDATE](/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-update-syntax/)を参照してください。 ### TAG data UPDATE TAG の実際の時系列データとメタデータは、異なる構文で更新します。 | 対象 | 構文 | 主な制約 | |------|------|-----------| | 時系列データ | `UPDATE tag_table SET ... WHERE ...` | タグ選択と BASETIME の両条件が必要 | | メタデータ | `UPDATE tag_table METADATA SET ...` | TAG メタデータ専用構文 | TAG data UPDATE は Standard Edition の論理 TAG テーブルでサポートされます。タグ名、BASETIME、 メタデータ列は `SET` の対象にできません。修正範囲にマテリアライズ済みの集計があれば `ROLLUP_REBUILD` で再構築してください。 TAG DATA の SET 右辺は既存行の列を参照できません。`SET value = value + 1` のような一括加算では 補正しません。計算済み補正値を定数またはパラメーターで渡し、必要範囲に限定します。 補正履歴が必要なら上書きだけでなく、変更前後の値と理由を別の履歴に保存します。 構文と許容式は次のリファレンスを正本とします。 - [TAG data UPDATE](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/) - [TAG data UPDATE の WHERE/SET 制約](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-where-set-constraints/) - [TAG メタデータ](/ja/dbms/tag-table-usage/tag-metadata/) LOG は `UPDATE` をサポートしません。 ## DELETE ポリシー ### TRANSACTION, VOLATILE, LOOKUP - TRANSACTION は一般的な `WHERE` 条件で削除できます。 - VOLATILE は主キー条件で削除するか、条件なしで全行を削除できます。 - LOOKUP は一般条件式で削除するか、`WHERE` なしで全行を削除できます。 LOOKUP の対応述語は [LOOKUP 述語 DELETE](/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-delete-syntax/)を参照してください。 ### LOG LOG は任意の一般的な `WHERE` ではなく、ログ保持用の削除構文を使います。`OLDEST`、`EXCEPT`、 `BEFORE`、全削除から目的に合う形式を選びます。正確な構文と実行例は [LOG データライフサイクル](/ja/dbms/log-table-usage/operations-lifecycle/)を参照してください。 ### TAG/KV TAG/KV は `BEFORE` で古いデータを削除するか、タグ名と軸条件で対象を選択します。 `BEFORE` の時刻は現在より過去である必要があります。構文は [TAG データ変更](/ja/dbms/tag-table-usage/data-input-mutation/)を参照してください。 保持目的の手動削除を繰り返す場合は [Retention Policy](/ja/dbms/operations-configuration-recovery/policy-data-retention/)を使用します。 ### TAG メタデータ `DELETE FROM table_name METADATA` で削除します。対象のタグに実データが1つでも残っていれば、 文全体が失敗します。 詳細は [TAG メタデータ](/ja/dbms/tag-table-usage/tag-metadata/)を参照してください。 ## TRUNCATE ポリシー `TRUNCATE TABLE` は LOG と TRANSACTION だけでサポートされます。スキーマとインデックス定義を 保持し、すべての行を削除します。 | 項目 | TRUNCATE | DELETE | |------|----------|--------| | 対象 | テーブル全体 | タイプにより全体または条件指定 | | `WHERE` | 不可 | 対応範囲で可能 | | TRANSACTION のロールバック | 明示的トランザクションで可能 | 明示的トランザクションで可能 | 削除前にバックアップと再入力経路を確認します。TAG は対応する `BEFORE` またはタグ/軸条件、 VOLATILE・LOOKUP の全削除は条件なしの `DELETE` を使用します。 TRANSACTION のロールバック可否を LOG の削除へ適用しないでください。確定済みの変更は後の ROLLBACK で戻せません。また、削除と物理ディスク領域の返却は同時とは限らないため、 使用容量と対象テーブルの領域回収状態を確認します。 --- title: "4.4 アンチパターン" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/ language: ja kind: page --- # 4.4 アンチパターン アンチパターンとは、特定のタイプを使うこと自体ではなく、データの意味や要件に合わない使い方です。 各例の前提が業務に当てはまるか確認し、代替案を選びます。同じスキーマでも、現在状態には適し、 履歴の蓄積には適さない場合があります。 - **[LOOKUP に無制限の履歴を蓄積](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#high-frequency-lookup)** - **[センサー別にテーブルを作成](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#per-sensor-create)** - **[不適切なタイプ選択](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#table-types-selection-type-wrong)** - **[VOLATILE を永続保存に使用](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#storage-persistent-volatile)** - **[時系列に TRANSACTION を誤用](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#time-series-storage-misuse-rdb)** ## LOOKUP に無制限の履歴を蓄積 ### 問題 問題は検索頻度ではなく、増え続ける計測履歴を LOOKUP に保存する設計です。LOOKUP は全行と インデックスをメモリに保持するため、長期履歴が増えるほどメモリ負荷も増えます。 小さな参照データをキーで繰り返し検索する用途には適しています。 ### アンチパターンの例 ```sql -- 不適切: センサー計測を LOOKUP に保存 CREATE LOOKUP TABLE sensor_data_wrong ( sensor_id VARCHAR(64) PRIMARY KEY, value DOUBLE, ts DATETIME ); -- sensor_id が PK のため、センサーごとに現在の1行しか保存できない -- 履歴を追加すると同じ PK と競合する INSERT INTO sensor_data_wrong VALUES ('TEMP-01', 25.3, NOW); INSERT INTO sensor_data_wrong VALUES ('TEMP-01', 25.5, NOW); -- PK 重複エラー ``` ### 適切なパターン タグ別の計測履歴の収集・クエリが中心なら TAG を検討します。LOOKUP でも計測ごとに別キーを 付けられますが、全履歴がメモリに常駐するコストは残ります。最新値キャッシュは、性能上必要で 元データから復旧できる場合に VOLATILE で追加します。TAG の最新値クエリで要件を満たすなら 別キャッシュは不要です。 ```sql -- 適切: 履歴は TAG CREATE TAG TABLE sensor_data ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); -- 最新値キャッシュは VOLATILE CREATE VOLATILE TABLE sensor_latest ( sensor_id VARCHAR(64) PRIMARY KEY, value DOUBLE, updated_at DATETIME ); ``` ### 結果 | | アンチパターン(LOOKUP) | 適切な設計(TAG) | |-|-----------------|-----------------| | 同じセンサーキーで履歴を蓄積 | X(このキーは行を識別) | O(タグ名の下に複数計測行) | | 継続入力の経路 | 行識別子中心 | 時系列 Append API を利用可能 | | 時間範囲クエリ | 一般条件検索 | タグ・時間軸の検索 | ## センサー別にテーブルを作成 ### 問題 センサー(タグ)ごとにテーブルを作ると、センサー数に応じて DDL、権限、クエリ対象が増え、 運用コストが高くなります。 ### アンチパターンの例 ```sql -- 不適切: センサーごとにテーブルを作成 CREATE TAG TABLE sensor_temp_01 ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); CREATE TAG TABLE sensor_temp_02 ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); CREATE TAG TABLE sensor_temp_03 ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); -- ... 10,000センサーなら10,000テーブル ``` ### 問題点 | 問題 | 説明 | |------|------| | 管理の複雑化 | テーブル数だけ DDL を管理 | | クエリの複雑化 | センサー間集計に複数テーブルの結合が必要 | | メタデータの増加 | システムカタログの負荷 | | 新センサー追加 | 毎回 DDL が必要 | ### 適切なパターン センサー名を PRIMARY KEY とする1つの TAG テーブルに、すべてのセンサーデータを保存します。 これは同じ列構造・権限・保持ポリシーを共有するセンサー群に適用します。単位、スキーマ、 アクセス権限、保持期間を個別管理するなら、テーブルを分けるのが適切な場合もあります。 センサー数そのものを分割基準にしないことが重要です。 ```sql -- 適切: すべての温度センサーを1テーブルに CREATE TAG TABLE temperature_sensor ( name VARCHAR(128) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); -- すべてのセンサーデータを同じテーブルに入力 INSERT INTO temperature_sensor VALUES ('TEMP-01', NOW, 23.5); INSERT INTO temperature_sensor VALUES ('TEMP-02', NOW, 24.1); INSERT INTO temperature_sensor VALUES ('TEMP-10000', NOW, 22.9); ``` ### 利点 - 新センサー追加に DDL が不要。新しいタグ名で INSERT するだけ。 - センサー間の集計が容易。 - 運用管理対象を削減。 ## 不適切なタイプ選択 データの特性に合わないタイプ選択の代表例です。 ### アンチパターン1: イベントログを TAG に保存 ```sql -- 不適切: イベントログを TAG に保存 CREATE TAG TABLE error_log_wrong ( name VARCHAR(256) PRIMARY KEY, -- イベント内容がタグ名になる time DATETIME BASETIME, level SHORT ); -- 問題: イベントごとに一意な名前を付けるとタグ数が急増 ``` **適切な設計**: LOG テーブルを使用します。 ```sql CREATE LOG TABLE error_log ( level SHORT, msg VARCHAR(512), src VARCHAR(128) ); ``` ### アンチパターン2: センサー値を LOG に保存 LOG にセンサー値を保存すること自体は誤りではありません。問題は、タグ別の計測時刻集計が必要なのに、 実際の計測時刻を省いて受信時刻だけを残すことです。複数項目の設備イベント検索が中心なら LOG が適する場合もあります。 ```sql -- 計測時刻が必要な要件には不十分なスキーマ CREATE LOG TABLE sensor_wrong ( sensor_id VARCHAR(64), value DOUBLE -- 計測時刻がなく、サーバー受信時刻だけを自動保存 ); ``` **適切な設計**: TAG テーブルを使用します。 ```sql CREATE TAG TABLE sensor_measurements ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); ``` ### アンチパターン3: 大量の履歴を LOOKUP に保存 ```sql -- 不適切: リレーショナルトランザクションが必要な注文履歴を LOOKUP に保存 CREATE LOOKUP TABLE order_history_wrong ( order_id LONG PRIMARY KEY, customer VARCHAR(64) -- 全行・インデックスのメモリと明示的トランザクション要件を確認 ); ``` **適切な設計**: TRANSACTION テーブルを使用します。 ```sql CREATE TRANSACTION TABLE order_history ( order_id LONG, customer VARCHAR(64), item_id INTEGER, amount DOUBLE, status VARCHAR(16) ); -- UPDATE/DELETE/SELECT をすべてサポート UPDATE order_history SET status = 'SHIPPED' WHERE order_id = 1001; ``` ### アンチパターン4: 時系列を TRANSACTION に保存 TRANSACTION も時間列と Append API を使用できますが、TAG 専用の時間軸ストレージや ROLLUP はありません。 リレーショナルな変更より計測履歴の収集・集計が中心なら TAG を検討します。詳細は [時系列に TRANSACTION を誤用](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#time-series-storage-misuse-rdb)を参照してください。 ## VOLATILE を永続保存に使用 ### 問題 永続的に保持する必要があるデータを VOLATILE に保存するパターンです。 ### アンチパターンの例 ```sql -- 不適切: 重要な設定を VOLATILE に保存 CREATE VOLATILE TABLE critical_config ( key_name VARCHAR(64) PRIMARY KEY, value VARCHAR(256) ); INSERT INTO critical_config VALUES ('license_key', 'XXXX-XXXX-XXXX'); INSERT INTO critical_config VALUES ('max_connections', '1000'); -- 再起動ですべての設定が消失! ``` ### 問題点 - サーバー停止・再起動でデータが消失します。テーブル定義は保持されます。 - プロセスが終了する障害でもメモリ内データを復旧できないため、唯一の元データを VOLATILE に保存するとデータ損失につながります。 ### 適切なパターン 永続的に必要なデータは LOOKUP または TRANSACTION に保存します。 ```sql -- 適切: 設定は LOOKUP CREATE LOOKUP TABLE app_config ( key_name VARCHAR(64) PRIMARY KEY, value VARCHAR(256) ); INSERT INTO app_config VALUES ('max_connections', '1000'); -- 再起動後もデータを保持 ``` ### VOLATILE の適切な用途 再起動後に再生成または破棄できるデータを保存します。クエリキャッシュだけでなく、寿命が明確な 作業状態も含められます。必ず保持する業務結果をメモリだけに保存しないでください。 | 適切 | 不適切 | |------|--------| | センサー最新値キャッシュ | 元のトランザクションデータ | | リアルタイム集計結果 | 重要な設定値 | | セッションの一時状態 | 監査ログ | | ダッシュボードキャッシュ | ユーザー情報 | ## 時系列に TRANSACTION を誤用 ### 問題 センサー・IoT 計測のような継続的な時系列を TRANSACTION に保存するパターンです。リレーショナルな 更新が不要なら、TAG のタグ・時間軸と ROLLUP を利用できず、必要なクエリ・運用に合わない場合があります。 一方、計測登録と他の業務変更を1トランザクションにまとめるなら TRANSACTION を選ぶ理由があります。 ### アンチパターンの例 ```sql -- 不適切: センサー時系列を TRANSACTION に保存 CREATE TRANSACTION TABLE sensor_timeseries ( sensor_id VARCHAR(64), ts DATETIME, value DOUBLE, unit VARCHAR(16) ); ``` ### 問題点 | 問題 | 説明 | |------|------| | 入力の意味が不一致 | リレーショナルトランザクション不要の値にもリレーショナル書き込みを使用 | | 時間軸がない | TAG の BASETIME 検索構造を利用できない | | 集計機能の違い | TAG 専用 ROLLUP を利用できない | ### 適切なパターン センサー計測は TAG に保存します。 ```sql -- 適切: TAG を使用 CREATE TAG TABLE sensor_history ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, unit VARCHAR(16) ); -- Append API の高速バッファで大量入力可能 -- 時間単位集計と TAG 専用最適化を利用可能 SELECT name, DATE_TRUNC('hour', time, 1) AS hour, AVG(value), MAX(value) FROM sensor_history WHERE time >= NOW - 86400000000000 GROUP BY name, hour; ``` ### TRANSACTION が適する場合 TRANSACTION は注文、在庫、設備履歴などリレーショナルな業務データに使います。時間列があっても UPDATE/DELETE が必要な業務履歴には TRANSACTION、変更せず蓄積する高頻度計測には TAG を選びます。 ## 意味の異なる値を同じ統計で集計 スキーマが同じでも単位や行の意味が異なれば単純集計できません。累積電力量(kWh)の平均は 消費電力(kW)ではなく、区間平均の単純平均は全サンプルの平均と異なる場合があります。 NULL を0で埋めると計測失敗が正常な0になります。 型とともに単位、サンプル数、品質規則を記録します。区間統計の再集計には合計と有効件数などを 保持し、元データを削除する前に将来の分析に必要な解像度を確認します。 --- title: "4.5 モデリングパターン" url: https://docs.machbase.com/ja/dbms/data-modeling-table-design/patterns-modeling/ language: ja kind: page --- # 4.5 モデリングパターン 運用環境でよく使うデータモデリングパターンを説明します。 各節の SQL は別々のモデルを示します。必要な節を選び、同名テーブルがないことを確認してから 専用の演習環境で実行します。スキーマ作成だけでは収集・集計・キャッシュ更新は自動実行されません。 入力アプリケーションやスケジューラーの処理と失敗対応も設計します。 - **[時間軸モデリング](/ja/dbms/data-modeling-table-design/patterns-modeling/#time-axis-modeling)** - **[距離軸モデリング](/ja/dbms/data-modeling-table-design/patterns-modeling/#distance-axis-modeling)** - **[状態・キャッシュ](/ja/dbms/data-modeling-table-design/patterns-modeling/#state-cache-status-modeling)** - **[イベント・ログ](/ja/dbms/data-modeling-table-design/patterns-modeling/#event-log-modeling-logs)** - **[参照・マスターデータ](/ja/dbms/data-modeling-table-design/patterns-modeling/#reference-master-modeling)** - **[永続・一時データの組み合わせ](/ja/dbms/data-modeling-table-design/patterns-modeling/#persistent-temporary)** - **[INSERT・UPDATE](/ja/dbms/data-modeling-table-design/patterns-modeling/#insert-update)** - **[JOIN・メタデータ設計](/ja/dbms/data-modeling-table-design/patterns-modeling/#join-metadata-design)** - **[複数タイプの組み合わせ](/ja/dbms/data-modeling-table-design/patterns-modeling/#table-types-patterns-combined-type)** ## 時間軸モデリング 時間を基準軸とするパターンで、センサー計測、エネルギー監視、環境データなどに適しています。 1行は1台のメーターの1回の観測です。`time` は受信時刻ではなく計測時刻とし、`kwh` が累積値か 区間使用量かを収集仕様に記録します。以下は電圧・電流も同じ観測に含む前提です。計測周期や 時刻が異なる場合は、同じ行へ無理に合わせず、別の時系列にするか欠測処理を定めます。 ### 基本パターン: TAG テーブル ```sql CREATE TAG TABLE power_meter ( meter_id VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, kwh DOUBLE, voltage DOUBLE, current DOUBLE ) METADATA ( location VARCHAR(64), phase SHORT, rating_kw DOUBLE ); ``` ### 時間範囲の集計 ```sql -- 1時間ごとの平均・最大計測値(直近24時間) SELECT meter_id, DATE_TRUNC('hour', time, 1) AS hour, AVG(kwh) AS avg_kwh, MAX(kwh) AS peak_kwh FROM power_meter WHERE time >= NOW - 86400000000000 GROUP BY meter_id, hour ORDER BY meter_id, hour; ``` `kwh` が累積電力量なら、上の平均はメーター指示値の平均であり、時間当たりの消費量ではありません。 区間消費量は開始・終了値の差に、初期化・交換・上限超過の処理規則を適用して求めます。 電力(kW)と電力量(kWh)も区別して列名と単位を決めます。 ### 複数解像度での保存 高解像度の元データと低解像度の集計データを、別テーブルに保存します。 ```sql -- 元データ(秒単位) CREATE TAG TABLE power_raw ( meter_id VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, kwh DOUBLE ); -- 1分集計(VOLATILE または別 TAG にキャッシュ) CREATE VOLATILE TABLE power_1min ( key_id VARCHAR(80) PRIMARY KEY, meter_id VARCHAR(32), ts DATETIME, avg_kwh DOUBLE, max_kwh DOUBLE ); ``` この DDL は保存領域を作るだけです。アプリケーションが `power_1min` の `key_id` にメーターと区間を 一意に識別する値を設定し、集計値を入力します。VOLATILE の結果は再起動で消えるため、長期集計の 保存先にはしません。元データ削除後も必要な統計は、永続 TAG または対応 ROLLUP に保持し、 それぞれの保持ポリシーを確認します。 ### タイムゾーン処理 DATETIME は時点を表し、文字列の入出力は接続のタイムゾーンに影響されます。韓国時間で表示するには クライアントの設定を合わせます。保存時刻に9時間を加えると、同じ時点を別タイムゾーンで表示するのではなく、 値自体を9時間後へ変えるため、表示変換と区別してください。 ```sql -- クライアントのタイムゾーンを確認し、元の時刻を取得 SELECT meter_id, time, kwh FROM power_meter WHERE meter_id = 'MTR-001' AND time >= '2024-01-01 00:00:00'; ``` 入力のタイムゾーンと接続設定が異なる場合は、入力前に基準を統一します。JDBC の `TIMEZONE` 例は [JDBC 接続](/ja/dbms/development-tools-integration/jdbc/)を参照してください。 ## 距離軸モデリング 距離・位置を基準軸とするパターンで、パイプライン検査、道路センサー、レーザースキャンなどに適しています。 距離軸は時間軸の別表示ではなく、時間軸専用の ROLLUP・Retention をそのまま適用できません。 同じ管を繰り返し検査する場合、`pipe_id` だけで検査回を混在させないよう、検査 ID やテーブル分割基準を 定めます。以下は1本の管の1回の検査を前提とし、距離は m、厚さは mm です。 ### 基本パターン ```sql CREATE TAG TABLE pipeline_thickness ( pipe_id VARCHAR(32) PRIMARY KEY, distance DOUBLE BASEDISTANCE, -- 単位: メートル thickness DOUBLE, temp DOUBLE ); ``` ### 範囲データの検索 ```sql -- 管 ID ごとの0~50mを検索 SELECT pipe_id, distance, thickness FROM pipeline_thickness WHERE pipe_id = 'PIPE-A' AND distance BETWEEN 0.0 AND 50.0 ORDER BY distance; -- しきい値未満の箇所を検索 SELECT pipe_id, distance, thickness FROM pipeline_thickness WHERE pipe_id = 'PIPE-A' AND thickness < 8.0 -- 厚さ8mm未満の箇所 ORDER BY distance; ``` ### 距離に基づく集計 ```sql -- 10m区間ごとの平均厚さ SELECT pipe_id, FLOOR(distance / 10.0) * 10 AS segment_start, AVG(thickness) AS avg_thickness, MIN(thickness) AS min_thickness FROM pipeline_thickness WHERE pipe_id = 'PIPE-A' GROUP BY pipe_id, FLOOR(distance / 10.0) * 10 ORDER BY segment_start; ``` ### 時間と距離の複合モデル 検査時刻と位置を併せて管理する場合は、時間軸 TAG に距離列を追加します。 ```sql -- 時間軸と位置情報を保存 CREATE TAG TABLE inspection_data ( inspector VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, distance DOUBLE, -- 位置列(軸ではない) thickness DOUBLE, defect SHORT ); -- 特定の日付・距離範囲を検索 SELECT inspector, time, distance, thickness FROM inspection_data WHERE inspector = 'INSPECTOR-01' AND time BETWEEN '2024-01-01' AND '2024-01-02' AND distance BETWEEN 100.0 AND 200.0 ORDER BY time; ``` ## 状態・キャッシュのモデリング デバイスやセンサーの現在状態をリアルタイムに検索するキャッシュパターンです。 ### 最新状態キャッシュ VOLATILE に各デバイスの現在状態をキャッシュします。 ```sql -- 状態キャッシュ(VOLATILE) CREATE VOLATILE TABLE device_status ( device_id VARCHAR(64) PRIMARY KEY, status VARCHAR(16), value DOUBLE, updated_at DATETIME ); -- 状態履歴(TAG または LOG) CREATE TAG TABLE device_status_history ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, status VARCHAR(16) ); ``` ### 状態更新の流れ 以下は履歴とキャッシュを個別に更新します。2つの入力は1トランザクションではなく、別々に評価する `NOW` も同時刻とは限りません。実際の収集では1回決めた計測時刻を両経路へ渡します。 遅れて届いた過去値が最新キャッシュを上書きしないよう、順序判定と同時更新をアプリケーションで制御します。 ```sql -- 新計測値を受信したとき: -- 1. TAG に履歴を保存 INSERT INTO device_status_history VALUES ('DEV-01', NOW, 78.5, 'WARNING'); -- 2. VOLATILE キャッシュを更新(ON DUPLICATE KEY UPDATE) INSERT INTO device_status VALUES ('DEV-01', 'WARNING', 78.5, NOW) ON DUPLICATE KEY UPDATE SET status = 'WARNING', value = 78.5, updated_at = NOW; ``` ### ダッシュボードのクエリ ```sql -- 現在アラーム状態のすべてのデバイス SELECT device_id, status, value, updated_at FROM device_status WHERE status IN ('ALARM', 'WARNING') ORDER BY updated_at DESC; -- 特定デバイスの最新状態 SELECT device_id, status, value, updated_at FROM device_status WHERE device_id = 'DEV-01'; ``` ### 状態定義の参照 状態コードの意味を LOOKUP で管理します。 ```sql CREATE LOOKUP TABLE status_definition ( code VARCHAR(16) PRIMARY KEY, label VARCHAR(64), color VARCHAR(16), severity SHORT ); INSERT INTO status_definition VALUES ('NORMAL', '正常', 'green', 0); INSERT INTO status_definition VALUES ('WARNING', '警告', 'yellow', 1); INSERT INTO status_definition VALUES ('ALARM', 'アラーム', 'red', 2); -- JOIN クエリ SELECT d.device_id, s.label, s.color, d.value FROM device_status d JOIN status_definition s ON d.status = s.code ORDER BY s.severity DESC; ``` ## イベント・ログのモデリング システムイベント、アラーム、監査ログを LOG テーブルでモデル化します。 ### 階層的なイベントモデル ```sql -- アラームイベントの LOG テーブル CREATE LOG TABLE alarm_event ( severity SHORT, -- 1=INFO, 2=WARN, 3=ERROR, 4=CRITICAL category VARCHAR(32), -- カテゴリ source VARCHAR(64), -- 発生元 message VARCHAR(512), src_ip IPV4 -- 発生元 IP(ある場合) ); -- システム監査用 LOG テーブル CREATE LOG TABLE audit_log ( user_id VARCHAR(64), action VARCHAR(32), -- INSERT, UPDATE, DELETE, LOGIN など target VARCHAR(128), -- 対象テーブル/リソース detail TEXT, -- 詳細(全文検索対象) result VARCHAR(8) -- SUCCESS, FAILURE ); CREATE INDEX idx_audit_detail ON audit_log(detail) INDEX_TYPE KEYWORD; ``` ### アラームの集計 ```sql -- 直近1時間の重大度別アラーム数 SELECT severity, COUNT(*) AS cnt FROM alarm_event WHERE _arrival_time >= NOW - 3600000000000 GROUP BY severity ORDER BY severity DESC; -- 発生元別アラーム状況(直近24時間) SELECT source, COUNT(*) AS total, SUM(CASE WHEN severity = 4 THEN 1 ELSE 0 END) AS critical_cnt FROM alarm_event WHERE _arrival_time >= NOW - 86400000000000 GROUP BY source ORDER BY total DESC; ``` ### ログレベルのフィルタリング ```sql -- ERROR 以上を検索(直近10分) SELECT _arrival_time, source, message FROM alarm_event WHERE severity >= 3 AND _arrival_time >= NOW - 600000000000 ORDER BY _arrival_time DESC LIMIT 100; ``` ### 全文検索 ```sql -- 指定キーワードを含む監査ログを検索 SELECT _arrival_time, user_id, action, target FROM audit_log WHERE detail SEARCH 'password' AND _arrival_time >= NOW - 86400000000000; ``` ## 参照・マスターデータのモデリング コード表、設備マスター、ユーザー情報などの参照データを LOOKUP でモデル化します。 履歴に識別子だけを保存すると、名前や場所の重複保存を減らせます。ただし現在のマスターの場所を 変えると、過去履歴との結合結果も新しい場所になります。発生時に所属したラインが重要なら、有効期間を 持つ変更履歴を設計するか、元の行に当時の属性を保存します。以下の階層の参照関係は外部キーで自動検証 されないため、存在しない工場・ラインコードを入力しないようアプリケーションで確認します。 ### 階層的なコード体系 ```sql -- 大分類コード CREATE LOOKUP TABLE category_main ( code VARCHAR(8) PRIMARY KEY, label VARCHAR(64) ); -- 中分類コード(大分類を参照) CREATE LOOKUP TABLE category_sub ( code VARCHAR(16) PRIMARY KEY, main_code VARCHAR(8), label VARCHAR(64) ); CREATE INDEX idx_sub_main ON category_sub(main_code); ``` ### 設備階層マスター ```sql -- 工場マスター CREATE LOOKUP TABLE factory ( factory_id VARCHAR(16) PRIMARY KEY, name VARCHAR(64), location VARCHAR(128) ); -- ラインマスター(工場を参照) CREATE LOOKUP TABLE production_line ( line_id VARCHAR(16) PRIMARY KEY, factory_id VARCHAR(16), name VARCHAR(64) ); -- 設備マスター(ラインを参照) CREATE LOOKUP TABLE equipment ( equip_id VARCHAR(32) PRIMARY KEY, line_id VARCHAR(16), equip_name VARCHAR(128), equip_type VARCHAR(32), install_dt DATETIME ); CREATE INDEX idx_equip_line ON equipment(line_id); CREATE INDEX idx_equip_type ON equipment(equip_type); ``` ### マスターの結合クエリ 計測テーブルには設備識別子を、工場・ライン・設備名などの属性は LOOKUP に1回だけ保存します。 クエリでは先に時間範囲を絞り、設備識別子で LOOKUP と結合します。構文と実行計画の確認は [JOIN・サブクエリ](/ja/dbms/tag-table-usage/query-analysis/)を参照してください。 ## 永続・一時データの組み合わせ 永続テーブル(TAG、LOG、TRANSACTION、LOOKUP)に元データを、VOLATILE にクエリ用キャッシュを 保存します。両経路を1トランザクションと考えず、キャッシュ遅延と失敗後の再構築も設計します。 ### 元データと集計キャッシュ 元データは永続テーブル、集計結果は VOLATILE に保存します。 ```sql -- 元データ(TAG、永続) CREATE TAG TABLE sensor_data ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); -- 集計キャッシュ(VOLATILE、一時) CREATE VOLATILE TABLE sensor_recent_avg ( key_id VARCHAR(64) PRIMARY KEY, sensor_id VARCHAR(64), base_ts DATETIME, avg_val DOUBLE, max_val DOUBLE, cnt LONG ); ``` ### キャッシュ更新 キャッシュの1行は、1センサーの直近2時間の統計です。`base_ts` は集計窓の境界ではなく、含まれる 最新の計測時刻です。同じ範囲定義で計算し、同一時点の結果を比べる場合は実行ごとに基準時刻を1回 決めます。以下は未来の計測値を除外します。比較時には各 SQL の `NOW` を同じ固定基準時刻に置き換え、 下限と上限を計算します。 ```sql -- 定期集計更新(1時間ごと) DELETE FROM sensor_recent_avg; INSERT INTO sensor_recent_avg SELECT name AS key_id, name, MAX(time) AS base_ts, AVG(value), MAX(value), COUNT(*) FROM sensor_data WHERE time >= NOW - 3600000000000 * 2 -- 直近2時間を再計算 AND time <= NOW GROUP BY name; ``` `INSERT ... SELECT` に `ON DUPLICATE KEY UPDATE` を付けないでください。再構築時は既存キャッシュを 削除してから再ロードします。 削除と再ロードの間は、他のクエリに空または一部だけのキャッシュが見えることがあります。 更新中の表示、失敗時の再試行、元データへのフォールバックをアプリケーションで定めます。 常に整合した完全な結果が必要なら、対応する切り替え・トランザクションモデルを検討します。 ### ダッシュボードクエリの最適化 ```sql -- 保存キャッシュを検索(元データへの切り替えはアプリケーション側) SELECT sensor_id, base_ts, avg_val, max_val FROM sensor_recent_avg WHERE base_ts >= NOW - 3600000000000 * 2 AND base_ts <= NOW ORDER BY sensor_id, base_ts; ``` この条件は、最新計測時刻が直近2時間に含まれるキャッシュ行を表示します。保存済み平均を クエリ時点で再計算するものではないため、集計の鮮度は更新周期で管理します。 ### 障害復旧 再起動すると VOLATILE のデータは消失しますが、テーブル定義は残ります。元の TAG から 同じ直近2時間の統計を再計算します。以下の CREATE は、初回構築などでテーブルが存在しない場合だけ作成します。 再計算対象が元データの保持期間内に残っている必要があります。 ```sql -- キャッシュ再構築(サーバー再起動後) CREATE VOLATILE TABLE IF NOT EXISTS sensor_recent_avg ( key_id VARCHAR(64) PRIMARY KEY, sensor_id VARCHAR(64), base_ts DATETIME, avg_val DOUBLE, max_val DOUBLE, cnt LONG ); INSERT INTO sensor_recent_avg SELECT name, name, MAX(time), AVG(value), MAX(value), COUNT(*) FROM sensor_data WHERE time >= NOW - 3600000000000 * 2 -- 通常更新と同じ直近2時間 AND time <= NOW GROUP BY name; ``` 復旧後、センサー別の件数・平均・最新時刻を、同じ基準時刻の元データ集計と比較します。`cnt` は NULL 計測値も含む行数です。平均に使ったサンプル数が必要なら `COUNT(value)` を別列に保存します。 ## INSERT・UPDATE パターン モデルでは変更可能なデータを決めますが、ここでは DML 対応表を再定義しません。タイプ別の変更条件は [データ変更ポリシー](../alter-data-mutation-policy/)、INSERT・Append・ファイル入力の選択は [データの入力とエクスポート](/ja/dbms/development-tools-integration/data-input-load-export/)を参照してください。 ## JOIN・メタデータ設計 複数タイプを組み合わせるときは次の原則を適用します。 まず結合関係を定義します。センサーコードごとにマスターが正確に1行か、工場間でコードが重複するかを 確認します。元の1行が複数の参照行に一致すると、結果行と SUM などが重複する場合があります。 名前だけでなく識別範囲と型を合わせてください。 1. 元の行数だけでなく、フィルター後の件数と実行計画で結合順序を検討します。 2. JOIN 列の型を合わせ、対応インデックスが使われるか確認します。 3. WHERE に時間範囲と業務条件を明示して結合行数を減らします。 4. TAG 属性を併せて読む目的なら、LOOKUP より METADATA が適切か検討します。 再現可能な結合例は [TAG のクエリと分析](/ja/dbms/tag-table-usage/query-analysis/)と [LOOKUP のクエリと分析](/ja/dbms/lookup-table-usage/query-analysis/)を参照してください。 ## 複数タイプの組み合わせ 運用システムで複数のテーブルタイプを組み合わせる代表的な設計です。 ### 製造設備の監視システム ``` ┌─────────────────────────────────────────────────────────┐ │ 設備監視システム │ ├──────────────────┬──────────────────┬───────────────────┤ │ TAG │ LOG │ LOOKUP │ │ sensor_data │ alarm_event │ equipment_master │ │ 計測履歴 │ アラームイベント │ 設備参照データ │ ├──────────────────┴──────────────────┴───────────────────┤ │ VOLATILE: sensor_latest(最新値キャッシュ) │ └─────────────────────────────────────────────────────────┘ ``` ### 物流・注文管理システム(Standard Edition) ``` ┌─────────────────────────────────────────────────────────┐ │ 物流管理システム │ ├──────────────────┬──────────────────┬───────────────────┤ │ TRANSACTION │ LOG │ LOOKUP │ │ orders │ delivery_log │ product_master │ │ 注文管理 │ 配送イベント │ 製品参照データ │ │ UPDATE/DELETE │ │ │ ├──────────────────┴──────────────────┴───────────────────┤ │ VOLATILE: order_status_cache(現在状態キャッシュ) │ └─────────────────────────────────────────────────────────┘ ``` ### パターンのまとめ | 役割 | 推奨タイプ | 理由 | |------|---------|------| | 高頻度の計測履歴 | TAG | Append API の高速バッファ、時系列最適化 | | イベント・アラームログ | LOG | 追記専用、受信時刻の自動記録 | | リレーショナル業務(UPDATE/DELETE) | TRANSACTION | SELECT/INSERT/UPDATE/DELETE 対応 | | 参照・コード情報 | LOOKUP | PK 識別、一般条件 UPDATE/DELETE、永続性 | | リアルタイム状態キャッシュ | VOLATILE | メモリ速度、UPSERT | --- 次に読む文書: - [SELECT の GROUP BY と集計](/ja/dbms/reference/sql/syntax/select-syntax/) - [運用と設定](/ja/dbms/operations-configuration-recovery/) --- title: "5. TAGテーブルの活用" url: https://docs.machbase.com/ja/dbms/tag-table-usage/ language: ja kind: section --- # 5. TAGテーブルの活用 TAGテーブルは、繰り返し観測する対象の名前と時間軸または距離軸を使って計測履歴を保存します。 本章では、Machbase DBMS 8.7.0のTAG構造、データの入力と検索、メタデータ、補正と運用を説明します。 第3・4章で決定したデプロイ環境とデータモデルを、実際のSQLで確認します。 タグは測定対象を、DATAの1行は1回の観測を表します。METADATAはタグごとに1行の属性であり、 過去の観測ごとに保存する属性ではありません。元の測定値、現在の属性、区間集計、収集時刻を 区別すると、検索結果と訂正範囲を一貫して解釈できます。 ## 本章の構成 | 節 | 内容 | |---|---| | [概要と使用基準](./overview-use-criteria/) | タグ識別子と観測行、時間軸・距離軸の選択 | | [テーブル構造とスキーマ](./table-structure-schema/) | 列の順序と型、LSL/USL、BINARYとストレージ設計 | | [作成、変更、削除](./create-alter-drop/) | 基本DDL、METADATAの拡張、オブジェクトの削除 | | [データの入力と変更](./data-input-mutation/) | タグの自動登録、SQL・Append・ファイル入力の違い | | [検索と分析](./query-analysis/) | 区間・最新値・STATの検索と結果の解釈 | | [インデックスと性能](./index-performance/) | 実データによるアクセスパスの確認 | | [運用とデータライフサイクル](./operations-lifecycle/) | 削除、保持ポリシー、重複排除の完了確認 | | [制約、エラー、トラブルシューティング](./constraints-errors-troubleshooting/) | 正常条件と意図的に失敗させる例 | | [活用パターンとシナリオ](./patterns-scenarios/) | 観測単位・単位系・欠損に応じたモデル | | [TAGメタデータ](./tag-metadata/) | 登録・検索・更新・削除、JSONとARRAY | | [TAG data UPDATEとデータ補正](./tag-data-update-correction/) | 直接訂正、NULLへの補正、監査履歴 | | [tagmetaimportとメタデータの一括登録](./tagmetaimport/) | CSVの準備、入力先、再入力エラーの確認 | ## 実習とサポート範囲 各ページは独立した実習です。準備SQLのテーブルがすでに存在する場合は、別の業務オブジェクト でないか確認し、無断で削除しないでください。成功例と失敗確認用の例を分けて実行し、 後片付けのSQLは実習で作成したオブジェクトだけに適用します。 TAG DATA UPDATEはStandard Edition専用です。自動重複検査期間、METADATA ALTER、LSL/USLの 詳細操作もEditionごとの範囲を確認します。SQL INSERT、Appendの処理応答、ストレージバッファの フラッシュ、インデックス・統計処理の完了は、それぞれ意味が異なります。 ROLLUPの作成・検索・再構築の全手順は[第6章](../tag-rollup-usage/)で説明します。 本章では、TAGの訂正と削除が集計に与える影響のみ扱います。 --- title: "5.1 概要と使用基準" url: https://docs.machbase.com/ja/dbms/tag-table-usage/overview-use-criteria/ language: ja kind: page --- # 5.1 概要と使用基準 TAGは、センサーや設備など同じ対象を繰り返し観測した履歴の保存に適しています。 まず「1つのタグ」と「1行」を区別します。同じ名前で異なる時刻の行を入力でき、 タグ名が同じという理由だけで重複行が排除されることはありません。 ## TAGテーブルの特性 `PRIMARY KEY`はタグ名を指定します。リレーショナルテーブルで各行を一意に識別するキーとは 役割が異なります。1つのテーブルには時間軸または距離軸を1つ指定します。 ```sql -- 時間に沿って発生した観測値を保存する時間軸TAGです。 CREATE TAG TABLE ch5_overview_time ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); -- 距離や位置の区間に基づいて観測値を保存する距離軸TAGです。 -- 距離軸TAGではROLLUPを使用できません。 CREATE TAG TABLE ch5_overview_distance ( name VARCHAR(64) PRIMARY KEY, distance DOUBLE BASEDISTANCE, value DOUBLE ); ``` どちらの例も、名前が1番目の列、軸が2番目の列です。時間軸は`DATETIME BASETIME`、 距離軸は`DOUBLE`、`LONG`、`ULONG`のいずれかと`BASEDISTANCE`を使用します。 `SUMMARIZED`を使用する場合は3番目の列に指定します。列の順序と指定可能な型は [作成、変更、削除](../create-alter-drop/)、モデルごとの設計判断は [テーブル構造とスキーマ](../table-structure-schema/)を参照してください。 `SUMMARIZED`は代表値の統計・集計に使用する列を指定する属性であり、ROLLUPオブジェクトを 自動作成するものではありません。 次の表は例のテーブルの列一覧ではなく、TAGテーブルの使用時に区別するデータの範囲です。 DATAはユーザーが入力する観測行で、METADATAとSTATはタグごとの属性・統計を確認するための 別の範囲です。 | データの範囲 | 意味 | |---|---| | タグ名 | センサーや繰り返し観測する対象を識別する最初の列 | | DATA | ユーザーが入力する観測行。軸の値と複数のデータ列 | | METADATA | タグごとの位置・単位・設定などの現在の属性。通常のDATA列とは区別 | | STAT | `V$_STAT`で確認するタグごとの入力統計。例のテーブルの直接の列ではない | ## TAGが適している場合 - 同じスキーマで複数の対象の履歴を継続して追加します。 - 特定タグの時間・距離範囲を頻繁に検索します。 - 現在の属性を条件としてタグを選択し、その履歴を分析します。 - 時間軸TAGで繰り返し区間統計を保存・検索する必要があります。この場合、ROLLUPの設計は [TAG ROLLUP](../../tag-rollup-usage/)で別途確認します。 単一値モデルは測定項目ごとにタグを分け、複数値モデルは同じ観測で得られた温度・圧力などを 1行にまとめます。測定時刻の異なる値を無理に同じ行に入れず、欠損・品質ポリシーを定めます。 時系列の同時刻のデータも重複収集の可能性があるため、名前・時刻・値の重複処理ポリシーを 別途確認します。 ## 他のテーブルを検討する場合 | 要件 | 検討する代替案 | |---|---| | 観測対象よりイベント自体が重要なイベント検索 | LOG | | 永続的なマスターデータの一般条件による検索・変更 | LOOKUP | | 複数のDMLに対する明示的なトランザクションとリレーショナルな変更 | TRANSACTION(Standard Edition専用) | | 元データから再構成できる共有状態キャッシュ | VOLATILE | TAGでもJOINと制限付きの値補正を使用できます。「JOINが必要ならTAGは使えない」 「計測値は必ずTAGに保存する」といった判断は避けます。 ただし、DATAのUPDATEはStandard Edition専用です。Cluster EditionではMETADATA UPDATEのみ 使用できるため、値補正が必要な場合は再入力と再集計の手順も設計します。 ## 設計手順 1. タグがセンサー・装置・検査回のどれを識別するかを決めます。 2. 測定時刻または距離・位置の意味と単位を決めます。 3. 値の型、NULLと品質表示、観測周期を決めます。 4. 観測ごとに保存する属性と現在のMETADATAを区別します。 5. 区間検索・集計・補正・保管の要件をEditionのサポート範囲と照合します。 例のテーブルの確認と削除は次のとおりです。 ```sql -- 例のテーブルのスキーマを確認します。 DESC ch5_overview_time; DESC ch5_overview_distance; -- 後の例と名前が重複しないように削除します。 DROP TABLE ch5_overview_distance; DROP TABLE ch5_overview_time; ``` 次は[スキーマ設計](../table-structure-schema/)と [入力・検索の実習](../data-input-mutation/)です。 --- title: "5.2 テーブル構造とスキーマ" url: https://docs.machbase.com/ja/dbms/tag-table-usage/table-structure-schema/ language: ja kind: page --- # 5.2 テーブル構造とスキーマ ## TAGテーブルの設計 TAGテーブルの設計では、列数だけでなく、何を1つのタグとするか、どの値をどの領域に置くかを決めます。 列の位置によって決まる役割、軸列の型、指定できない型は [作成、変更、削除](../create-alter-drop/#original-85-creating-tag-tables)を参照してください。 このページでは、その規則の範囲内で決定する項目を扱います。 このページのDDLはモデルごとの独立した例です。作成順序が必要な実習は各節で説明します。 同名の既存オブジェクトがある場合は、別名で実行します。 スキーマを決める際は、次の項目を合わせて検討します。 - [活用例](#tag-schema-use-case-summary) - [タグ名の列](#tag-name-column-design) - [時間軸と距離軸の選択](#time-axis-design-tag) - [値の列の設計](#tag-table-design-design-column) - [METADATA列の設計](#metadata-column-design-summary) - [JSON METADATA列の設計](#json-metadata-column-design-summary) - [バイナリデータ列の設計](#tag-table-design-design-column-binary) - [VARCHARストレージの最適化](#tag-table-design-storage-varchar) - [ストレージ戦略](#tag-table-design-strategy) - [LSL・USLの設計](#tag-table-design-lsl-usl) - [補正と重複のポリシー](#correction-duplication-policy-summary) - [制約とサポート範囲](#tag-schema-limitations-summary) ### 活用例 TAGは、同じ構造の観測値が複数の対象から継続して蓄積される業務に適しています。センサー、設備、 移動体、検査回などの反復観測対象を先に決め、対象ごとの履歴を時間軸または距離軸で検索できるか 確認します。ここでは、対象をTAGでモデル化するか、別のテーブルタイプに分けるかを決定します。 業務モデルの例は[活用例](../patterns-scenarios/#use-cases-tag)を参照してください。 ### タグ名の列 センサー別、設備別、検査回別のどの単位を1つのタグとするかを先に決めます。細かく分けるとタグ数が 増えてメタデータとインデックスの負担が大きくなり、大きくまとめると1つのタグに異なる対象の履歴が 混在します。命名規則は[VARCHARストレージの最適化](#tag-table-design-storage-varchar)でも扱います。 ### 時間軸と距離軸の選択 軸は、検索条件で何を範囲指定するかに基づいて選択します。測定時刻で区間を指定する場合は時間軸、 特定経路の累積位置など距離区間で指定する場合は距離軸です。1つのTAGテーブルは両方の軸を同時に 持てないため、後から変更するにはテーブルを作り直す必要があります。 ```sql -- 測定時刻で区間を指定する時間軸TAGです。 CREATE TAG TABLE time_sensor ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); ``` ```sql -- 距離・位置で区間を指定する距離軸TAGです。 CREATE TAG TABLE rail_sensor ( name VARCHAR(40) PRIMARY KEY, distance DOUBLE BASEDISTANCE, value DOUBLE ); ``` `DURATION`、ROLLUP、時間関数はBASETIMEだけに適用されます。距離範囲の検索は通常の比較と `BETWEEN`を使用します。実行例は[検索と分析](../query-analysis/)を参照してください。 ### 値の列の設計 TAGテーブルの値の列は、タグ名と軸列を除く通常のデータ列です。 計測値、状態、品質コードなど測定行ごとに変わる値を保存します。 #### サポートされる型 以下はよく使用する型の例です。JSON、BINARY、DECIMAL、数値ARRAYを含む全サポート範囲は [データ型リファレンス](/ja/dbms/reference/sql/types/)を参照してください。 | 型 | 説明 | 保存サイズ | |------|------|---------| | `DOUBLE` | 64ビット浮動小数点 | 8バイト | | `FLOAT` | 32ビット浮動小数点 | 4バイト | | `LONG` | 64ビット整数 | 8バイト | | `INTEGER` (`INT`) | 32ビット整数 | 4バイト | | `SHORT` | 16ビット整数 | 2バイト | | `VARCHAR(n)` | 可変長文字列 | 最大nバイト | #### 推奨する型の選択 | データ | 推奨する型 | |--------|---------| | 温度、湿度、圧力などのアナログ値 | `DOUBLE` | | カウンター、状態コード | `INTEGER` | | フラグ、二値状態 | `SHORT` | | エネルギー、流量の累積値 | `DOUBLE`または`LONG` | | タグの文字列値 | `VARCHAR(n)` | #### 複数の値の列の設計 1つのテーブルに複数の計測項目を保存すると、NULL値が発生する場合があります。 計測項目が同時に収集される場合に適しています。 ```sql CREATE TAG TABLE weather_station ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, temperature DOUBLE, -- 常に収集 humidity DOUBLE, -- 常に収集 wind_speed DOUBLE, -- 任意 rainfall DOUBLE -- 任意 ); ``` #### NULLを許容する設計 TAGテーブルの値の列はデフォルトでNULLを許可します。特定タグが一部の項目だけを収集する場合は、 残りの列にNULLを挿入します。 ```sql -- wind_speedとrainfallがない場合 INSERT INTO weather_station VALUES ('WS-01', NOW, 22.5, 65.0, NULL, NULL); ``` ### METADATA列の設計 METADATA列はDATA行ごとに繰り返す値ではなく、タグごとの現在の属性を保存するために使用します。 設置場所、単位、装置設定、管理状態など、タグ名に付随する属性が該当します。DATAとMETADATAを 分離すると、観測履歴を維持しながらタグの現在の属性だけを検索・変更できます。ここでは各属性を METADATAに置くかDATA列に残すかを決定します。観測ごとに値が変わる場合はDATA、タグの寿命を通して おおむね固定ならMETADATAです。入力・検索・更新の例は [METADATAの使用](../tag-metadata/#original-85-tag-metadata)を参照してください。 ### JSON METADATA列の設計 タグ別の属性が階層構造を持つ場合や属性の集合が頻繁に変わる場合は、JSON METADATA列を検討します。 たとえば設備の場所、メーカー情報、設置オプションを1つのJSONドキュメントに保存し、必要なパスだけを 検索できます。ここではMETADATAを個別列にするか1つのJSONドキュメントにするかを決定します。 属性の集合が固定で条件検索が多い場合は個別列、タグごとに属性構成が異なる場合はJSONが適しています。 頻繁に条件として使用するパスは、インデックス設計も検討します。詳しい構文と例は [JSON METADATA](../tag-metadata/#metadata-design-json)を参照してください。 ### バイナリデータ列の設計 TAGテーブルの`BINARY(n)`は、1~32767バイトのセンサーフレームの保存に使用します。 入力リテラル、長さの制約、ドライバーの動作は[Binary列](#original-85-binary-columns)を 参照してください。大きな画像や波形は外部ストレージに置き、参照キーだけを保存する設計も検討してください。 ### VARCHARストレージの最適化 `VARCHAR`は実際の最大長に合わせて宣言します。保存オプションの正確な構文は [DDLリファレンス](/ja/dbms/reference/sql/syntax/ddl-syntax/)を参照してください。タグ名はサイト、 設備、センサーの識別子を一貫した区切り文字で組み合わせ、範囲検索できるように設計します。 ### ストレージ戦略 データはタグごとに分離された列指向ストレージに保存されます。データ量と検索パターンに応じて 適切な戦略を選択します。 #### 単一テーブルと複数テーブル ##### 単一TAGテーブル(推奨) 同種のセンサーは1つのTAGテーブルにまとめて管理します。 ```sql -- 推奨: 全温度センサーを1つのテーブルにまとめる CREATE TAG TABLE temperature_sensor ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); ``` **利点** - 管理箇所を最小化 - タグを横断する集計が容易 - 運用を簡素化 ##### 複数TAGテーブル 列構成が異なる場合や保持期間・アクセス権・運用周期を分けて管理する必要がある場合は、 テーブルの分割を検討します。センサー数が増えたという理由だけでセンサー別テーブルを作成しません。 ```sql -- 温度・湿度センサー(DOUBLE値) CREATE TAG TABLE thermo_sensor ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, temp DOUBLE, humid DOUBLE ); -- 振動センサー(DOUBLE + BINARY波形) CREATE TAG TABLE vibration_sensor ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, rms DOUBLE, waveform BINARY(4096) ); ``` #### タグ数の管理 - タグ数の増加に伴うタグインデックスとメタデータのメモリ使用量を、本番規模のデータで測定します。 - センサーの階層構造をタグ名に符号化して管理します。 - タグ名がレコードごとに一意になる設計は避けます(アンチパターン)。 #### パーティション戦略 時間軸TAGは`BASETIME`に基づいて範囲を絞って検索します。システムのストレージオブジェクトや パーティション名に依存せず、保持期間は [データ保持ポリシー](/ja/dbms/operations-configuration-recovery/policy-data-retention/)で管理してください。 ### LSL・USLの設計 LSL(Lower Specification Limit)は下側規格限界、USL(Upper Specification Limit)は 上側規格限界です。TAGテーブルのMETADATA列にタグごとの許容範囲を設定すると、範囲外のDATA入力を 拒否できるため、タグごとに異なる入力品質基準を適用できます。 値を補正する機能ではなく、入力を拒否する機能です。範囲外の入力は収集エラーポリシーに従って 記録・再処理する必要があります。 #### 制約条件 次の制約が適用されます。 * LSL/USLをCluster全体で非サポートとは扱いません。テーブル作成時の限界定義、メタデータ値の設定、 DATA INSERT・Appendの限界検査は共通の経路です。既存METADATAに限界列をALTERで追加する 以下の実習はStandard Editionで行います。 * LSL/USLを設定するには、Tagテーブルの3番目の列__Value__に__SUMMARIZED__を指定する必要があります。 * LSLはUSL以下であり、__Value__列の入力値はLSL以上USL以下である必要があります。__(LSL <= Value <= USL)__ * LSL/USL設定前に入力されたデータは検証されません。 * LSL/USL列をNULLにすると入力データを検証しません。 * LSL/USLは個別に使用できます。上限だけを適用する場合はUSLだけを設定できます。 * USLだけを設定すると上限超過のみ、LSLだけを設定すると下限未満のみを検査します。 #### サポートされるデータ型 限界列は対象の__Value__列と同じ型である必要があります。以下では基本数値型の規格範囲設定を 説明します。SUMMARIZED自体がサポートする型にはJSONも含まれるため、SUMMARIZEDを宣言できる条件と 数値限界の設定条件は区別します。 |型|説明|範囲|有効桁数| |----|------|-----|----| |short|16ビット符号付き整数型|-32767 ~ 32767|-| |ushort|16ビット符号なし整数型|0 ~ 65534|-| |integer|32ビット符号付き整数型|-2147483647 ~ 2147483647|-| |uinteger|32ビット符号なし整数型|0 ~ 4294967294|-| |long|64ビット符号付き整数型|-9223372036854775807 ~ 9223372036854775807|-| |ulong|64ビット符号なし整数型|0~18446744073709551614|-| |float|32ビット浮動小数点データ|-|6[^1]| |double|64ビット浮動小数点データ|-|15[^1]| #### LSL/USLの設定と使用 次のCREATE例は異なる選択肢を示します。以降のINSERT・UPDATE実習では基本の`example`だけを使用し、 代替テーブルは別途作成します。 タグメタデータテーブルの列に`LOWER LIMIT`(LSL)または`UPPER LIMIT`(USL)キーワードを指定します。 Tagテーブルの作成時またはメタデータ列の追加時に設定できます。 ##### CREATE ```sql CREATE TAG TABLE example ( tag_id VARCHAR(50) PRIMARY KEY, time DATETIME BASETIME, value INTEGER SUMMARIZED) METADATA ( lsl INTEGER LOWER LIMIT, usl INTEGER UPPER LIMIT ); ``` 2つの列を併用することも、片方だけ使用することもできます。 LSLだけを設定すると`Value >= LSL`を検査し、上限は制限しません。USL値を`NULL`にした場合と 同じ意味です。 ```sql CREATE TAG TABLE example_lower_only ( tag_id VARCHAR(50) PRIMARY KEY, time DATETIME BASETIME, value INTEGER SUMMARIZED) METADATA ( lsl INTEGER LOWER LIMIT ); ``` ##### ADD COLUMN データ入力後に`ADD COLUMN`で追加する場合、デフォルト値は__NULL__です。 ```sql CREATE TAG TABLE example_alter_limits ( tag_id VARCHAR(50) PRIMARY KEY, time DATETIME BASETIME, value INTEGER SUMMARIZED ); ALTER TABLE example_alter_limits METADATA ADD COLUMN (lsl INTEGER LOWER LIMIT); ALTER TABLE example_alter_limits METADATA ADD COLUMN (usl INTEGER UPPER LIMIT); ``` [CREATE](#create)と同様、片方の属性だけを追加することもできます。 ```sql CREATE TAG TABLE example_alter_upper ( tag_id VARCHAR(50) PRIMARY KEY, time DATETIME BASETIME, value INTEGER SUMMARIZED ); ALTER TABLE example_alter_upper METADATA ADD COLUMN (usl INTEGER UPPER LIMIT); ``` ##### INSERT 特定のTAG IDのLSL/USL値を設定します。 ```sql INSERT INTO example metadata VALUES ('TAG_01', 100, 200); ``` 設定後にタグデータを入力すると、次のように動作します。 ```sql INSERT INTO example VALUES ('TAG_01', NOW, 95); -- 失敗 ``` ```text [ERR-02342: SUMMARIZED value is less than LOWER LIMIT.] ``` ```sql INSERT INTO example VALUES ('TAG_01', NOW, 100); -- 成功(境界を含む) ``` ```text 1 row(s) inserted. Elapsed time: 0.000 ``` ```sql INSERT INTO example VALUES ('TAG_01', NOW, 150); -- 成功 ``` ```text 1 row(s) inserted. Elapsed time: 0.000 ``` ```sql INSERT INTO example VALUES ('TAG_01', NOW, 200); -- 成功(境界を含む) ``` ```text 1 row(s) inserted. Elapsed time: 0.000 ``` ```sql INSERT INTO example VALUES ('TAG_01', NOW, 205); -- 失敗 ``` ```text [ERR-02341: SUMMARIZED value is greater than UPPER LIMIT.] ``` Tagテーブルを検索すると、規格範囲内のデータだけが入力されたことを確認できます。 ```sql SELECT * FROM example; ``` ```text TAG_ID TIME VALUE LSL USL ------------------------------------------------------------------------------------------------------------------------------ TAG_01 2023-09-12 09:31:27 923:289:631 100 100 200 TAG_01 2023-09-12 09:31:27 929:013:232 150 100 200 TAG_01 2023-09-12 09:31:27 939:209:248 200 100 200 [3] row(s) selected. Elapsed time: 0.001 ``` ##### UPDATE LSL/USL列の値を変更します。入力済みのデータには遡及適用されない点に注意してください。 ```sql UPDATE example metadata SET lsl = 10, usl = 100 WHERE tag_id = 'TAG_01'; ``` ```text 1 row(s) updated. Elapsed time: 0.001 ``` ```sql SELECT tag_id, lsl, usl FROM example METADATA; ``` ```text TAG_ID LSL USL ---------------------------------------------------------------------------------------- TAG_01 10 100 [1] row(s) selected. Elapsed time: 0.001 ``` ##### DELETE LSL/USL列は`DROP COLUMN`で削除せず、値をNULLに設定して制約を解除します。 ```sql UPDATE EXAMPLE METADATA SET lsl = NULL, usl = NULL WHERE tag_id = 'TAG_01'; ``` ```text 1 row(s) updated. Elapsed time: 0.001 ``` ```sql SELECT tag_id, lsl, usl FROM example METADATA; ``` ```text TAG_ID LSL USL ---------------------------------------------------------------------------------------- TAG_01 NULL NULL [1] row(s) selected. Elapsed time: 0.001 ``` #### TRACEログでLSL/USL違反を確認 - 場所: `$MACHBASE_HOME/trc/machbase.trc` - 簡易フィルター: ```bash grep LIMIT_DROP $MACHBASE_HOME/trc/machbase.trc | tail -n 20 ``` - ログ形式: `LIMIT_DROP (TYPE=) TABLE=<テーブル名> TAG= <列名=値 ...>` - TYPE=LOWER/UPPERで違反した限界を区別します。 - DATETIMEは`YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn`形式です。 - 実際の例: ``` [2025-11-29 13:50:34 P-151395 T-126343511537344][QP-INFO] LIMIT_DROP (TYPE=LOWER) TABLE=TAG3 TAG=tag-1 TIME=2020-01-01 00:00:00 000:000:000 VALUE=5.55 [2025-11-29 13:50:34 P-151395 T-126343511537344][QP-INFO] LIMIT_DROP (TYPE=UPPER) TABLE=TAG3 TAG=tag-1 TIME=2020-01-01 00:00:04 000:000:000 VALUE=30.55 [2025-11-29 13:50:35 P-151395 T-126344475694784][QP-INFO] LIMIT_DROP (TYPE=LOWER) TABLE=TAG3 TAG=tag-2 TIME=1998-12-24 09:00:00 000:000:000 VALUE=0 [2025-11-29 13:50:35 P-151395 T-126344475694784][QP-INFO] LIMIT_DROP (TYPE=UPPER) TABLE=TAG3 TAG=tag-2 TIME=1998-12-24 09:00:00 000:000:008 VALUE=45 ``` - 活用のポイント - TAGごとのLOWER/UPPER違反時刻と値を一覧できます。 - grepでTAG名・テーブル名を追加フィルターすると、特定対象だけを追跡できます。 - 注意: 1行は最大約4KBのため、列が多いと末尾が切れる場合があります。起動直後、メタキャッシュの 準備前はテーブル名がIDで表示される場合があります。 [^1]: [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) ### 補正と重複のポリシー 値の補正と重複排除は列定義だけで完結しませんが、スキーマ設計時に事前に決める必要があります。 補正が必要な場合は、変更可能な値の列、元データを別列または別テーブルに保持するか、補正後のROLLUPを どう再構築するかを決めます。DATAのUPDATEはStandard Edition専用のため、Cluster Editionでは 補正の代わりに再入力と再集計の手順を設計します。詳細は [データ補正](../tag-data-update-correction/#design-correction-tag)を参照してください。 同じタグと同じ軸値が繰り返し入力される可能性がある場合は、重複を許可するか、収集段階で排除するか、 Machbaseの自動重複排除を使用するかを決めます。設定変更と運用検証の手順は [自動重複排除](../operations-lifecycle/#original-85-duplication-removal)を参照してください。 ### 制約とサポート範囲 TAGテーブルは反復観測の履歴に合わせた構造のため、すべてのSQL機能を一般的なリレーショナルテーブルと 同様にサポートするわけではありません。軸列、METADATA、値の補正、ROLLUP、Editionごとのサポート範囲を 設計前に確認します。ここでは設計案がサポート範囲内かを確認し、範囲外なら該当項目に戻ってスキーマを 調整します。非サポート機能と代表的なエラーは [制約と注意事項](../constraints-errors-troubleshooting/#limitations-tag)を参照してください。 ## Binary列 `BINARY(n)`はTagテーブルでセンサーフレーム用の固定長バイナリ値を保存します。 TAGで長さを省略した`BINARY`は32767バイトとして扱われます。必要なフレームサイズを明示すると、 保存・転送サイズを把握しやすくなります。TAG以外のテーブルでは長さ指定形式の`BINARY(n)`を 宣言できません。有効な長さは1~32K-1(1~32767)バイトで、インデックスは作成できません。 明示的なバイナリリテラルで`BINARY`値を入力します。 ### DDLの規則 ```sql CREATE TAG TABLE t1( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, frame BINARY(4) ); ``` - 有効な長さ: `1 <= n <= 32767`(32K-1)。 - 範囲外の場合は作成時にエラーになります(`BINARY(0)`など)。 - `DESC`とテーブルメタデータは宣言されたバイト長を表示します(16進数の幅ではありません)。 SQLの`LENGTH(binary_col)`は、短い入力値の末尾に付く0パディングを除いた表示値の長さを返します。 ### サポートされる入力形式 ```sql X'hex_digits' x'hex_digits' B'bit_digits' b'bit_digits' O'octal_digits' o'octal_digits' ``` | 形式 | 意味 | 単位 | | --- | --- | --- | | `X'...'`, `x'...'` | 16進数リテラル | 16進数2桁 = 1バイト | | `B'...'`, `b'...'` | 2進数リテラル | 8ビット = 1バイト | | `O'...'`, `o'...'` | 8進数リテラル | 8進数3桁 = 1バイト | 接頭辞は大文字・小文字のどちらも使用できます。 ```sql CREATE TAG TABLE t_bin ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value BINARY(4) ); INSERT INTO t_bin VALUES('hex1', '2024-01-01 00:00:00', X'0A'); INSERT INTO t_bin VALUES('hex2', '2024-01-01 00:00:01', x'00010203'); INSERT INTO t_bin VALUES('bit1', '2024-01-01 00:00:02', B'00001010'); INSERT INTO t_bin VALUES('oct1', '2024-01-01 00:00:03', O'012'); ``` `X'0A'`、`B'00001010'`、`O'012'`はいずれも1バイトの値`0x0A`を表します。 ### バイナリリテラルの規則 #### 16進数リテラル `X'...'`と`x'...'`には`0-9`、`A-F`、`a-f`を使用できます。 ```sql X'00' X'0AFF' x'abcdef' ``` 16進数の文字数は必ず偶数である必要があります。2桁が1バイトに相当します。 #### 2進数リテラル `B'...'`と`b'...'`には`0`と`1`だけを使用できます。 ```sql B'00000000' -- 0x00 B'00001010' -- 0x0A b'11111111' -- 0xFF ``` ビット数は必ず8の倍数である必要があります。8桁が1バイトに相当します。 #### 8進数リテラル `O'...'`と`o'...'`には`0-7`だけを使用できます。 ```sql O'000' -- 0x00 O'012' -- 0x0A o'377' -- 0xFF ``` 8進数の文字数は必ず3桁単位である必要があります。各3桁の値は`000`から`377`までの 1バイトの範囲内である必要があります。 #### 空の値 単一引用符の中を空にして、長さ0のバイナリ値を表します。 ```sql X'' B'' O'' ``` ### 長さの制限 `BINARY(n)`列には最大`n`バイトまで入力できます。 ```sql CREATE TAG TABLE t_limit ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value BINARY(2) ); INSERT INTO t_limit VALUES('ok_hex', '2024-01-01 00:00:00', X'0AFF'); INSERT INTO t_limit VALUES('ok_bit', '2024-01-01 00:00:01', B'0000101011111111'); INSERT INTO t_limit VALUES('ok_oct', '2024-01-01 00:00:02', O'012377'); INSERT INTO t_limit VALUES('bad_hex', '2024-01-01 00:00:03', X'000102'); -- 失敗: 3バイト ``` 入力元の種類に関係なく、最終的なバイナリ値が対象の`BINARY(n)`の長さを超えると入力は失敗します。 この規則はバイナリリテラルだけでなく、通常の文字列、従来の`'0x...'`文字列入力、他の`BINARY`列の 値を`INSERT ... SELECT`でコピーする場合にも同じように適用されます。 ```sql CREATE TAG TABLE t_src ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value BINARY(8) ); CREATE TAG TABLE t_dst ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value BINARY(4) ); INSERT INTO t_src VALUES('k1', '2024-01-01 00:00:00', X'0102030405060708'); INSERT INTO t_dst SELECT name, time, value FROM t_src; -- 失敗: 8バイトの値をBINARY(4)に入力 ``` `CASE`、`INSERT ... SELECT`、ビューなどのSQL式で使用する場合も、最終的なバイナリ値が対象の `BINARY(n)`の長さを超えると入力は失敗します。 ### 無効な入力 次の入力は無効です。 ```sql X'0' -- 16進数の文字数が奇数 X'0G' -- Gは16進数の文字ではない B'0101' -- ビット数が8の倍数ではない B'00000002' -- 2は2進数の文字ではない O'12' -- 8進数の文字数が3桁単位ではない O'400' -- 1バイトの範囲を超過 X'0102 -- 閉じる単一引用符がない ``` 不正な値または長さ超過の入力は、次のエラーで失敗します。 ```text [ERR-02233: Error occurred at column (n): (Invalid insert value.)] ``` ### 従来の文字列入力との違い 互換性のため、文字列形式の`'0x...'`入力も使用できます。`'0x...'`は文字列から`BINARY`列への 変換方式であり、`X'...'`、`B'...'`、`O'...'`はSQLでバイナリ値であることを明示する バイナリリテラルです。 通常の文字列を`BINARY(n)`列に入力することもできますが、文字列のバイト長が`n`を超えると失敗します。 新しくSQLを記述する場合は、意味が明確なバイナリリテラル形式を推奨します。 `'0b...'`、`'0o...'`、引用符のない`0x...`、`0b...`、`0o...`形式はバイナリリテラルとして サポートされません。 ### 出力とツールの補足 - machsqlは`0x`のない大文字の16進数で出力します。短い入力値の末尾に付く0パディングは テキスト出力に表示されません。 - machloader: スキーマに`BINARY(n)`を宣言します。不正な値や長さ超過は失敗します。 - Machbase SQLCLI、ODBC、Java、C#、Node.jsドライバーは固定長バッファで送受信し、メタデータの `LENGTH`はバイト長です。 ## 例の後片付け このページで実際に作成したテーブルのみ削除します。代替DDLを実行していない場合は、 そのテーブルのDROP文も実行しません。 ```sql DROP TABLE time_sensor; DROP TABLE rail_sensor; DROP TABLE weather_station; DROP TABLE temperature_sensor; DROP TABLE thermo_sensor; DROP TABLE vibration_sensor; DROP TABLE example; DROP TABLE example_lower_only; DROP TABLE example_alter_limits; DROP TABLE example_alter_upper; DROP TABLE t1; DROP TABLE t_bin; DROP TABLE t_limit; DROP TABLE t_dst; DROP TABLE t_src; ``` --- title: "5.3 作成、変更、削除" url: https://docs.machbase.com/ja/dbms/tag-table-usage/create-alter-drop/ language: ja kind: page --- # 5.3 作成、変更、削除 TAGテーブルにはタグ識別子と1つの軸列が必須です。このページでは実行可能な基本例を示し、 全オプションについてはSQLリファレンスを案内します。 ## TAGテーブルの作成 TAGテーブルでは最初の2つの列の役割が固定されています。名前列と軸列は省略できず、 順序を変えたり別の位置に指定したりすると、作成に失敗します。 | 列の位置 | 用途と特性 | | --- | --- | | 1番目 | タグ名です。`VARCHAR`列に`PRIMARY KEY`を指定し、他の型は使用できません。センサー・設備・検査回など繰り返し観測する対象を識別します。同じタグ名で複数のDATA行を入力できるため、リレーショナルテーブルの行ごとの一意キーとは区別します。 | | 2番目 | 観測値を時間または距離・位置で整列・検索します。時間軸は`DATETIME BASETIME`、距離軸は`DOUBLE`、`LONG`、`ULONG`のいずれかに`BASEDISTANCE`を指定します。1つのTAGテーブルに定義できるのは時間軸または距離軸のいずれか1つです。 | | 3番目以降 | 温度、圧力、状態、品質コードなど観測ごとに変化するDATA列です。数値型、`VARCHAR`、`DATETIME`、JSON、数値ARRAY、BINARYを使用できます。複数のDATA列からタグを代表する値を1つ選ぶと、タグごとの値の統計と自動ROLLUPの基準にできます。この場合は`SUMMARIZED`を指定します。任意指定であり、3番目の列にのみ指定できます。 | ARRAYは名前列、軸列、`SUMMARIZED`列には使用できず、それ以外のDATA列で 使用します。LOGテーブルとは異なり、TAGテーブルのDATA列では`TEXT`、`CLOB`、`BLOB`を 使用できないため、長い文字列は`VARCHAR`、バイナリデータは`BINARY`で保存します。型の表記と 値の範囲は[データ型リファレンス](/ja/dbms/reference/sql/types/)を参照してください。 タグごとに1回だけ保存する属性は、上記の列位置ではなく`METADATA`句で別途宣言します。 次の時間軸の例では`location`が該当します。 次の2つのテーブルは、このページ専用の独立した実習用です。既存オブジェクトがないことを 確認して順番に実行します。データの実際の意味に合う時間軸または距離軸を選びます。 距離軸TAGではROLLUPを使用できません。 ### 時間軸TAG ```sql CREATE TAG TABLE ch5_tag_ddl ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ) METADATA ( location VARCHAR(64) ); ``` `SUMMARIZED`を指定すると、2つの効果があります。まず、タグごとのSTATビューに`MIN_VALUE`、 `MAX_VALUE`など値自体の統計がこの列を基準として蓄積されます。`SUMMARIZED`列が ない場合、STATには行数と軸の範囲だけが残り、値の統計は保存されません。次に、`WITH ROLLUP`に よる自動作成とJSONドキュメント全体のROLLUPがこの列を対象とします。 一方、通常の数値ROLLUPは`CREATE ROLLUP ... ON table(column)`で列を直接指定するため、 `SUMMARIZED`がなくても作成できます。値の統計が不要でROLLUPも手動で作成する場合は指定不要です。 指定できる型はサポート対象の数値型とJSONです。ROLLUPの作成条件は [第6章](../../tag-rollup-usage/)を参照してください。 位置・単位などタグごとに1回保存する属性は`METADATA`、測定ごとに変化する値は通常の データ列に定義します。 ### 距離軸TAG ```sql CREATE TAG TABLE ch5_distance_ddl ( name VARCHAR(32) PRIMARY KEY, distance DOUBLE BASEDISTANCE, value DOUBLE ); ``` 小数の距離値には`DOUBLE`、整数の軸には値の範囲に応じて`LONG`または`ULONG`を使用します。 ## TAGテーブルの変更 この節のMETADATA ADD/DROP実習はStandard Editionを前提とします。 TAGデータ列の任意の変更には制限があります。スキーマを拡張する場合は、まず新しいテーブルへの 移行を検討してください。メタデータ列はサポートされる構文で追加・削除できます。 ```sql ALTER TABLE ch5_tag_ddl METADATA ADD COLUMN (team VARCHAR(32)); ALTER TABLE ch5_tag_ddl METADATA ADD COLUMN (limits DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); ALTER TABLE ch5_tag_ddl METADATA DROP COLUMN (team); ALTER TABLE ch5_tag_ddl METADATA DROP COLUMN (limits); ``` Standard EditionではTAG METADATAに固定長の数値ARRAY列を追加できます。 ALTER前から存在するメタデータ行には指定したARRAY DEFAULTが適用されます。ALTER後にTAG DATAの 入力で自動登録されるメタデータ行にはDEFAULTが再適用されず、新しいARRAY列全体がNULLになります。 TAG DATAの通常のARRAY列は`CREATE TABLE`で宣言できますが、ALTERでは追加できません。 TAG METADATA ARRAYにはインデックスが自動作成されず、明示的なインデックスもサポートされません。 詳細は[TAGメタデータ](../tag-metadata/)と [数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 データのある運用テーブルでは、変更前に依存クエリ、SDKの列順序、再入力経路を確認します。 ALTER後は`DESC ch5_tag_ddl;`とMETADATAの検索で変更結果を確認します。 ## TAGテーブルの削除 `DROP TABLE`は生データとメタデータをまとめて削除します。ROLLUPなどの依存オブジェクトがある場合は、 先に依存関係に従って削除する必要があります。TAGの`DROP TABLE ... CASCADE`は関連するROLLUPも 削除できるため、単純な後片付けの標準コマンドにはしません。 Custom ROLLUPの対象テーブルについては、別途依存関係の制約も確認します。 ```sql DROP TABLE ch5_distance_ddl; DROP TABLE ch5_tag_ddl; ``` 正確な属性、許容範囲、DDLは [DDL構文リファレンス](/ja/dbms/reference/sql/syntax/ddl-syntax/)を参照してください。 次に読む内容: - [TAGテーブル構造とスキーマ](../table-structure-schema/) - [TAGデータの入力と変更](../data-input-mutation/) - [TAGメタデータ](../tag-metadata/) --- title: "5.4 データの入力と変更" url: https://docs.machbase.com/ja/dbms/tag-table-usage/data-input-mutation/ language: ja kind: page --- # 5.4 データの入力と変更 TAGデータはSQL `INSERT`、Append API、ファイルロードツールで入力します。SQLの例は機能確認と 少量の入力に使用し、継続的な収集にはAppend APIを優先して検討します。 ## SQL INSERT 次の例では時間軸と距離軸のTAGをそれぞれ作成し、データを確認して削除します。 実習用の名前が既存テーブルと重複しないことを先に確認します。時間軸の名前はセンサーを、 距離軸の名前は1つの検査対象・検査回を識別します。 ```sql CREATE TAG TABLE ch5_input_time ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); INSERT INTO ch5_input_time VALUES ('TEMP_001', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 25.5); INSERT INTO ch5_input_time VALUES ('TEMP_001', TO_DATE('2026-01-01 10:01:00', 'YYYY-MM-DD HH24:MI:SS'), 25.7); CREATE TAG TABLE ch5_input_distance ( name VARCHAR(32) PRIMARY KEY, distance DOUBLE BASEDISTANCE, value DOUBLE, quality INTEGER ); INSERT INTO ch5_input_distance VALUES ('PIPE_A', 0.0, 10.1, 100); INSERT INTO ch5_input_distance VALUES ('PIPE_A', 500.5, 11.2, 100); EXEC TABLE_FLUSH(ch5_input_time); EXEC TABLE_FLUSH(ch5_input_distance); SELECT name, time, value FROM ch5_input_time ORDER BY time; SELECT name, distance, value, quality FROM ch5_input_distance ORDER BY distance; SELECT COUNT(*) FROM ch5_input_time; SELECT COUNT(*) FROM ch5_input_distance; DROP TABLE ch5_input_distance; DROP TABLE ch5_input_time; ``` 各テーブルはそれぞれ2行を返します。時間軸の値は25.5、25.7、距離軸は0.0、500.5です。 タグを事前登録していないため、最初のDATA入力でその名前が自動登録されます。 実際の発生時刻と再送の有無はアプリケーションで管理します。 `TABLE_FLUSH`は、保留中のストレージ・入力バッファを明示的にフラッシュする必要がある 検証・運用手順で使用します。トランザクションのコミットや検索時の可視性を保証する手段ではなく、 通常の収集ループで行ごとに実行しないでください。引数とエラー仕様は [EXECプロシージャリファレンス](/ja/dbms/reference/sql/syntax/execute-procedure-syntax/#table-flush)を 参照してください。 ## メタデータとともに入力 ユーザーメタデータのあるTAGでも、DATAだけを入力して新しいタグを自動登録できます。 位置・単位などを先に指定する必要がある場合は、`INSERT ... METADATA`で登録してからDATAを 入力します。データとメタデータを一緒に渡す構文もサポートされています。 通常のDATA入力のたびに登録済み属性が更新されるとは限りません。システム管理列は入力一覧に 含めないでください。 メタデータ値の登録・更新・削除は[TAGメタデータ](../tag-metadata/)を参照してください。 ## 入力経路の選択 | 経路 | 適している場合 | 確認事項 | | --- | --- | --- | | SQL `INSERT` | 機能確認、低頻度の入力 | 文ごとの解析・往復コスト | | SDK Append | 継続的な高スループット入力 | バッチサイズ、フラッシュ、エラー処理 | | `csvimport` / `machloader` | クライアントファイルの一括ロード | 列順序、日付形式、badファイル | | `LOAD DATA INFILE` | サーバーからアクセスできるファイル | サーバー上のパス・権限、エラーポリシー | SDKごとの接続とAppendの例は[開発ツール連携](/ja/dbms/development-tools-integration/)、 ファイル形式とコマンドは [データの入力・ロード・エクスポート](/ja/dbms/development-tools-integration/data-input-load-export/)を 参照してください。 ## データの訂正 TAG data UPDATEはStandard Editionで、タグの選択条件とBASETIMEの範囲をともに指定して 実行します。タグ名、軸、メタデータ列は通常のdata UPDATEの対象にしません。 訂正後も計算済みのROLLUPは自動変更されないため、ROLLUPがある場合は対象範囲を明示的に 再構築します。手順は[ROLLUP_REBUILD](../../tag-rollup-usage/rollup-rebuild/)を参照してください。 成功応答・失敗行数と再試行ポリシーは、選択した入力APIで確認します。SQLのNULL、SDKのNULL表現、 数値の0を区別し、同じ観測を再送する場合の重複ポリシーも定めます。 数値ARRAY・スパース入力には[ARRAY Appendの例](../../development-tools-integration/data-input-load-export/array-append/)を 使用します。 詳しい手順は[TAGデータの訂正](../tag-data-update-correction/)を参照してください。 --- title: "5.5 検索と分析" url: https://docs.machbase.com/ja/dbms/tag-table-usage/query-analysis/ language: ja kind: page --- # 5.5 検索と分析 TAGテーブルから時系列データを検索する主なパターンを説明します。時間軸・距離軸の範囲検索、 複数タグの検索、統計ビューの活用を含みます。 ## Tagデータの検索 ### サンプルスキーマ(時間軸) 次の例はTAGテーブルに2つのタグを登録し、タグごとに10行を入力します。 `TAG_0001`は2018年1月1日から10日、`TAG_0002`は2月1日から10日のデータを使用します。 ```sql create tag table TAG (name varchar(20) primary key, time datetime basetime, value double summarized); insert into tag metadata values ('TAG_0001'); insert into tag metadata values ('TAG_0002'); insert into tag values('TAG_0001', '2018-01-01 01:00:00 000:000:000', 1); insert into tag values('TAG_0001', '2018-01-02 02:00:00 000:000:000', 2); insert into tag values('TAG_0001', '2018-01-03 03:00:00 000:000:000', 3); insert into tag values('TAG_0001', '2018-01-04 04:00:00 000:000:000', 4); insert into tag values('TAG_0001', '2018-01-05 05:00:00 000:000:000', 5); insert into tag values('TAG_0001', '2018-01-06 06:00:00 000:000:000', 6); insert into tag values('TAG_0001', '2018-01-07 07:00:00 000:000:000', 7); insert into tag values('TAG_0001', '2018-01-08 08:00:00 000:000:000', 8); insert into tag values('TAG_0001', '2018-01-09 09:00:00 000:000:000', 9); insert into tag values('TAG_0001', '2018-01-10 10:00:00 000:000:000', 10); insert into tag values('TAG_0002', '2018-02-01 01:00:00 000:000:000', 11); insert into tag values('TAG_0002', '2018-02-02 02:00:00 000:000:000', 12); insert into tag values('TAG_0002', '2018-02-03 03:00:00 000:000:000', 13); insert into tag values('TAG_0002', '2018-02-04 04:00:00 000:000:000', 14); insert into tag values('TAG_0002', '2018-02-05 05:00:00 000:000:000', 15); insert into tag values('TAG_0002', '2018-02-06 06:00:00 000:000:000', 16); insert into tag values('TAG_0002', '2018-02-07 07:00:00 000:000:000', 17); insert into tag values('TAG_0002', '2018-02-08 08:00:00 000:000:000', 18); insert into tag values('TAG_0002', '2018-02-09 09:00:00 000:000:000', 19); insert into tag values('TAG_0002', '2018-02-10 10:00:00 000:000:000', 20); exec table_flush(tag); ``` 例の最後の`TABLE_FLUSH`はストレージバッファを明示的に処理する手順です。 トランザクションのコミットや検索時の可視性を保証するコマンドとは解釈しません。詳細は [TABLE_FLUSH](/ja/dbms/reference/sql/syntax/execute-procedure-syntax/#table-flush)を参照してください。 ### 全TAGデータの抽出 ```sql select * from tag ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0001 2018-01-01 01:00:00 000:000:000 1 TAG_0001 2018-01-02 02:00:00 000:000:000 2 TAG_0001 2018-01-03 03:00:00 000:000:000 3 TAG_0001 2018-01-04 04:00:00 000:000:000 4 TAG_0001 2018-01-05 05:00:00 000:000:000 5 TAG_0001 2018-01-06 06:00:00 000:000:000 6 TAG_0001 2018-01-07 07:00:00 000:000:000 7 TAG_0001 2018-01-08 08:00:00 000:000:000 8 TAG_0001 2018-01-09 09:00:00 000:000:000 9 TAG_0001 2018-01-10 10:00:00 000:000:000 10 TAG_0002 2018-02-01 01:00:00 000:000:000 11 TAG_0002 2018-02-02 02:00:00 000:000:000 12 TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 TAG_0002 2018-02-05 05:00:00 000:000:000 15 TAG_0002 2018-02-06 06:00:00 000:000:000 16 TAG_0002 2018-02-07 07:00:00 000:000:000 17 TAG_0002 2018-02-08 08:00:00 000:000:000 18 TAG_0002 2018-02-09 09:00:00 000:000:000 19 TAG_0002 2018-02-10 10:00:00 000:000:000 20 [20] row(s) selected. ``` 上記は例の実行結果です。結果の順序を保証する必要がある場合は`ORDER BY name, time`を明示します。 条件のない検索の出力順序は、実行計画とスキャン方向に依存する場合があります。 ### 特定のタグ名によるデータの抽出 TAG名がTAG_0002のデータを検索する例です。 ```sql select * from tag where name='TAG_0002' ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0002 2018-02-01 01:00:00 000:000:000 11 TAG_0002 2018-02-02 02:00:00 000:000:000 12 TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 TAG_0002 2018-02-05 05:00:00 000:000:000 15 TAG_0002 2018-02-06 06:00:00 000:000:000 16 TAG_0002 2018-02-07 07:00:00 000:000:000 17 TAG_0002 2018-02-08 08:00:00 000:000:000 18 TAG_0002 2018-02-09 09:00:00 000:000:000 19 TAG_0002 2018-02-10 10:00:00 000:000:000 20 [10] row(s) selected. ``` ### 時間範囲の検索 TAG_0002に時間範囲を指定してデータを検索する例です。 > `BETWEEN`は両方の境界を含み、`>=`と`<=`を組み合わせた条件と同じです。 > 以下の例は境界時刻にデータがないため、`>`・`<`の条件でも同じ結果を返します。 > 連続する検索区間で境界行を重複して読み取らないようにするには、 > `time >= 開始 AND time < 終了`を使用します。 ```sql select * from tag where name = 'TAG_0002' and time between to_date('2018-02-01') and to_date('2018-02-05') ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0002 2018-02-01 01:00:00 000:000:000 11 TAG_0002 2018-02-02 02:00:00 000:000:000 12 TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 [4] row(s) selected. ``` ```sql select * from tag where name = 'TAG_0002' and time > to_date('2018-02-01') and time < to_date('2018-02-05') ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0002 2018-02-01 01:00:00 000:000:000 11 TAG_0002 2018-02-02 02:00:00 000:000:000 12 TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 [4] row(s) selected. ``` ### 距離軸のサンプルスキーマ 距離軸(`BASE DISTANCE`)のTagテーブルを使用する例です。 ```sql CREATE TAG TABLE trip_tag ( name VARCHAR(20) PRIMARY KEY, distance_m DOUBLE BASE DISTANCE, value DOUBLE, quality INTEGER ); INSERT INTO trip_tag VALUES('ODO_A', 0, 10.1, 100); INSERT INTO trip_tag VALUES('ODO_A', 500, 11.2, 101); INSERT INTO trip_tag VALUES('ODO_A', 1000, 12.3, 102); INSERT INTO trip_tag VALUES('ODO_B', 1000.1, 21.5, 100); INSERT INTO trip_tag VALUES('ODO_B', 1500, 22.1, 101); INSERT INTO trip_tag VALUES('ODO_B', 2000, 22.9, 102); EXEC TABLE_FLUSH(trip_tag); ``` ### 距離区間の検索 ```sql SELECT name, distance_m, value, quality FROM trip_tag WHERE name = 'ODO_A' AND distance_m BETWEEN 0 AND 1000 ORDER BY distance_m; ``` 時間軸と同様、距離軸も軸範囲を絞り込むことが基本的な検索パターンです。 ### DOUBLE距離軸の小数境界による検索 ```sql SELECT name, distance_m, value, quality FROM trip_tag WHERE name = 'ODO_B' AND distance_m BETWEEN 1000.1 AND 2000 ORDER BY distance_m; ``` 数値をそのまま比較するため、`1000`は除外され、`1500`と`2000`は含まれます。 ### 距離軸の実行計画の確認 大規模な距離軸検索では、`EXPLAIN`で距離条件がキー範囲に含まれることを確認します。 ```sql EXPLAIN SELECT name, distance_m, value FROM trip_tag WHERE name = 'ODO_B' AND distance_m BETWEEN 1000.1 AND 2000 ORDER BY distance_m; ``` 確認するポイント: - `KEYVALUE INDEX SCAN`または同様のインデックススキャンが表示されるか - `KEY RANGE`の下に`distance_m between ...`条件が表示されるか ### 距離バケットの集計 次の例は0以上の距離を500単位の区間に分割します。TRUNCは0方向に切り捨てるため、 負の座標の区間が必要な場合は、FLOORなど必要な境界規則を別途選択します。 ```sql SELECT TRUNC(distance_m / 500, 0) * 500 AS dist_bucket, COUNT(*) AS sample_count, MIN(value) AS min_v, MAX(value) AS max_v, AVG(value) AS avg_v FROM trip_tag WHERE name = 'ODO_B' GROUP BY TRUNC(distance_m / 500, 0) * 500 ORDER BY dist_bucket; ``` たとえば`1750`は`1500`のバケットに集計されます。 ### 複数タグの時間範囲検索 2つ以上のタグに同じ時間範囲を適用する例です。対象名の一覧が決まっている場合は`IN`で表します。 対象タグが多い場合の性能は、リストのサイズと時間範囲を合わせて測定します。 ```sql select * from tag where name in ('TAG_0002', 'TAG_0001') and time between to_date('2018-01-05') and to_date('2018-02-05') ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0001 2018-01-05 05:00:00 000:000:000 5 TAG_0001 2018-01-06 06:00:00 000:000:000 6 TAG_0001 2018-01-07 07:00:00 000:000:000 7 TAG_0001 2018-01-08 08:00:00 000:000:000 8 TAG_0001 2018-01-09 09:00:00 000:000:000 9 TAG_0001 2018-01-10 10:00:00 000:000:000 10 TAG_0002 2018-02-01 01:00:00 000:000:000 11 TAG_0002 2018-02-02 02:00:00 000:000:000 12 TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 [10] row(s) selected. ``` ### 指定値を超えるデータの検索 タグ値の条件も指定できます。TAG_0002の値から、12より大きく15より小さい値を絞り込んだ結果です。 ```sql select * from tag where name = 'TAG_0002' and value > 12 and value < 15 and time between to_date('2018-02-01') and to_date('2018-02-05') ORDER BY name, time; ``` ```text NAME TIME VALUE -------------------------------------------------------------------------------------- TAG_0002 2018-02-03 03:00:00 000:000:000 13 TAG_0002 2018-02-04 04:00:00 000:000:000 14 [2] row(s) selected. ``` ### タグ別統計ビュー`V$
_STAT` Tagテーブルを作成すると、Tag IDごとの統計情報を集計する仮想テーブルが自動作成されます。 この仮想テーブルの名前はv${tagテーブル名}_statです。 タグ名・軸に関する統計と、3番目のSUMMARIZED列の値の統計を区別します。 STATはバックグラウンドのインデックス・統計処理状態を反映するため、直前の入力の検証は 元データのSELECTと合わせて行います。すぐに統計を確認する実習では、TABLE_FLUSHの後に INDEX_FLUSHで処理を待ちます。 BASE DISTANCEの軸別STATスキーマはMachbase 8.7.0からサポート 軸に関する列名と型はTAGテーブルの軸によって異なります。 | TAGの軸 | 最小/最大の軸値 | 最小/最大値が発生した軸値 | 最新入力行の軸値 | 軸統計の型 | |--------|--------------|----------------------|------------------|--------------| | `DATETIME BASE TIME` | `MIN_TIME`, `MAX_TIME` | `MIN_VALUE_TIME`, `MAX_VALUE_TIME` | `RECENT_ROW_TIME` | `DATETIME` | | `DOUBLE/LONG/ULONG BASE DISTANCE` | `MIN_DISTANCE`, `MAX_DISTANCE` | `MIN_VALUE_DISTANCE`, `MAX_VALUE_DISTANCE` | `RECENT_ROW_DISTANCE` | 元のBASE DISTANCEの型 | 両Editionの共通列は`NAME`、`ROW_COUNT`、`MIN_VALUE`、`MAX_VALUE`です。 Cluster Editionではスキーマの先頭に`HOSTNAME VARCHAR(64)`が追加されます。 #### BASE TIME STATスキーマ ```sql DESC v$tag_stat; ``` ```text [ COLUMN ] ---------------------------------------------------------------------------------------------------- NAME NULL? TYPE LENGTH ---------------------------------------------------------------------------------------------------- NAME varchar 100 ROW_COUNT ulong 20 MIN_TIME datetime 31 MAX_TIME datetime 31 MIN_VALUE double 17 MIN_VALUE_TIME datetime 31 MAX_VALUE double 17 MAX_VALUE_TIME datetime 31 RECENT_ROW_TIME datetime 31 ``` 3番目の列にSUMMARIZEDキーワードがない場合、VALUE関連情報 (MIN_VALUE、MAX_VALUE、MIN_VALUE_TIME、MAX_VALUE_TIME)は保存されません。 収集される統計情報は次のとおりです。 |列名|情報| |--|--| |NAME|Tag IDの名前| |ROW_COUNT|行数| |MIN_TIME|該当Tag IDの行で最小のbasetime列値| |MAX_TIME|該当Tag IDの行で最大のbasetime列値| |MIN_VALUE|該当Tag IDの行で最小のsummarized列値| |MIN_VALUE_TIME|MIN_VALUEとともに挿入されたbasetime列値| |MAX_VALUE|該当Tag IDの行で最大のsummarized列値| |MAX_VALUE_TIME|MAX_VALUEとともに挿入されたbasetime列値| |RECENT_ROW_TIME|最も最近に挿入されたbasetime列値| 次の統計実習は、前の20行の検索例とは別のテーブルを使用します。そのため、以下の2つのタグだけが 検索され、前のTAG_0001・TAG_0002が統計の期待結果に混在しません。 1. SUMMARIZED列がある場合 ```sql CREATE TAG TABLE ch5_stat_time (name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED); ``` ```sql INSERT INTO ch5_stat_time VALUES('tag-0', TO_DATE('2021-08-12'), 10); INSERT INTO ch5_stat_time VALUES('tag-0', TO_DATE('2021-08-13'), 10); INSERT INTO ch5_stat_time VALUES('tag-0', TO_DATE('2021-08-14'), 20); INSERT INTO ch5_stat_time VALUES('tag-0', TO_DATE('2021-08-11'), 5); INSERT INTO ch5_stat_time VALUES('tag-1', TO_DATE('2022-08-12'), 100); INSERT INTO ch5_stat_time VALUES('tag-1', TO_DATE('2022-08-11'), 200); INSERT INTO ch5_stat_time VALUES('tag-1', TO_DATE('2022-08-10'), 50); ``` ```sql EXEC TABLE_FLUSH(ch5_stat_time); EXEC INDEX_FLUSH(ch5_stat_time); SELECT * FROM v$ch5_stat_time_stat ORDER BY name; ``` ```text NAME ROW_COUNT MIN_TIME MAX_TIME MIN_VALUE --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MIN_VALUE_TIME MAX_VALUE MAX_VALUE_TIME RECENT_ROW_TIME --------------------------------------------------------------------------------------------------------------------------------- tag-0 4 2021-08-11 00:00:00 000:000:000 2021-08-14 00:00:00 000:000:000 5 2021-08-11 00:00:00 000:000:000 20 2021-08-14 00:00:00 000:000:000 2021-08-11 00:00:00 000:000:000 tag-1 3 2022-08-10 00:00:00 000:000:000 2022-08-12 00:00:00 000:000:000 50 2022-08-10 00:00:00 000:000:000 200 2022-08-11 00:00:00 000:000:000 2022-08-10 00:00:00 000:000:000 [2] row(s) selected. ``` 2. SUMMARIZED列がない場合 ```sql CREATE TAG TABLE other_tag (name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE); ``` ```text Executed successfully. ``` ```sql INSERT INTO other_tag VALUES('tag-0', TO_DATE('2021-08-12'), 10); INSERT INTO other_tag VALUES('tag-0', TO_DATE('2021-08-13'), 10); INSERT INTO other_tag VALUES('tag-0', TO_DATE('2021-08-14'), 20); INSERT INTO other_tag VALUES('tag-0', TO_DATE('2021-08-11'), 5); INSERT INTO other_tag VALUES('tag-1', TO_DATE('2022-08-12'), 100); INSERT INTO other_tag VALUES('tag-1', TO_DATE('2022-08-11'), 200); INSERT INTO other_tag VALUES('tag-1', TO_DATE('2022-08-10'), 50); ``` ```sql EXEC TABLE_FLUSH(other_tag); EXEC INDEX_FLUSH(other_tag); SELECT * FROM v$other_tag_stat ORDER BY name; ``` ```text NAME ROW_COUNT MIN_TIME MAX_TIME MIN_VALUE --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MIN_VALUE_TIME MAX_VALUE MAX_VALUE_TIME RECENT_ROW_TIME --------------------------------------------------------------------------------------------------------------------------------- tag-0 4 2021-08-11 00:00:00 000:000:000 2021-08-14 00:00:00 000:000:000 NULL NULL NULL NULL 2021-08-11 00:00:00 000:000:000 tag-1 3 2022-08-10 00:00:00 000:000:000 2022-08-12 00:00:00 000:000:000 NULL NULL NULL NULL 2022-08-10 00:00:00 000:000:000 [2] row(s) selected. ``` #### BASE DISTANCE STATスキーマ 距離軸TAGテーブルの統計ビューは、距離値を数値型で提供します。 ```sql CREATE TAG TABLE distance_sensor ( name VARCHAR(32) PRIMARY KEY, odometer_m DOUBLE BASE DISTANCE, value DOUBLE SUMMARIZED ); INSERT INTO distance_sensor VALUES('sensor', 20.5, 8); INSERT INTO distance_sensor VALUES('sensor', 10.25, 3); INSERT INTO distance_sensor VALUES('sensor', 30.75, 5); EXEC TABLE_FLUSH(distance_sensor); EXEC INDEX_FLUSH(distance_sensor); ``` Standard Editionの`DOUBLE BASE DISTANCE`テーブルのスキーマは次のとおりです。 ```sql DESC V$DISTANCE_SENSOR_STAT; ``` ```text [ COLUMN ] ---------------------------------------------------------------------------------------------------- NAME NULL? TYPE LENGTH ---------------------------------------------------------------------------------------------------- NAME varchar 100 ROW_COUNT ulong 20 MIN_DISTANCE double 17 MAX_DISTANCE double 17 MIN_VALUE double 17 MIN_VALUE_DISTANCE double 17 MAX_VALUE double 17 MAX_VALUE_DISTANCE double 17 RECENT_ROW_DISTANCE double 17 ``` 5つの距離軸統計列の型は、元のBASE DISTANCE列の型に従います。 | BASE DISTANCEの型 | STAT列の型 | `DESC`の長さ | |--------------------|----------------|-------------| | `DOUBLE` | `double` | 17 | | `LONG` | `long` | 20 | | `ULONG` | `ulong` | 20 | ```sql SELECT name, row_count, min_distance, max_distance, min_value, min_value_distance, max_value, max_value_distance, recent_row_distance FROM V$DISTANCE_SENSOR_STAT WHERE name = 'sensor'; ``` - `MIN_DISTANCE`と`MAX_DISTANCE`は、該当統計行の最小・最大距離です。 - `MIN_VALUE_DISTANCE`と`MAX_VALUE_DISTANCE`は、それぞれ最小・最大のsummarized値が発生した距離です。 - `RECENT_ROW_DISTANCE`は最大距離ではなく、最も最近に入力された行の距離です。 - `SUMMARIZED`列がない場合、`MIN_VALUE_DISTANCE`と`MAX_VALUE_DISTANCE`は`NULL`です。 ##### Cluster Editionでの検索 Cluster Editionの統計ビューには`HOSTNAME`が追加され、Warehouseごとの統計行が返る場合が あります。まずWarehouseごとの値を確認します。 ```sql SELECT hostname, name, row_count, min_distance, max_distance, min_value, min_value_distance, max_value, max_value_distance, recent_row_distance FROM V$DISTANCE_SENSOR_STAT ORDER BY hostname, name; ``` 行数と距離の境界値は、タグ名ごとに安全に集計できます。 ```sql SELECT name, SUM(row_count) AS row_count, MIN(min_distance) AS min_distance, MAX(max_distance) AS max_distance FROM V$DISTANCE_SENSOR_STAT GROUP BY name; ``` {{< callout type="warning" >}} `MIN_VALUE`と`MIN_VALUE_DISTANCE`、`MAX_VALUE`と`MAX_VALUE_DISTANCE`は、同じWarehouse行の 組み合わせを維持する必要があります。2つの列を独立して`MIN`または`MAX`で集計すると、 異なるWarehouseの値が組み合わされる可能性があります。`RECENT_ROW_DISTANCE`もWarehouseごとの 最新入力距離のため、`MAX(RECENT_ROW_DISTANCE)`をクラスター全体の最新入力行と解釈しないでください。 {{< /callout >}} ##### 8.7.0との互換性 BASE DISTANCE統計ビューの従来の名前はエイリアスとして提供されません。既存テーブルも、 8.7.0サーバーが再起動すると新しいスキーマで構成されます。 | 8.7.0より前の名前 | 8.7.0の名前 | |-----------------|------------| | `MIN_TIME` | `MIN_DISTANCE` | | `MAX_TIME` | `MAX_DISTANCE` | | `MIN_VALUE_TIME` | `MIN_VALUE_DISTANCE` | | `MAX_VALUE_TIME` | `MAX_VALUE_DISTANCE` | | `RECENT_ROW_TIME` | `RECENT_ROW_DISTANCE` | BASE TIME TAGテーブルは従来の`*_TIME DATETIME`スキーマを維持します。 ### スキャン方向のヒント 軸方向の走査と結果のソートを区別します。軸を逆方向に検索したときの最新値は最大の軸値であり、 最後に入力した行を示すSTATのRECENT_ROW値とは異なる場合があります。 同じ軸値を持つ複数行の順序も区別する必要がある場合は、アプリケーションに追加の基準が必要です。 ```sql SELECT * FROM tag WHERE name = 'TAG_0001' ORDER BY time LIMIT 10; SELECT /*+ SCAN_FORWARD(tag) */ name, time, value FROM tag WHERE name = 'TAG_0001' LIMIT 10; SELECT /*+ SCAN_BACKWARD(tag) */ name, time, value FROM tag WHERE name = 'TAG_0001' LIMIT 10; ``` ヒントがない場合のデフォルト方向は [TABLE_SCAN_DIRECTION](/ja/dbms/reference/configuration/configuration/)を参照してください。 ## 後片付け ```sql DROP TABLE ch5_stat_time; DROP TABLE distance_sensor; DROP TABLE trip_tag; DROP TABLE other_tag; DROP TABLE tag; ``` --- title: "5.6 インデックスと性能" url: https://docs.machbase.com/ja/dbms/tag-table-usage/index-performance/ language: ja kind: page --- # 5.6 インデックスと性能 TAGの検索では、まずタグ名と軸の範囲を絞り込むことが基本です。追加インデックスは、実際の検索条件と 実行計画を測定して選択します。 ## 基本的な検索経路 TAGテーブルは`PRIMARY KEY`のタグ名と`BASETIME`または`BASEDISTANCE`の軸を基準として 検索できるように、必要な構造を自動管理します。アプリケーションは、生成されるシステムオブジェクトの 名前や保存段階に依存しないでください。 | 検索条件 | 調整方針 | | --- | --- | | 1つのタグの軸範囲 | タグ名と軸範囲の両方を明示 | | 複数タグの同じ時間範囲 | まず時間範囲を制限し、対象タグ数を管理 | | メタデータ属性 | TAG `METADATA`列として定義 | | 繰り返す時間集計 | ROLLUPを検討 | | 値条件が中心の検索 | 値列のセカンダリインデックスを実行計画で検証 | タグ名や軸範囲を指定せず広範囲のデータを検索すると、読み取り範囲が大きくなります。 常に高速と考えず、実際のデータ量で`EXPLAIN`の結果と実行時間を確認してください。 ## METADATA列 設置場所や装置タイプなど、タグごとに1回定義する属性は`METADATA`列として設計します。 通常のスカラーMETADATA列には検索インデックスが自動提供されます。ただしJSON列自体には 自動インデックスがないため、必要なJSONパスにインデックスを定義します。数値ARRAYメタデータ列では 自動・明示的インデックスのいずれもサポートされません。詳細は [TAGメタデータ](../tag-metadata/)を参照してください。 時系列値や頻繁に変化する状態をMETADATAに入れると、更新経路と意味が不明確になります。 値の性質に応じてTAGデータ列、LOOKUP、VOLATILE、またはTRANSACTION(Standard Edition専用) テーブルを検討してください。 ## 値列のセカンダリインデックス 値条件を頻繁に使用する場合は、`INDEX_TYPE TAG`のセカンダリインデックスを検討できます。 追加インデックスは入力・保存コストを増やすため、作成前後の代表的なクエリを比較します。 次の例では専用の名前で値とJSONパスのインデックスを作成し、実行計画を確認して全オブジェクトを 削除します。小規模なサンプルは構文と結果の検証用であり、性能の優位性を示すものではありません。 名前が重複しない独立した環境で実行します。 ```sql CREATE TAG TABLE ch5_index_tag ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, payload JSON ) METADATA ( location VARCHAR(64) ); INSERT INTO ch5_index_tag METADATA VALUES ('TEMP-01', 'LINE-A'); INSERT INTO ch5_index_tag METADATA VALUES ('TEMP-02', 'LINE-B'); INSERT INTO ch5_index_tag VALUES ('TEMP-01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, '{"state":"normal"}'); INSERT INTO ch5_index_tag VALUES ('TEMP-01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 90.0, '{"state":"alarm"}'); INSERT INTO ch5_index_tag VALUES ('TEMP-02', TO_DATE('2026-01-01 00:02:00', 'YYYY-MM-DD HH24:MI:SS'), 95.0, '{"state":"alarm"}'); CREATE INDEX idx_ch5_index_tag_value ON ch5_index_tag (value) INDEX_TYPE TAG; CREATE INDEX idx_ch5_index_tag_json ON ch5_index_tag (payload->'$.state'); EXPLAIN SELECT name, time, value FROM ch5_index_tag WHERE name = 'TEMP-01' AND time BETWEEN TO_DATE('2026-01-01', 'YYYY-MM-DD') AND TO_DATE('2026-01-02', 'YYYY-MM-DD') AND value > 80.0; SELECT name, value FROM ch5_index_tag WHERE location = 'LINE-A' AND value > 80.0 ORDER BY name, time; SELECT name, value FROM ch5_index_tag WHERE payload->'$.state' = 'alarm' ORDER BY name, time; DROP INDEX idx_ch5_index_tag_json; DROP INDEX idx_ch5_index_tag_value; DROP TABLE ch5_index_tag; ``` 最初のSELECTはTEMP-01の90.0を1行、2番目はTEMP-01の90.0とTEMP-02の95.0を返します。 インデックス作成前後で同じ検索結果になることを確認し、本番規模のデータでは検索時間だけでなく 入力コストとインデックスサイズも比較します。 JSONパス演算子の戻り値の型と比較値の型を合わせ、対象パスが実際にインデックスを使用するか `EXPLAIN`で確認します。 ## 適用しない調整 - TAGの軸列には別途インデックスを作成しません。 - LOG用の`MINMAX_CACHE_SIZE`設定をTAGの値列に適用しません。 - 広い期間の繰り返し集計をセカンダリインデックスだけで解決しようとせず、ROLLUPを検討します。 正確なインデックス構文は[SQL構文リファレンス](/ja/dbms/reference/sql/syntax/)、 測定とチューニング手順は[クエリチューニング](/ja/dbms/performance-tuning/performance-query-tuning/)を 参照してください。 --- title: "5.7 運用とデータライフサイクル" url: https://docs.machbase.com/ja/dbms/tag-table-usage/operations-lifecycle/ language: ja kind: page --- # 5.7 運用とデータライフサイクル TAGデータのライフサイクルは、手動削除、Retention Policy、重複入力の防止で管理します。 このページでは運用上の選択基準を説明します。全SQL構文は関連リファレンスを参照してください。 ## TAGデータの削除 TAGデータはタグ識別子と軸条件を使用して削除範囲を制限します。時間軸TAGの代表的な選択肢は 次のとおりです。 | 目的 | 条件 | | --- | --- | | 1つのタグの全データを削除 | タグの`PRIMARY KEY`の一致 | | 1つのタグの時間範囲を削除 | タグの一致 + BASETIME範囲 | | 全タグの過去データを削除 | BASETIME条件または`BEFORE` | | テーブルの全データを削除 | 条件なしのTAG `DELETE` | 次の例では専用の検証テーブルを作成し、削除範囲を確認して後片付けします。 ```sql CREATE TAG TABLE ch5_lifecycle ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); INSERT INTO ch5_lifecycle VALUES ('TAG_0001', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1.0); INSERT INTO ch5_lifecycle VALUES ('TAG_0001', TO_DATE('2026-01-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0); INSERT INTO ch5_lifecycle VALUES ('TAG_0002', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0); DELETE FROM ch5_lifecycle WHERE name = 'TAG_0001' AND time < TO_DATE('2026-01-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'); SELECT name, time, value FROM ch5_lifecycle ORDER BY name, time; DELETE FROM ch5_lifecycle; SELECT COUNT(*) FROM ch5_lifecycle; DROP TABLE ch5_lifecycle; ``` 最初の削除後は、TAG_0001の2026-01-02の値2.0とTAG_0002の値3.0が残ります。 全削除後のCOUNTは0です。DATAの削除とMETADATAの削除は別の操作です。 タグの登録情報まで削除する場合は[METADATAの削除](../tag-metadata/)の条件も確認します。 削除条件の演算子とEditionごとのサポート範囲は [TAG DELETE構文](/ja/dbms/reference/sql/syntax/dml-syntax/)を参照してください。 手動削除を定期的に繰り返す必要がある場合は、 [Retention Policy](/ja/dbms/operations-configuration-recovery/policy-data-retention/)を使用してください。 ### ROLLUPデータの処理 元のTAGデータの削除と計算済みROLLUPの処理は別です。生データを訂正・削除した後に集計も変更する 必要がある場合は、対象範囲のROLLUPを再構築します。ROLLUPの削除構文を保持ポリシーのように 繰り返し実行しないでください。 - [ROLLUPの部分削除と再構築](/ja/dbms/tag-rollup-usage/rollup-rebuild/) - [TAGデータ訂正後のROLLUP再構築](../tag-data-update-correction/) ## 自動重複排除 `TAG_DUPLICATE_CHECK_DURATION`は重複検査期間を分単位で設定します。 Standard Editionでは0~43200分を指定でき、0は無効化を表します。 Cluster Editionでは0のみ許可されるため、以下の有効化の実習はStandard Edition専用です。 サーバー時刻を基準とする検査期間内のデータで、タグ・軸・データ値が同じ行を重複と判定します。 インデックス処理と重複行の整理中に実行されるため、Appendの成功応答を「重複排除済みの行数」と 解釈しないでください。遅延到着データが検査期間外の場合は期待した重複排除が行われない場合があり、 業務キーの一意制約の代わりにはなりません。 ```sql CREATE TAG TABLE ch5_dedup ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) TAG_DUPLICATE_CHECK_DURATION = 1440; INSERT INTO ch5_dedup VALUES ('TAG_0001', NOW, 1.0); INSERT INTO ch5_dedup SELECT name, time, value FROM ch5_dedup; EXEC TABLE_FLUSH(ch5_dedup); EXEC INDEX_FLUSH(ch5_dedup); SELECT name, time, value FROM ch5_dedup WHERE name = 'TAG_0001'; ALTER TABLE ch5_dedup SET TAG_DUPLICATE_CHECK_DURATION = 60; DROP TABLE ch5_dedup; ``` 2回目の入力は最初の行のコピーなので、軸の時刻も完全に同じです。この実習は運用中の同時入力が ないことを前提とします。ストレージバッファとインデックスの処理を待ち、1行が残ることを確認します。 通常の収集ループで行ごとに2つのフラッシュを呼び出すパターンは使用しません。 全属性と制約は現在のバージョンの [CREATE TAG TABLE構文](/ja/dbms/reference/sql/syntax/ddl-syntax/)で確認してください。 保持ポリシーですでに削除されたデータは、重複判定の対象として残っていません。 ## 運用の確認手順 1. 生データとROLLUPの保持期間をそれぞれ決めます。 2. 遅延到着データの最大遅延を測定し、重複検査期間を決めます。 3. 削除・訂正前に対象タグと時間範囲を`SELECT`で確認します。 4. 大量変更後にROLLUPと代表的な検索結果を検証します。 5. 入力量、ディスク使用量、Retentionの実行状態をまとめて監視します。 --- title: "5.8 制約、エラー、トラブルシューティング" url: https://docs.machbase.com/ja/dbms/tag-table-usage/constraints-errors-troubleshooting/ language: ja kind: page --- # 5.8 制約、エラー、トラブルシューティング このページのUPDATE実習はStandard Editionを前提とします。まず次のテーブルを作成し、 正常なSQLと意図的に失敗するSQLを区別して実行します。失敗例を正常なスクリプトにまとめて 入れないでください。同名の既存オブジェクトは削除しません。 ```sql CREATE TAG TABLE ch5_error_time ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, status INTEGER ) METADATA (location VARCHAR(64)); INSERT INTO ch5_error_time METADATA VALUES ('sensor-01', 'zone-1'); INSERT INTO ch5_error_time METADATA VALUES ('sensor-02', 'zone-2'); INSERT INTO ch5_error_time VALUES ('sensor-01', TO_DATE('2026-07-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 0); INSERT INTO ch5_error_time VALUES ('sensor-02', TO_DATE('2026-07-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 0); CREATE TAG TABLE ch5_error_distance ( name VARCHAR(64) PRIMARY KEY, distance DOUBLE BASEDISTANCE, value DOUBLE SUMMARIZED ); ``` ## TAG data UPDATEのWHERE条件エラー WHERE句にはタグの選択条件とBASETIME条件の両方が必要です。 条件が曖昧な場合や許可されていない形式の場合、UPDATEは拒否されます。 {{< callout type="warning" >}} **必須条件** `WHERE name ...`形式のタグ選択条件と`time ...`形式のBASETIME条件をともに指定します。 条件なしの全件UPDATE、タグ条件だけのUPDATE、時間条件だけのUPDATEは許可されません。 {{< /callout >}} ### 症状 次のようなUPDATEがエラーとして拒否されます。 ```sql -- 時間条件なし UPDATE ch5_error_time SET value = 99.9 WHERE name = 'sensor-01'; -- タグ選択条件なし UPDATE ch5_error_time SET value = 99.9 WHERE time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); -- OR条件を使用 UPDATE ch5_error_time SET value = 99.9 WHERE name = 'sensor-01' OR name = 'sensor-02'; ``` ### 原因 対象タグと時間範囲を明確に制限できない条件は拒否されます。 | 条件の形式 | サポート | |-----------|:--------:| | `name = 'sensor-01' AND time >= ...` | O | | `name IN ('sensor-01', 'sensor-02') AND time BETWEEN ...` | O | | `name LIKE 'sensor-%' AND time < ...` | O | | `value > 10`のみ | X | | `name = 'sensor-01'`のみ | X | | `time >= ...`のみ | X | | `OR`、サブクエリ、集計条件 | X | ### 解決方法 タグ選択条件と時間条件をともに明示します。 ```sql UPDATE ch5_error_time SET value = 99.9 WHERE name = 'sensor-01' AND time = TO_DATE('2026-07-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'); UPDATE ch5_error_time SET status = 1 WHERE name IN ('sensor-01', 'sensor-02') AND time >= TO_DATE('2026-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2026-07-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'); ``` ### NAMEまたはTIMEのバインドが`ERR-02190`で拒否される場合 Machbase 8.7.0以降のStandard Editionでは、次のようにNAMEとBASETIMEの条件値に バインドパラメーターを使用できます。 ```sql UPDATE ch5_error_time SET value = ? WHERE name = ? AND time = ?; ``` タグ選択条件とBASETIME条件の両方があるにもかかわらず、この文が `ERR-02190: Invalid UPDATE/DELETE condition. Specify it as (primary key column) = (value)`で 拒否される場合は、サーバーバージョンを確認します。旧バージョンのサーバーはTAG data UPDATEの NAME/TIMEバインドをサポートしていません。サーバーを8.7.0以降にアップグレードし、名前付きマーカーを 使用する場合は該当する名前付きAPIをサポートする8.7.0 SDKも使用します。 `?`の例はSDKで準備・バインドするSQLであり、machsqlで値を指定せずそのまま実行する文ではありません。 同じプリペアドステートメントを再利用する際は、SET、NAME、TIMEの値をすべて再バインドします。 マーカーの詳細な規則は [TAG data UPDATEのバインド](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/#tag-data-update-predicate-bind)を 参照してください。 大量のUPDATEの前には、同じWHERE条件で`SELECT COUNT(*)`を実行し、変更対象の行数を確認します。 ## TAG data UPDATEのSET対象列エラー SET句は実際のデータ列だけを対象とします。PRIMARY KEY、BASETIME、メタデータ列を SETの対象に指定するとエラーになります。 {{< callout type="warning" >}} **SETの対象** `value`とユーザーデータ列はUPDATEできます。`name`、`time`、METADATAブロックの列は TAG data UPDATEのSET対象ではありません。 {{< /callout >}} ### 症状 ```sql -- エラー: PRIMARY KEY列(name)の更新を試行 UPDATE ch5_error_time SET name = 'new-sensor' WHERE name = 'old-sensor' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); -- エラー: BASETIME列(time)の更新を試行 UPDATE ch5_error_time SET time = NOW WHERE name = 'sensor-01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); -- エラー: メタデータ列をdata UPDATEで変更 UPDATE ch5_error_time SET location = 'zone-2' WHERE name = 'sensor-01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); ``` ### 列の種類別のUPDATE可否 | 列の種類 | 説明 | data UPDATE | |-----------|------|:-----------:| | PRIMARY KEY (`name`) | TAGを識別する一意キー | X | | BASETIME (`time`) | 時系列データのタイムスタンプ | X | | データ列(`value`、補助列) | 実際の行の値 | O | | `SUMMARIZED`データ列 | 統計対象のデータ列 | O | | メタデータ列 | METADATAブロックのタグ属性 | X | ### 解決方法 データ値は通常のUPDATEで変更します。 ```sql UPDATE ch5_error_time SET value = 99.9, status = 1 WHERE name = 'sensor-01' AND time = TO_DATE('2026-07-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'); ``` メタデータには別の構文を使用します。 ```sql UPDATE ch5_error_time METADATA SET location = 'zone-2' WHERE name = 'sensor-01'; ``` タグ名や時間軸を変更する必要がある場合は、新しい`name`/`time`値でデータを挿入してから、 運用ポリシーに従って既存データを削除します。 ## BASE DISTANCE TAG STATの列エラー Machbase 8.7.0はBASE DISTANCE TAGの`V$
_STAT`の軸列を距離の名前と数値型で 提供します。アップグレード前のSQLが`MIN_TIME`、`MAX_TIME`、`RECENT_ROW_TIME`などを検索すると、 列が見つからないエラーになる場合があります。 ### 症状 - アップグレード後、BASE DISTANCE統計ビューの従来の`*_TIME`列を検索できません。 - 旧バージョンのサーバーでは、距離値が`DATETIME`として解釈され、意味のない日付に見える場合があります。 - Cluster EditionでStandardと同じ位置ベースの結果マッピングを使用すると、先頭の`HOSTNAME`に より後続列の対応がずれる場合があります。 ### 診断 対象テーブルの軸と実際の統計ビュースキーマをともに確認します。 ```sql DESC ch5_error_distance; DESC V$CH5_ERROR_DISTANCE_STAT; ``` BASE DISTANCEテーブルの場合、`MIN_DISTANCE`、`MAX_DISTANCE`、`MIN_VALUE_DISTANCE`、 `MAX_VALUE_DISTANCE`、`RECENT_ROW_DISTANCE`が元の距離軸の型で表示される必要があります。 Cluster Editionでは`HOSTNAME VARCHAR(64)`が先頭列に追加されます。 ### 解決方法 1. SQLの従来の`*_TIME`名を、対応する`*_DISTANCE`名に変更します。 2. SDKの結果マッピングを`DATETIME`から元の`DOUBLE`、`LONG`、`ULONG`型に変更します。 3. Clusterの結果は列名で読み取るか、`HOSTNAME`を含めた位置番号を再確認します。 4. BASE TIME TAGのクエリは従来の`*_TIME DATETIME`マッピングを維持します。 全変換表とCluster集計の注意事項は [タグ別統計ビュー](../query-analysis/#tag-stat-axis-schema)を参照してください。 ## 制約と注意事項 ### 機能のサポート範囲 | 機能 | 状態 | |------|------| | 実際の時系列データのUPDATE | Standard Editionでサポート(タグ/BASETIME条件が必要) | | メタデータのUPDATE | サポート(`UPDATE ... METADATA`) | | DELETE | サポート(`BEFORE`、タグ/軸条件、または全削除) | | 複数のPRIMARY KEY | 非サポート(単一列のみ) | | BASETIMEとBASEDISTANCEの同時使用 | 非サポート | | TAG DATAの通常列のALTER ADD/DROP | 非サポート | | TAG METADATA列のALTER ADD/DROP | サポート(Standard Edition) | ### タグ数の制限 - 単一のTAGテーブルに作成できるタグ数はシステム設定によって制限されます。 - タグ数が増えるとタグインデックスとメタデータのメモリ使用量も増えるため、本番規模のデータで 検索・入力性能を測定します。 - タグ名がレコードごとに一意になる設計は避けてください(アンチパターン:[センサーごとのテーブル作成](/ja/dbms/data-modeling-table-design/table-types-patterns-type-anti/#per-sensor-create)を参照)。 ### 遅延到着データ - BASETIME列には任意の過去時刻を挿入できます。 - 遅延到着データが多いワークロードでは、実際の入力レートと検索性能を別途測定します。 ### Cluster Editionのサポート TAGテーブルはCluster Editionでサポートされています。 ただしTAG data UPDATEはStandard Edition専用で、Cluster Editionではサポートされません。 ### まとめ ``` TAGテーブル = センサー名 (PK) + 時間/距離軸 + 計測値 - INSERT/APPEND: O - UPDATE: 実際のDATAはStandard Editionのタグ/BASETIME条件、METADATAは別のSQL - DELETE: O (BEFOREまたはタグ/軸条件) - METADATA: O (別途属性を保存、UPDATE可能) ``` --- **次に読む内容** - [TRANSACTIONテーブルの設計](/ja/dbms/rdb-table-usage/) ## 実習の後片付け 正常な変更結果をSELECTで確認し、今回の実習テーブルのみ削除します。 ```sql SELECT name, time, value, status FROM ch5_error_time ORDER BY name, time; DROP TABLE ch5_error_time; DROP TABLE ch5_error_distance; ``` --- title: "5.9 活用パターンとシナリオ" url: https://docs.machbase.com/ja/dbms/tag-table-usage/patterns-scenarios/ language: ja kind: page --- # 5.9 活用パターンとシナリオ 各例は独立した実習です。テーブルの作成前に同名のオブジェクトがないことを確認します。 タグ名、1回の観測の意味、値の単位、欠損ポリシーを先に決めてからDDLを適用します。 ## 活用例 ### IoTセンサーデータ 工場、ビル、インフラに設置された各種センサーのデータを1つのTAGテーブルで管理します。 ```sql CREATE TAG TABLE factory_sensor ( name VARCHAR(128) PRIMARY KEY, time DATETIME BASETIME, temperature DOUBLE, vibration DOUBLE, current DOUBLE ); -- 同じ設備の同じ観測による測定値を1行にまとめます。 INSERT INTO factory_sensor VALUES ( 'F01/LINE-A/MOTOR-01', NOW, 75.3, 0.15, 2.4 ); ``` このモデルは、1台の装置の同時刻の観測を複数列に保存します。項目別のタグ `.../TEMP`、`.../VIBRATION`を使用する場合は、`name, time, value`形式の単一値モデルを 検討します。項目ごとに測定時刻が異なる場合は、NULLと品質状態でその違いを表現してください。 ### エネルギー監視 電力、ガス、水道メーターのデータを時間ごとに収集します。 ```sql CREATE TAG TABLE energy_meter ( meter_id VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, kwh DOUBLE, voltage DOUBLE, current DOUBLE ); ``` `kwh`が累積計量値の場合、AVG(kwh)は指示値の平均であり、区間使用量ではありません。 消費量は区間境界値の差にリセット・交換・欠損の処理規則を適用して計算します。 電力kWと電力量kWhを区別し、メタデータや収集仕様に単位を明記します。 ### 車両・移動体の追跡 GPS座標と速度を時系列で記録します。 ```sql CREATE TAG TABLE vehicle_track ( vehicle_id VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, lat DOUBLE, lon DOUBLE, speed DOUBLE, heading DOUBLE ); ``` 座標系、緯度・経度、速度の単位を収集仕様に明記します。位置の欠損を数値0で置き換えると、 実際の座標と区別できません。このテーブルの作成によって空間インデックスや経路マッチングが 自動提供されるわけではありません。まず車両・時間区間で検索し、必要な分析を実行します。 ### 適していない場合 - レコードごとにタグ名が変わる場合(タグ数の急増) - タグ・時間範囲を指定せず、全データを頻繁にUPDATEする必要がある場合 - 単純なイベントログ(LOGテーブルを推奨) ## 結果の確認と後片付け IoTの例では、次の検索で3つの測定値が同じ1行として返ることを確認します。 ```sql SELECT name, time, temperature, vibration, current FROM factory_sensor; DROP TABLE factory_sensor; DROP TABLE energy_meter; DROP TABLE vehicle_track; ``` 後片付けは、このページで実際に作成したテーブルだけに適用します。 --- title: "5.10 TAGメタデータ" url: https://docs.machbase.com/ja/dbms/tag-table-usage/tag-metadata/ language: ja kind: page --- # 5.10 TAGメタデータ ## Tagメタデータ ### 概要 METADATAはタグごとに1行の現在の属性です。通常のTAG検索では、同じ属性が各DATA行とともに 表示されます。現在の属性を変えると過去のDATAの検索結果にも新しい属性が表示される場合があるため、 発生時点の属性が必要な場合はDATAまたは別の属性履歴に保存します。 以下では基本メタデータ、JSONメタデータ、全体例を別々のテーブルに分けます。 タグの静的属性を保存する領域として使用し、センサー位置、装置状態、設置情報、外部識別子、 JSONドキュメント形式の属性を格納できます。 メタデータ専用SQLで次の操作を実行できます。以下の例の`TAG`はテーブル名であり、 使用時には実際のTAGテーブル名に置き換えます。 - メタデータ専用の検索 - メタデータ条件による`UPDATE` / `DELETE` - メタデータ行の最終変更時刻の検索 - ARRAYメタデータ列のADD/DROPと既存行へのDEFAULT適用 - `JSON`型メタデータ列の宣言 - JSONパスの検索とJSONパスインデックス - JSONドキュメントの一部だけを変更する部分更新 ユーザーは内部ストレージテーブルを直接操作せず、`TAG METADATA`構文だけを使用できます。 ### メタデータ列の定義 メタデータ列は`CREATE TAG TABLE`の`METADATA (...)`句で定義します。 ```sql CREATE TAG TABLE ch5_meta ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( location VARCHAR(100), status VARCHAR(20), srcip IPV4 ); ``` メタデータ列はタグ名ごとに1行だけ保存されます。 ### ARRAYメタデータ列の追加と削除 Standard Editionでは、既存TAGテーブルのMETADATA領域に固定長の数値ARRAY列を 追加・削除できます。 ```sql INSERT INTO ch5_meta (name, time, value) VALUES ('TEMP_OLD', TO_DATE('2026-09-05 00:00:00'), 10.0); ALTER TABLE ch5_meta METADATA ADD COLUMN (limits DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); INSERT INTO ch5_meta (name, time, value) VALUES ('TEMP_NEW', TO_DATE('2026-09-05 00:00:01'), 20.0); SELECT name, limits FROM ch5_meta METADATA ORDER BY name; ``` ALTER前から存在する`TEMP_OLD`のメタデータ行には`[0.0000, NULL]`が補充されます。 ALTER後にTAG DATAの入力で自動登録された`TEMP_NEW`のメタデータ行にはADD COLUMNのDEFAULTが 再適用されず、`limits`全体がNULLになります。DEFAULTがない場合はALTER前の行も全体がNULLです。 追加したARRAYメタデータ列は、通常のTAG検索の明示的な射影と`SELECT *`にも含まれます。 ARRAYメタデータ列にはインデックスが自動作成されず、以下のような明示的なインデックスも サポートされません。 ```sql -- サポートされず、エラーを返します。 CREATE INDEX idx_sensor_limits ON ch5_meta METADATA(limits); ``` 列を削除する場合も`METADATA`を指定します。 ```sql ALTER TABLE ch5_meta METADATA DROP COLUMN (limits); ``` TAG DATAの通常のARRAY列は`CREATE TAG TABLE`で宣言できますが、ALTERでは追加できません。 サポートされる要素型、要素数、DEFAULTの規則は [数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ### メタデータの入力 メタデータは`INSERT INTO ... METADATA`で入力します。 ```sql INSERT INTO ch5_meta METADATA VALUES ( 'TEMP_001', 'Building-A/F1', 'READY', '192.168.0.11' ); ``` 列一覧も指定できます。 ```sql INSERT INTO ch5_meta METADATA (name, status, srcip, location) VALUES ('TEMP_002', 'STOP', '192.168.0.12', 'Building-A/F2'); ``` 注意事項: - 列一覧を省略したVALUESは、タグ名に続いてメタデータの宣言順に従います。 - 列一覧を指定した場合は、その一覧の順に値を渡します。 - 省略した入力のNULL・DEFAULT処理は、該当DDLと入力経路の規則に従います。 - 識別子はTAGのタグ名列です。この例では`name`という名前で宣言しています。 - メタデータ行の作成時に`_LAST_UPDATE_TIME`がサーバー時刻で自動記録されます。 ### メタデータの検索 #### メタデータのみ検索 メタデータ専用検索は`FROM TAG METADATA`を使用します。 ```sql SELECT name, location, status, srcip FROM ch5_meta METADATA ORDER BY name; ``` この検索はタグ名ごとに1行を返します。 ```sql SELECT * FROM ch5_meta METADATA ORDER BY name; ``` `SELECT *`と`table_alias.*`は`NAME`とメタデータ列のみを返します。 `_LAST_UPDATE_TIME`などのシステム管理列は`SELECT *`の結果に表示されません。 必要な場合は列名を明示します。 #### 最終変更時刻の検索 TAGメタデータには、各メタデータ行の最終変更時刻を示すシステム管理列 `_LAST_UPDATE_TIME`があります。 `_LAST_UPDATE_TIME`はTagデータ行の最終入力時刻ではなく、Tagメタデータ行が作成された時刻、 または実際にメタデータ値が変更された時刻です。 ##### 検索方法 `_LAST_UPDATE_TIME`は列名を明示して検索します。 ```sql SELECT name, _last_update_time FROM ch5_meta METADATA; ``` 他のメタデータ列とともに検索したり、条件に使用したりできます。 ```sql SELECT name, location, status, _last_update_time FROM ch5_meta METADATA WHERE name = 'TEMP_001'; ``` `SELECT *`と`table_alias.*`の結果には`_LAST_UPDATE_TIME`は表示されません。 ##### 自動記録・更新の規則 メタデータ行が新しく作成されると`_LAST_UPDATE_TIME`が自動記録されます。 ```sql INSERT INTO ch5_meta METADATA(name, location, status) VALUES('TEMP_003', 'Building-A/F3', 'READY'); ``` ユーザーメタデータ値が実際に変わると`_LAST_UPDATE_TIME`が更新されます。 ```sql UPDATE ch5_meta METADATA SET status = 'DONE' WHERE name = 'TEMP_003'; ``` 同じ値への更新やJSONの存在しないパスの削除など、保存結果が変わらない更新は実際の変更と みなしません。この場合、`_LAST_UPDATE_TIME`は維持されます。 ```sql UPDATE ch5_meta METADATA SET status = 'DONE' WHERE name = 'TEMP_003'; ``` JSONの存在しないパスの削除も、保存値が変わらなければno-opです。 実行例は以下のJSONテーブルを作成してから確認します。 ##### 直接入力・変更の制限 `_LAST_UPDATE_TIME`はシステム管理列のため、ユーザーが直接値を入力・変更できません。 次の文は許可されません。 ```sql INSERT INTO ch5_meta METADATA(name, location, status, _last_update_time) VALUES('TEMP_004', 'Building-A/F4', 'READY', now); ``` ```sql UPDATE ch5_meta METADATA SET _last_update_time = now WHERE name = 'TEMP_003'; ``` また、TAGの名前列名、TAGメタデータ列名、`ALTER TABLE ... METADATA ADD COLUMN`の 対象列名に`_LAST_UPDATE_TIME`は使用できません。 `ALTER TABLE ... METADATA DROP COLUMN`で`_LAST_UPDATE_TIME`を削除することもできません。 ```sql CREATE TAG TABLE invalid_sensor ( _last_update_time VARCHAR(128) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); ``` ```sql CREATE TAG TABLE invalid_sensor_meta ( name VARCHAR(128) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( _last_update_time DATETIME ); ``` `_LAST_UPDATE_TIME2`のように接頭辞だけが同じ名前は、別のユーザー列として使用できます。 ##### 時間条件による検索と自動インデックス `_LAST_UPDATE_TIME`には時間条件検索用のインデックスが自動提供されます。 ```sql SELECT name, location, _last_update_time FROM ch5_meta METADATA WHERE _last_update_time >= TO_DATE('2026-06-08 00:00:00') ORDER BY _last_update_time; ``` そのため、ユーザーが同じ列に別のインデックスを重複作成する必要はありません。 ##### machloader / tagmetaimportの使用時の注意事項 TAGメタデータのインポートでは、入力ファイルやformファイルには`NAME`とユーザーメタデータ列のみを 含めます。内部列`_ID`とシステム管理列`_LAST_UPDATE_TIME`は入力対象ではありません。 メタデータが`location`、`status`の場合、入力データは次の形式です。 ```text TEMP_001,Building-A/F1,READY TEMP_002,Building-A/F2,STOP ``` `_LAST_UPDATE_TIME`はインポート時にサーバーが自動設定します。 通常のLOG、LOOKUP、VOLATILEテーブルでユーザーが`_LAST_UPDATE_TIME`という列を定義した場合は、 通常のユーザー列として動作します。予約された動作はTAGメタデータのシステム列だけに適用されます。 #### データとともに検索 メタデータ条件で時系列データを検索する場合は、通常の`FROM TAG`を使用します。 ```sql SELECT name, status, time, value FROM ch5_meta WHERE status = 'READY' ORDER BY name, time; ``` この検索はデータ行単位で返すため、同じタグのメタデータ値が各データ行で繰り返されます。 注意事項: - `FROM TAG METADATA`では`TIME`、`VALUE`などのデータ列は検索できません。 - `FROM TAG`はデータ検索モード、`FROM TAG METADATA`はメタデータ検索モードです。 - `TAG METADATA`では内部列`_ID`、`_RID`を使用できません。 ### メタデータの更新 メタデータの更新は`UPDATE TAG METADATA`を使用します。 ```sql UPDATE ch5_meta METADATA SET status = 'DONE', srcip = '10.0.0.20' WHERE name = 'TEMP_001'; ``` メタデータ条件で複数タグを一度に更新することもできます。 ```sql UPDATE ch5_meta METADATA SET status = 'DONE' WHERE status = 'READY'; ``` 注意事項: - 更新対象は`NAME`とメタデータ列です。 - `TIME`、`VALUE`などのデータ列は`UPDATE ... METADATA`で変更できません。 - 内部列は変更できません。 - 実際にメタデータ値が変わった場合だけ`_LAST_UPDATE_TIME`が更新されます。 ### メタデータの削除 メタデータの削除は`DELETE FROM TAG METADATA`を使用します。 特定タグのメタデータを削除する場合は、`WHERE`句でタグ名条件を指定します。 ```sql DELETE FROM ch5_meta METADATA WHERE name = 'TEMP_002'; ``` メタデータ条件で複数タグを一度に削除することもできます。 ```sql DELETE FROM ch5_meta METADATA WHERE status = 'STOP'; ``` `WHERE`句を省略すると全メタデータが対象です。この実習には前に入力したTEMP_OLD・TEMP_NEWの DATAが残っているため、以下の全削除は意図的に失敗します。 ```sql DELETE FROM ch5_meta METADATA; ``` 注意事項: - 削除対象のいずれかに実データ行がある場合、文全体が失敗します。 - つまり、使用中のタグのメタデータは削除できません。 - 全削除でも使用中のタグが1つでもあると、一部だけを削除せず文全体が失敗します。 使用中のタグのメタデータを削除する場合は、先にそのタグのデータ行を削除してから メタデータ削除を再実行します。 ```sql DELETE FROM ch5_meta WHERE name = 'TEMP_001'; DELETE FROM ch5_meta METADATA WHERE name = 'TEMP_001'; ``` ### JSONメタデータ列 メタデータに`JSON`列を宣言できます。 ```sql CREATE TAG TABLE ch5_meta_json ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( status VARCHAR(20), info JSON ); ``` JSONメタデータの入力例: ```sql INSERT INTO ch5_meta_json METADATA VALUES ( 'SHIP_001', 'READY', '{"name":"alpha","ship":{"status":"READY"}}' ); ``` 注意事項: - `JSON`メタデータ列には長さを指定しません。 - 無効なJSON文字列はエラーになります。 - 生のJSON列自体にはインデックスが自動作成されません。 ### JSONの値が変わらない場合 ```sql SELECT name, _last_update_time FROM ch5_meta_json METADATA; UPDATE ch5_meta_json METADATA SET info = JSON_REMOVE(info, '$.missing') WHERE name = 'SHIP_001'; SELECT name, _last_update_time FROM ch5_meta_json METADATA; ``` パスが存在せず保存値が変わらない場合、変更時刻も維持されます。 ### JSONパスの検索 JSONメタデータは`->`演算子で検索できます。 ```sql SELECT name, info->'$.name', info->'$.ship.status' FROM ch5_meta_json METADATA WHERE info->'$.ship.status' = 'READY' ORDER BY name; ``` データ検索でも同じ方法を使用できます。 ```sql SELECT name, time, value FROM ch5_meta_json WHERE info->'$.ship.status' = 'READY' ORDER BY name, time; ``` #### パスの表記規則 検索と部分更新のパスは完全なJSONPathを使用します。 - 通常のキー: `$.name` - ネストしたキー: `$.ship.status` - キー名に`.`または`-`が含まれる場合は角括弧表記を使用 ```sql SELECT info->'$[''ship.owner'']' FROM ch5_meta_json METADATA; SELECT info->'$[''ship-owner'']' FROM ch5_meta_json METADATA; ``` ### JSONパスインデックス #### テーブル作成時に宣言 頻繁に検索するJSONパスは、メタデータ定義時にインデックスを作成できます。 ```sql CREATE TAG TABLE ch5_meta_json_indexed ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( status VARCHAR(20), info JSON INDEX('name', 'ship.status') ); ``` `INDEX(...)`内の文字列は次の規則で解釈されます。 - `'name'`は`$.name` - `'ship.status'`は`$.ship.status` - 特殊文字のあるキーや複雑なパスは完全なJSONPathを直接使用 ```sql INFO JSON INDEX('$[''ship.owner'']') ``` #### 作成後にインデックスを追加 テーブル作成後もJSONパスインデックスを追加できます。 ```sql CREATE INDEX idx_ship_owner ON ch5_meta_json METADATA (info->'$.owner'); ``` #### インデックスの削除 インデックス名だけで削除します。 ```sql SHOW INDEX idx_ship_owner; DROP INDEX idx_ship_owner; ``` 明示的に作成したインデックスは、作成時に指定した名前で管理します。`SHOW INDEX idx_ship_owner;`は DROP前に実行します。削除後に同名を検索すると、存在しないオブジェクトになります。 #### インデックス使用時の注意事項 現在のJSONパスインデックスは、主に文字列比較で動作します。 ```sql SELECT name FROM ch5_meta_json METADATA WHERE info->'$.status' = 'READY'; ``` 文字列リテラルとの比較はインデックスを使用できます。一方、数値リテラルとの比較は フルスキャンになる場合があります。 例: - `info->'$.num' = '10'`: インデックスを使用可能 - `info->'$.num' = 10`: フルスキャンの可能性あり ### JSONの部分更新 JSON関数は、指定パスを変更した新しいドキュメント値を返します。UPDATEはその結果を列に保存します。 これはパス単位の論理更新であり、保存ファイルの一部だけをその場で変更するという性能保証ではありません。 #### JSON_SET SQLのスカラー値をJSONのスカラーとして保存します。 ```sql UPDATE ch5_meta_json METADATA SET info = JSON_SET(info, '$.ship.status', 'DONE') WHERE name = 'SHIP_001'; ``` #### JSON_SET_JSON 入力文字列をJSONとして解釈し、オブジェクトまたは配列を保存します。 ```sql UPDATE ch5_meta_json METADATA SET info = JSON_SET_JSON(info, '$.owner', '{"name":"machbase","team":"db"}') WHERE name = 'SHIP_001'; ``` #### JSON_REMOVE 指定したメンバーまたは下位パスを削除します。 ```sql UPDATE ch5_meta_json METADATA SET info = JSON_REMOVE(info, '$.owner.team') WHERE name = 'SHIP_001'; ``` #### 部分更新の規則 - `JSON_SET(..., path, NULL)`はJSONの`null`を保存します。 - `JSON_SET_JSON(..., path, NULL)`の結果はSQLの`NULL`です。 - JSONドキュメント引数が`NULL`の場合、関数の結果はSQLの`NULL`です。 - パスが`NULL`または空文字列の場合はエラーになります。 - 存在しないパスへの`JSON_REMOVE`はエラーではなくno-opです。 - `JSON_REMOVE(..., '$')`は許可されません。 - 部分更新は主にオブジェクトのパスをサポートします。 - 配列要素のパス更新(例: `$.items[0]`)はサポートしません。 ### 全体例 ```sql CREATE TAG TABLE ch5_meta_complete ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( status VARCHAR(20), srcip IPV4, info JSON INDEX('name', 'ship.status') ); INSERT INTO ch5_meta_complete METADATA VALUES ( 'SHIP_001', 'READY', '192.168.0.11', '{"name":"alpha","ship":{"status":"READY"}}' ); INSERT INTO ch5_meta_complete VALUES ('SHIP_001', '2026-04-01 00:00:00', 10.5); SELECT name, status, info FROM ch5_meta_complete METADATA; SELECT name, time, value FROM ch5_meta_complete WHERE info->'$.ship.status' = 'READY'; CREATE INDEX idx_ship_owner ON ch5_meta_complete METADATA (info->'$.owner'); UPDATE ch5_meta_complete METADATA SET info = JSON_SET(info, '$.ship.status', 'DONE') WHERE name = 'SHIP_001'; DROP INDEX idx_ship_owner; ``` ### まとめ - メタデータ専用検索は`FROM TAG METADATA` - データ検索は`FROM TAG` - メタデータの更新・削除は`UPDATE/DELETE ... METADATA` - ARRAYメタデータ列の変更は`ALTER TABLE ... METADATA ADD/DROP COLUMN` - JSONメタデータは`INFO JSON` - `_LAST_UPDATE_TIME`はメタデータ行の最終変更時刻で、明示的に検索可能 - JSONパスインデックスは`INFO JSON INDEX(...)`または`CREATE INDEX ... ON TAG METADATA (...)` - JSONの部分更新は`JSON_SET`、`JSON_SET_JSON`、`JSON_REMOVE` - `_LAST_UPDATE_TIME`はサーバーが自動管理し、StandardとClusterで同じ動作 ## 実習の後片付け 全削除の失敗例とは異なり、DROPはテーブルとDATA・METADATAをすべて削除します。 以下の名前が今回の実習で作成したオブジェクトであることを確認して実行します。 ```sql DROP TABLE ch5_meta; DROP TABLE ch5_meta_json; DROP TABLE ch5_meta_json_indexed; DROP TABLE ch5_meta_complete; ``` --- title: "5.11 TAG data UPDATEとデータ補正" url: https://docs.machbase.com/ja/dbms/tag-table-usage/tag-data-update-correction/ language: ja kind: page --- # 5.11 TAG data UPDATEとデータ補正 TAG DATAの補正には、元の値を直接変更する方法と、元の値を保持して検索時に補正値を適用する 方法があります。ROLLUPへの影響も異なります。このページのUPDATE実習は Machbase DBMS 8.7.0 Standard Editionを前提とします。 ## 値の直接訂正 タグ名とBASETIMEの条件をともに指定します。SETの右辺では既存行の列を参照できないため、 `SET value = value + 1`のような式ではなく、計算済みの値またはバインドパラメーターを渡します。 次のテーブルを、名前が重複しないことを確認して準備します。ROLLUPの訂正も確認できるように、 デフォルトのROLLUPも作成します。 ```sql CREATE TAG TABLE ch5_correction ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED, status INTEGER ) WITH ROLLUP; INSERT INTO ch5_correction VALUES ('TEMP-01', TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 0); INSERT INTO ch5_correction VALUES ('TEMP-01', TO_DATE('2026-01-01 12:30:00', 'YYYY-MM-DD HH24:MI:SS'), 99.0, 0); INSERT INTO ch5_correction VALUES ('TEMP-02', TO_DATE('2026-01-01 12:30:00', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 0); ``` ### 範囲の確認、更新、再検索 ```sql SELECT COUNT(*), MIN(value), MAX(value) FROM ch5_correction WHERE name = 'TEMP-01' AND time >= TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2026-01-01 13:00:00', 'YYYY-MM-DD HH24:MI:SS'); UPDATE ch5_correction SET value = 25.0, status = 1 WHERE name = 'TEMP-01' AND time >= TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2026-01-01 13:00:00', 'YYYY-MM-DD HH24:MI:SS'); SELECT name, time, value, status FROM ch5_correction ORDER BY name, time; ``` 最初の検索は2件、最小値10.0、最大値99.0です。UPDATE後、TEMP-01の2行はvalue=25.0、 status=1となり、TEMP-02の20.0は維持されます。事前のCOUNTは対象をロックしないため、 同時入力がある作業では基準時刻と範囲を別途制御します。 ### 複数タグとエラー処理 タグの選択には`=`、`IN`、`LIKE`を使用できます。広いパターンや長い時間範囲を変更する前に、 対象名と件数を確認し、小さな範囲に分割します。複数タグは順番に処理される場合があるため、 失敗時に文全体がアトミックに取り消されたと考えないでください。 変更済みの値と残りの対象を再検索してから再試行します。 連続する時間区間を`>= 開始 AND < 終了`で定義すると、境界行を重複処理しません。 1日全体を`23:59:59`までと指定すると、その後の小数秒データを取りこぼす可能性があります。 正確な許容条件とバインディングは[TAG UPDATE](../../reference/sql/syntax/dml-syntax/tag-data-update-syntax/)を 参照してください。 ### ROLLUPの再構築 元データを変更しても計算済みのROLLUPは自動変更されません。上の実習で変更した区間を次のように 再構築し、[ROLLUPの再構築](../../tag-rollup-usage/rollup-rebuild/)の進行状況確認と 検索検証の手順に従います。 ```sql EXEC ROLLUP_REBUILD(ch5_correction, 'TEMP-01', TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2026-01-01 13:00:00', 'YYYY-MM-DD HH24:MI:SS')); ``` ## 元データの保持とNULLへの補正 元の値と補正値を別列に保存すると、最初の値を保持できます。補正値自体がNULLの場合もあるため、 `corrected_value IS NOT NULL`だけで補正の有無を判定せず、フラグを使用します。 ```sql CREATE TAG TABLE ch5_correction_overlay ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, raw_value DOUBLE, corrected_value DOUBLE, is_corrected SHORT ); INSERT INTO ch5_correction_overlay VALUES ('TEMP-01', TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 99.0, NULL, 0); UPDATE ch5_correction_overlay SET corrected_value = NULL, is_corrected = 1 WHERE name = 'TEMP-01' AND time = TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'); SELECT name, raw_value, is_corrected, CASE WHEN is_corrected = 1 THEN corrected_value ELSE raw_value END AS effective_value FROM ch5_correction_overlay; ``` raw_valueは99.0、is_correctedは1、effective_valueはNULLです。フラグが0なら元の値を 使用します。この方法は検索式で値を選択し、raw_valueは変更しません。 デフォルトROLLUPがこのCASE式を自動集計したり、raw_valueの再構築だけで補正を反映したりすると 考えず、有効値を集計する別の検索・集計モデルを定めます。 ## 補正履歴と検証 複数回の変更理由と担当者を残す場合は、別途履歴を記録します。 ```sql CREATE LOG TABLE ch5_correction_log ( sensor_name VARCHAR(64), target_time DATETIME, old_value DOUBLE, new_value DOUBLE, reason VARCHAR(256), corrected_by VARCHAR(64) ); ``` TAGの更新とLOGへの履歴記録は、1つのTRANSACTIONトランザクションにはまとめられません。 実行順序・部分失敗・再試行時に同じ作業を識別する番号をアプリケーションで設計します。 テーブルを作成するだけで監査履歴が自動記録されるわけではありません。 訂正後に元の値・有効値、影響行数、区間統計、レポートを確認します。完了後は今回の実習で作成した オブジェクトのみ削除します。以下のCASCADEはch5_correctionのROLLUPもまとめて削除します。 ```sql DROP TABLE ch5_correction CASCADE; DROP TABLE ch5_correction_overlay; DROP TABLE ch5_correction_log; ``` --- title: "5.12 tagmetaimportとメタデータの一括登録" url: https://docs.machbase.com/ja/dbms/tag-table-usage/tagmetaimport/ language: ja kind: page --- # 5.12 tagmetaimportとメタデータの一括登録 ## tagmetaimportによるメタデータの登録 `tagmetaimport`はCSVのタグ名とユーザーメタデータをインポートするツールです。 通常のSQLの論理TAG名と`-t`の入力先を区別する必要があります。現在のラッパーは`-t`を machloaderに渡します。以下の論理テーブル`ch5_meta_import`のメタデータ入力先は `_CH5_META_IMPORT_META`です。`-t ch5_meta_import`が自動的にMETADATAを選択すると 考えないでください。 この名前はツールの対象指定に使用します。SQLの検索・変更には`ch5_meta_import METADATA`を 使用し、ストレージオブジェクトを直接変更する手順に拡張しないでください。デフォルトの対象に 依存せず、`-t`を明示します。 ## 1. テーブルの準備 既存オブジェクトのない実習用データベースで次のSQLを実行します。 ```sql CREATE TAG TABLE ch5_meta_import ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA ( location VARCHAR(40), status VARCHAR(20) ); ``` ## 2. CSVの準備 次の内容をクライアントの`ch5_metadata.csv`に保存します。 ```csv name,location,status TEMP_001,Building-A/F1,READY TEMP_002,Building-A/F2,STOP TEMP_003,Building-B/F3,READY ``` ファイルにはタグ名に続いてMETADATAの宣言順で値を記載します。DATAのtime・valueと システム列`_ID`・`_LAST_UPDATE_TIME`は含めません。ヘッダーがある場合は`-H`を指定します。 ヘッダーが任意の列順序を自動的に対応付けるとは考えないでください。 ## 3. 入力と結果の確認 アドレス・アカウントを実際の実習用サーバーに合わせ、使用する8.7.0パッケージの`MACHBASE_HOME`と ライブラリ環境で実行します。 ```bash tagmetaimport -s 127.0.0.1 -P 5656 -u SYS -p MANAGER \ -t _CH5_META_IMPORT_META -d ch5_metadata.csv -H \ -l ch5_import.log -b ch5_import.bad ``` 初回実行の期待結果は成功3件・失敗0件です。以下のMETADATA検索は3行を返し、DATAのCOUNTは0です。 メタデータ登録と測定値の入力は異なります。 ```sql SELECT name, location, status, _last_update_time FROM ch5_meta_import METADATA ORDER BY name; SELECT COUNT(*) FROM ch5_meta_import; ``` ## 4. 既存タグと再実行 同じファイルを再入力しても既存タグは自動更新されません。現在の経路は通常のMETADATA INSERTのため、 重複タグはエラー行として集計されます。2回目の実行の期待結果は成功0件・失敗3件で、既存属性は 維持されます。終了ステータスだけでなく、成功・失敗件数とbad/logファイルをまとめて確認します。 新しい行と不正な行が混在するファイルでも、全体が1つのトランザクションになるとは考えません。 反映済みのタグを確認し、失敗行だけを修正して再処理します。既存属性は明示的なUPDATEまたは サポートされるUPSERTで変更します。 ```sql UPDATE ch5_meta_import METADATA SET status = 'DONE' WHERE name = 'TEMP_001'; INSERT INTO ch5_meta_import METADATA VALUES ('TEMP_002', 'Building-C/F2', 'READY') ON DUPLICATE KEY UPDATE; SELECT name, location, status FROM ch5_meta_import METADATA ORDER BY name; ``` TEMP_001はDONEに、TEMP_002はBuilding-C/F2・READYに変わります。 実際に値が変わると変更時刻が更新され、同じ値のno-opでは維持されます。 `tagmetaimport`に自動UPSERTオプションがあると解釈しないでください。 ## 後片付けと関連ドキュメント 結果の確認後、`DROP TABLE ch5_meta_import;`で今回の実習テーブルだけを削除します。 CSV・ログ・badファイルは、再処理に不要であることを確認してから削除します。 詳細なオプションは[tagmetaimportコマンドリファレンス](../../reference/command-line-tools/tagmetaimport/)、 SQLでの登録・変更規則は[TAGメタデータ](../tag-metadata/)を参照してください。 --- title: "6. TAGテーブルのROLLUP活用" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/ language: ja kind: section --- # 6. TAGテーブルのROLLUP活用 ROLLUPは時間軸TAGのデータを事前集計し、検索時に統計を合算して繰り返し分析のコストを減らす機能です。 この章ではMachbase DBMS 8.7.0の基本・条件付き・拡張・JSON・Custom ROLLUPを区別し、 作成から結果検証、再構築までを説明します。 ## 最初に区別する3つの間隔 | 概念 | 意味 | 例 | |---|---|---| | 作成時のINTERVAL | 保存する集計バケットの間隔 | 1 MIN | | WAKEUP INTERVAL | 集計ジョブを起動する周期 | 10 SEC | | クエリのバケット | レポートが要求する結果区間 | `rollup('min', 5, time)` | 同じバケットに複数回の部分集計が保存される場合があります。 基本ROLLUPでは公開クエリ構文が必要な統計をマージし、Customの出力先TAGではユーザーが最終再集計クエリを作成します。 元データの保持期間とROLLUPの保持・再構築ポリシーは別途定めます。 ## この章の構成 | 節 | 内容 | |---|---| | [概要と選択基準](./overview-use-criteria/) | 基本実習と元データ・集計の比較 | | [対象TAGの設計](./target-tag-table-design/) | ON/FROM、階層の制約、容量見積もり | | [作成と削除](./create-delete-rollup/) | CREATE、WITH ROLLUP、IF NOT EXISTSと依存関係 | | [クエリ構文](./query-syntax-rollup/) | 候補選択、時間単位、origin | | [条件付きROLLUP](./conditional-rollup/) | 元データのフィルターと明示的な候補選択 | | [Custom ROLLUP](./custom-rollup/) | 増分結果の再集計とOHLCV階層 | | [拡張ROLLUP](./extension-rollup/) | FIRST/LASTとOHLCの検証 | | [JSON ROLLUP](./json-summarized-rollup/) | パス・ドキュメント全体の集計とNULL | | [制御と状態](./ingestion-control-rollup/) | STOP/START/WAKEUP/FORCE、V$ROLLUPとgap | | [REBUILD](./rollup-rebuild/) | 実際のサポート対象、バケット境界、訂正 | | [パフォーマンスチューニング](./performance-tuning-rollup/) | 同じ結果を基準にコストを比較 | | [活用シナリオ](./patterns-scenarios/) | 複数タグと元データ・集計の役割分担 | 各ページは独立した実習で、オブジェクト名を`ch6_`で区別します。 既存の業務オブジェクトと名前が重複しないことを確認し、意図的なエラー例は成功するスクリプトと分離してください。 固定時刻のデータは、示した固定区間で検索します。実習用テーブル・ROLLUPだけを削除してください。 CustomとREBUILDはStandard Edition専用です。 ROLLUPの作成や取り込みに成功したことだけで、集計が完了したと判断しないでください。 実習では名前を指定したFORCEで処理範囲に追いつき、結果を確認します。 [サポート範囲](../reference/support-scope-constraints/rollup/)と [トラブルシューティング](../troubleshooting/rollup/)で、制約と診断を引き続き確認してください。 --- title: "6.1 ROLLUPの概要と選択基準" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/overview-use-criteria/ language: ja kind: page --- # 6.1 ROLLUPの概要と選択基準 ROLLUPは、生データの行から同じ集計を繰り返すコストを削減します。 元データの保持ポリシーや任意のクエリ結果のキャッシュではなく、集計に保存していない元の情報は復元できません。 ## 選択基準 | 要求 | 検討する方式 | |---|---| | 1つの数値カラムの区間統計を繰り返し使用 | 通常のROLLUP | | 特定の品質条件を満たすサンプルだけを集計 | 条件付きROLLUP | | 区間の最初・最後の値が必要 | EXTENSION ROLLUP | | 複数の集計式を別のTAGに保存 | Custom ROLLUP(Standard Edition専用) | | JSONパスやドキュメント内の数値を集計 | JSONパスまたはドキュメント全体のROLLUP | | 距離軸TAG | 通常の数値区間集計。ROLLUPは未サポート | 通常の数値カラムを明示して作成するROLLUPでは、SUMMARIZEDは必須ではありません。 WITH ROLLUPによる自動作成とJSONドキュメント全体の集計には、別途SUMMARIZEDの条件があります。 詳細は[作成構文](../create-delete-rollup/)を参照してください。 ## 基本実習 ### 1. 作成と入力 ```sql CREATE TAG TABLE ch6_basic ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_basic_ru ON ch6_basic(value) INTERVAL 1 MIN; INSERT INTO ch6_basic VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_basic VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_basic VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_basic VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); ``` ### 2. 集計完了範囲の確認 ```sql EXEC TABLE_FLUSH(ch6_basic); ALTER ROLLUP ch6_basic_ru FORCE; SHOW ROLLUPGAP; ``` SHOW ROLLUPGAPはmachsqlのコマンドです。SDKではV$ROLLUPなど、サポートされるSQLクエリを使用します。 TABLE_FLUSHは保存バッファを処理し、FORCEは指定したROLLUPの処理範囲に追いつくための操作です。 継続入力中に今後到着する行まで処理を完了するという意味ではありません。 ### 3. 元データとの比較 ```sql SELECT DATE_TRUNC('minute', time) AS bucket, COUNT(value), MIN(value), MAX(value), AVG(value) FROM ch6_basic WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; SELECT rollup('min', 1, time) AS bucket, COUNT(value), MIN(value), MAX(value), AVG(value) FROM ch6_basic WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` | バケット | COUNT(value) | MIN | MAX | AVG | |---|---:|---:|---:|---:| | 2026-01-01 00:00:00 | 2 | 10 | 20 | 15 | | 2026-01-01 00:01:00 | 1 | 30 | 30 | 30 | 両方のクエリは同じ結果を返す必要があります。 DATE_TRUNCによる元データの集計が、ROLLUPの存在だけで自動的に切り替わるとは説明しません。 ROLLUPのクエリでは`rollup()`を明示します。 ### 4. クリーンアップ ```sql DROP ROLLUP ch6_basic_ru; DROP TABLE ch6_basic; ``` ## 導入前の確認 代表的なタグ数、入力量、検索頻度、許容できる集計遅延を決めます。 必要な最小の区間と元データの保持期間を先に決め、[階層設計](../target-tag-table-design/)に進んでください。 長期間の性能は本番に近いデータで測定し、この小さなサンプルの実行時間から推定しないでください。 --- title: "6.2 ROLLUP対象TAGテーブルの設計" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/target-tag-table-design/ language: ja kind: page --- # 6.2 ROLLUP対象TAGテーブルの設計 ## ONとFROM `ON source(column)`は元の時間軸TAGの列を集計します。 `FROM rollup_name`は既存の通常・拡張ROLLUPの統計を、より大きい区間に合算します。 Customの出力先もTAGですが、次のCustom段階は出力先TAGをSELECTするINTO...AS構文で構成します。 ## 階層の実習 ```sql CREATE TAG TABLE ch6_design ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_design_sec ON ch6_design(value) INTERVAL 1 SEC; CREATE ROLLUP ch6_design_min FROM ch6_design_sec INTERVAL 1 MIN; CREATE ROLLUP ch6_design_hour FROM ch6_design_min INTERVAL 1 HOUR; INSERT INTO ch6_design VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_design VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_design VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_design VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); EXEC TABLE_FLUSH(ch6_design); ALTER ROLLUP ch6_design_sec FORCE; ALTER ROLLUP ch6_design_min FORCE; ALTER ROLLUP ch6_design_hour FORCE; SELECT name, rollup('hour', 1, time) AS bucket, SUM(value), COUNT(value), AVG(value) FROM ch6_design GROUP BY name, bucket ORDER BY name, bucket; ``` TEMP_01は合計60、件数3、平均20、TEMP_02は100、1、100です。 下位からFORCEを実行すると、上位が新しく作成された下位の結果も処理できます。 ### 階層の制約 - 上位の間隔はソースの間隔より大きい整数倍である必要があります。同じ間隔も許可されません。 - FROMを使って通常のROLLUPを拡張ROLLUPに変更したり、その逆に変更したりすることはできません。 階層内のEXTENSION属性を一致させてください。 - JSONパス・ドキュメントモードもソースと一致する必要があります。 - 必要なクエリの最小区間より粗い統計から、より細かい元データは復元できません。 次は、それぞれ意図的に失敗する作成例です。 ```sql CREATE ROLLUP ch6_design_bad_same FROM ch6_design_min INTERVAL 1 MIN; CREATE ROLLUP ch6_design_bad_divisor FROM ch6_design_min INTERVAL 90 SEC; CREATE ROLLUP ch6_design_bad_ext FROM ch6_design_sec INTERVAL 1 MIN EXTENSION; ``` ## 間隔と保存量の決定 すべてのタグがすべての区間に値を持つと仮定すると、論理バケット数はおおよそ `(保持時間 / バケット間隔) × タグ数`です。1万タグの1秒バケットを365日間保持すると、約3,154億バケットになります。 実際の保存行数は部分集計・空の区間・列数の影響を受け、ディスク容量は圧縮と保存オーバーヘッドも含めて測定する必要があります。 秒単位の観測値を分単位でしか検索しない場合は、最初からすべての秒階層が必要かを検討してください。 作成間隔はSEC/MIN/HOURで表しますが、DAY/WEEK/MONTH/YEARはクエリのバケット単位です。 特に、日単位のクエリに24 HOURの保存間隔をそのまま適用できるとは考えず、[候補選択規則](../query-syntax-rollup/)を確認してください。 新しいROLLUPはソースに残る既存データも初期集計するため、初期処理量とgapを確認します。 元データの補正はFORCEで巻き戻して処理されません。[REBUILDのサポート範囲](../rollup-rebuild/)に従ってください。 ## クリーンアップ ```sql DROP ROLLUP ch6_design_hour; DROP ROLLUP ch6_design_min; DROP ROLLUP ch6_design_sec; DROP TABLE ch6_design; ``` --- title: "6.3 ROLLUPの作成と削除" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/create-delete-rollup/ language: ja kind: page --- # 6.3 ROLLUPの作成と削除 ## 作成構文 ```text CREATE ROLLUP [IF NOT EXISTS] name ON source_tag [(column_or_json_path)] INTERVAL n (SEC|MIN|HOUR) [WAKEUP INTERVAL m (SEC|MIN|HOUR)] [EXTENSION] [WHERE predicate]; CREATE ROLLUP [IF NOT EXISTS] name FROM source_rollup INTERVAL n (SEC|MIN|HOUR) [WAKEUP INTERVAL m (SEC|MIN|HOUR)] [EXTENSION] [WHERE predicate]; ``` EXTENSIONの後に別の拡張名は指定しません。CREATEの単位はSEC/MIN/HOURであり、 クエリ関数のDAY/MONTHなどとは区別します。間隔は正数で、現在の検証上限は365日に相当する間隔です。 ソース・階層・集計モードの条件も満たす必要があります。 | 対象 | 条件 | |---|---| | 通常の数値カラム | サポートされる数値型を指定。SUMMARIZEDは必須ではない | | JSONパス | 対象のJSONカラムと有効なパスを指定 | | JSONドキュメント全体 | JSON SUMMARIZEDカラムが必要 | | WITH ROLLUPによる自動作成 | 3番目にSUMMARIZEDカラムが必要 | | METADATA・距離軸・TAG以外 | 通常のROLLUPの対象外 | ## 作成・重複確認・検索の実習 ```sql CREATE TAG TABLE ch6_create ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP IF NOT EXISTS ch6_create_ru ON ch6_create(value) INTERVAL 1 MIN; CREATE ROLLUP IF NOT EXISTS ch6_create_ru ON ch6_create(value) INTERVAL 1 MIN; INSERT INTO ch6_create VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_create VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_create VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_create VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); EXEC TABLE_FLUSH(ch6_create); ALTER ROLLUP ch6_create_ru FORCE; SELECT DISTINCT ROLLUP_NAME, COLUMN_NAME, INTERVAL_TIME, WAKEUP_INTERVAL FROM V$ROLLUP WHERE ROLLUP_NAME = 'CH6_CREATE_RU'; SELECT rollup('min', 1, time) AS bucket, AVG(value) FROM ch6_create WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` 同名で再作成しても既存の定義は保持されます。IF NOT EXISTSは定義の変更や同一性の確認機能ではなく、 不正なSQLやソースの検証をすべて省略するオプションでもありません。 2つの間隔カラムは60000msで、検索結果の平均は00:00が15、00:01が30です。 IF NOT EXISTSなしで同じ名前を作成するとエラーになります。通常の実習とは別に確認してください。 ```sql CREATE ROLLUP ch6_create_ru ON ch6_create(value) INTERVAL 1 MIN; ``` ## WITH ROLLUPによる自動作成 次は別のテーブルです。SECからMIN・HOURまでの基本階層を自動作成します。 ```sql CREATE TAG TABLE ch6_auto ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ) WITH ROLLUP (SEC); SELECT DISTINCT ROLLUP_NAME, ROOT_TABLE, INTERVAL_TIME, EXT_TYPE FROM V$ROLLUP WHERE ROOT_TABLE = 'CH6_AUTO' ORDER BY INTERVAL_TIME; ``` INTERVAL_TIMEが1000・60000・3600000の3行が返されます。 EXTENSIONの自動作成は`WITH ROLLUP (SEC) EXTENSION`形式です。 実際の作成名はV$ROLLUPで確認し、名前の競合が自動的に解消されるとは考えないでください。 引数に応じて作成される階層が異なります。`(SEC)`はSEC・MIN・HOURの3つ、`(MIN)`はMIN・HOURの2つ、 `(HOUR)`はHOURを1つ作成します。引数の省略は`(SEC)`と同じです。 このとき、最初の段階だけが元のTAGをソースとし、次の段階は直前のROLLUPをソースとする階層で接続されます。 引数にはSEC・MIN・HOURのみ使用でき、クエリ関数が受け付けるDAYなどの単位を指定するとエラーになります。 ## 削除と定義変更 他のROLLUPが参照するソースは、上位の依存オブジェクトから削除します。 Customの出力先TAGは、ジョブを削除するまでDROPできません。 定義を変更する場合は、読み取り側アプリケーションと再集計時間を考慮し、新しいオブジェクトへ切り替えるか、既存の定義を削除して再作成します。 ```sql DROP ROLLUP ch6_create_ru; DROP TABLE ch6_create; DROP TABLE ch6_auto CASCADE; ``` 最後のCASCADEは、この実習で自動作成したROLLUPも削除します。通常の運用での削除方法のデフォルトにはしないでください。 CustomソースのCASCADEが関連ジョブを削除しても、ユーザーの出力先TAGまで自動削除するという意味ではありません。 条件付き・拡張・JSON・Customの実習は各節で独立して提供します。 完全な構文は[SQLリファレンス](../../reference/sql/syntax/rollup-syntax/)を参照してください。 --- title: "6.4 ROLLUPのクエリ構文" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/query-syntax-rollup/ language: ja kind: page --- # 6.4 ROLLUPのクエリ構文 ## 明示的なROLLUPクエリ ```text rollup(time_unit, period, basetime_column [, origin]) ``` | 引数 | 仕様 | |---|---| | time_unit | SECOND/SEC、MINUTE/MIN、HOUR、DAY、WEEK、MONTH、YEAR。大文字・小文字は区別しない | | period | 正の整数リテラル。カラムやパラメータープレースホルダーは不可 | | basetime_column | 元の時間軸TAGのBASETIMEカラム | | origin | 省略時はタイムゾーンオフセットを反映したデフォルト基準点。明示時は単位別の制約を確認 | 戻り値はDATETIMEのバケットです。保存済み集計の最小間隔より細かい結果は復元できません。 適用可能なROLLUPがない場合は、生データのスキャンへ自動的に切り替わらず、エラーになります。 元データの集計が必要なら、DATE_TRUNC/DATE_BIN + GROUP BYのクエリを別途作成してください。 ## 準備と基本クエリ ```sql CREATE TAG TABLE ch6_query ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_query_sec ON ch6_query(value) INTERVAL 1 SEC; INSERT INTO ch6_query VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_query VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_query VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_query VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); EXEC TABLE_FLUSH(ch6_query); ALTER ROLLUP ch6_query_sec FORCE; SELECT name, rollup('min', 1, time) AS bucket, COUNT(value), SUM(value), MIN(value), MAX(value), AVG(value) FROM ch6_query WHERE time >= TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2026-01-01 00:02:00', 'YYYY-MM-DD HH24:MI:SS') GROUP BY name, bucket ORDER BY name, bucket; ``` TEMP_01の00:00はCOUNT=2、SUM=30、AVG=15、00:01は1、30、30です。 TEMP_02の00:00は1、100、100です。SELECTでnameを返す場合は、GROUP BYにもnameを指定します。 nameを省略すると複数タグをまとめた集計になるため、単位の異なるセンサーを混在させないでください。 ## 候補選択とヒント 1. ROLLUP_TABLEヒントがある場合は、その候補の互換性を検査します。 2. 自動選択では、集計カラム・JSONパス・モードと要求間隔に合う候補を探します。 3. 条件なしの候補を先に探し、なければ条件付き候補を含めて検索します。 4. 適用可能な最大の間隔を選び、同じ間隔では先に登録された候補を維持します。 通常か拡張かだけで「通常が常に優先される」と断定しないでください。 条件付きROLLUPしかない場合はフィルタリング済みデータが自動選択され得るため、結果が表すサンプル集合を確認します。 特定の集計を必ず使用する必要がある場合は、ヒントを明示してください。 ```sql SELECT /*+ ROLLUP_TABLE(ch6_query_sec) */ rollup('min', 1, time) AS bucket, AVG(value) FROM ch6_query WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` ### 保存候補の間隔とクエリのバケット 現在の候補間隔検査では、SEC要求をperiod秒、MIN要求をperiod分として計算します。 HOURおよびDAY/WEEK/MONTH/YEAR要求は、候補選択段階でperiod時間を基準に検査し、 選択した統計を要求されたカレンダー・時間バケットへ再集計します。 したがって、`rollup('day', 1, time)`のために24 HOUR ROLLUPを作成すれば自動的に使用できるとは考えないでください。 この要求では1時間の基準に合うHOUR/MIN/SEC候補を検討します。 作成時のINTERVALと結果バケットの意味を区別し、実際の実行計画を確認してください。 ## 集計関数とサンプル 通常の数値ROLLUPはMIN、MAX、SUM、COUNT、AVG、SUMSQをサポートします。 ROLLUPクエリのFIRST/LASTにはEXTENSIONが必要です。 Customの結果は通常のTAGに保存されるため、[Customの再集計](../custom-rollup/)の合計・件数の規則を使用します。 JSONドキュメント全体の集計におけるCOUNTは、[JSONの節](../json-summarized-rollup/)で別途説明します。 ### SUMSQと分散・標準偏差 ROLLUPクエリはSTDDEV、STDDEV_POP、VARIANCE、VAR_POPを直接サポートしていません。 `rollup()`クエリでこれらの関数を使用すると、 `ERR-02816: Only rollup column with aggregate function can be referenced in ROLLUP SELECT query.` が発生します。分散と標準偏差は、区間別の結果をそのまま加算できないためです。 2つの区間の標準偏差を平均しても、全区間の標準偏差にはなりません。 代わりにROLLUPは、値の平方和であるSUMSQをCOUNT、SUMと併せて保存します。 この3つはすべて加算できるため、保存間隔より大きいバケットに再集計しても有効であり、クエリ時に分散と標準偏差を計算できます。 SUMSQは通常のROLLUPとEXTENSION ROLLUPの両方に含まれます。 | 値 | 計算式 | |---|---| | 母分散 | `SUMSQ/N - (SUM/N)^2` | | 母標準偏差 | 母分散の平方根 | | 標本分散 | `(SUMSQ - SUM^2/N) / (N-1)` | | 標本標準偏差 | 標本分散の平方根 | Nは`COUNT(value)`であり、NULLを除いた有効値の個数です。 ROLLUPのクエリブロックにはサポートされる集計だけを置き、分散と標準偏差はインラインビューの外で計算します。 COUNT、SUM、SUMSQを一度だけ読み取り、派生計算を分離するため、計算式を変更してもROLLUPクエリ部分はそのまま使用できます。 ```sql SELECT bucket, n, s, sq, sq/n - POWER(s/n, 2) AS var_pop, SQRT(sq/n - POWER(s/n, 2)) AS stddev_pop FROM ( SELECT rollup('min', 1, time) AS bucket, COUNT(value) AS n, SUM(value) AS s, SUMSQ(value) AS sq FROM ch6_query WHERE name = 'TEMP_01' GROUP BY bucket ) t ORDER BY bucket; ``` 00:00バケットの値は10と20なので、n=2、s=30、sq=500、母分散25、母標準偏差5です。 00:01バケットは値が1つなので、母分散と母標準偏差は0です。 標本分散の分母は`N-1`のため、値が1つのバケットを先に判別する必要があります。 この判定もインラインビューの外で行います。`ELSE NULL`を明示すると`ERR-02042`が発生するため、`ELSE`を省略します。 ```sql SELECT bucket, n, CASE WHEN n > 1 THEN (sq - POWER(s, 2)/n) / (n - 1) END AS var_samp FROM ( SELECT rollup('min', 1, time) AS bucket, COUNT(value) AS n, SUM(value) AS s, SUMSQ(value) AS sq FROM ch6_query WHERE name = 'TEMP_01' GROUP BY bucket ) t ORDER BY bucket; ``` 00:00バケットの標本分散は50、値が1つの00:01バケットはNULLです。 値が1つの区間を結果から除くには、インラインビューの外で`WHERE n > 1`を使用します。 元テーブルの`VARIANCE`と`STDDEV`は同じ区間でNULLではなく0を返すため、両方の結果を併用する場合は表示ポリシーを合わせてください。 上の例の値では、元テーブルに`VAR_POP`、`STDDEV_POP`、`VARIANCE`、`STDDEV`を直接使用した結果と一致します。 ただし、2つの計算式は平均が大きく偏差が小さいほど桁落ちが発生します。 例えば、値が100000付近で小数点以下だけ変動する場合、`SUMSQ/N`と`(SUM/N)^2`がほぼ同じ大きさになり、減算結果の有効桁数が減少します。 浮動小数点誤差で分散がごく小さな負数になると、`SQRT`の結果も無効になります。 精度が重要な区間では、元テーブルの`STDDEV`、`VAR_POP`の結果と比較し、使用可能な範囲を確認してください。 ## カレンダー単位とorigin 同じ準備データを使用し、月単位の結果と月曜日を基準にした週単位を確認します。 ```sql SELECT rollup('month', 1, time, '2000-01-01 00:00:00') AS bucket, SUM(value), COUNT(value), AVG(value) FROM ch6_query WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; SELECT rollup('week', 1, time, '1970-01-05 00:00:00') AS bucket, AVG(value) FROM ch6_query WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` 月単位のクエリは2026-01-01バケットにSUM=60、COUNT=3、AVG=20を返します。 月・年のoriginはタイムゾーン解釈後に月の1日である必要があり、結果はその月境界の午前0時です。 任意の日付や時刻オフセットで月次業務の開始時刻を移す機能と解釈しないでください。 日・週などの固定間隔のoriginと、月・年のカレンダー計算を区別します。 文字列の意味は接続タイムゾーンと併せて確認してください。 DSTが自動的に業務カレンダーに合うと考えず、境界前後の元データのDATE_BIN集計と比較してください。 保存済み集計を分割する必要があるoriginや検索境界では、元データと同じ結果を期待できるか検証します。 ## クリーンアップ ```sql DROP ROLLUP ch6_query_sec; DROP TABLE ch6_query; ``` --- title: "6.5 条件付きROLLUP" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/conditional-rollup/ language: ja kind: page --- # 6.5 条件付きROLLUP ## 元データをフィルタリングしてから集計 条件付きROLLUPは、元データの品質・状態の条件を適用した統計を保持します。 計算済みの平均から後で不良サンプルだけを除く処理とは異なります。 条件で使用したqualityカラム自体が集計結果に保持されるわけでもありません。 ## 1. テーブルと2つのROLLUPの準備 ```sql CREATE TAG TABLE ch6_condition ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_condition_all ON ch6_condition(value) INTERVAL 1 MIN EXTENSION; CREATE ROLLUP ch6_condition_good ON ch6_condition(value) INTERVAL 1 MIN EXTENSION WHERE quality = 1; INSERT INTO ch6_condition VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_condition VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_condition VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_condition VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); INSERT INTO ch6_condition VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:50', 'YYYY-MM-DD HH24:MI:SS'), 90.0, 0); EXEC TABLE_FLUSH(ch6_condition); ALTER ROLLUP ch6_condition_all FORCE; ALTER ROLLUP ch6_condition_good FORCE; ``` ## 2. 元データの条件とROLLUPの比較 ```sql SELECT DATE_TRUNC('minute', time) AS bucket, COUNT(value), AVG(value), MIN(value), MAX(value), FIRST(time, value), LAST(time, value) FROM ch6_condition WHERE name = 'TEMP_01' AND quality = 1 GROUP BY bucket ORDER BY bucket; SELECT /*+ ROLLUP_TABLE(ch6_condition_good) */ rollup('min', 1, time) AS bucket, COUNT(value), AVG(value), MIN(value), MAX(value), FIRST(time, value), LAST(time, value) FROM ch6_condition WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; SELECT /*+ ROLLUP_TABLE(ch6_condition_all) */ rollup('min', 1, time) AS bucket, COUNT(value), AVG(value), MIN(value), MAX(value), FIRST(time, value), LAST(time, value) FROM ch6_condition WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` | バケット・集合 | COUNT | AVG | MIN | MAX | FIRST | LAST | |---|---:|---:|---:|---:|---:|---:| | 00:00 全件 | 3 | 40 | 10 | 90 | 10 | 90 | | 00:00 quality=1 | 2 | 15 | 10 | 20 | 10 | 20 | | 00:01 両集合共通 | 1 | 30 | 30 | 30 | 30 | 30 | このサンプルでは、不良値が区間の最後にあるためLASTも異なります。 FIRST/LASTが返すのは、時刻と値の組ではなく、選択されたvalueです。 ## 候補の明示的な選択 この例では、全件統計と正常値の統計の結果集合を固定するためにヒントを使用します。 自動選択は条件なしの候補を優先しますが、条件付き候補しかない場合はフィルタリング済み統計を選択し得ます。 「条件付きROLLUPは常に無視される」「EXTENSIONでは常にヒントが必須」という規則と解釈しないでください。 ## 構文と制約 通常のROLLUPのフィルターは、INTERVAL・EXTENSIONの後のWHEREに記述します。 比較、BETWEEN、IN、LIKE、論理演算、サポートされるスカラー関数を使用できますが、 サブクエリ、集計関数、タグ名PRIMARY KEYの条件はサポートしていません。 CustomはSELECT内のWHEREを使用するため、構文を混同しないでください。 ## 状態確認とクリーンアップ ```sql SELECT DISTINCT ROLLUP_NAME, PREDICATE, ENABLED FROM V$ROLLUP WHERE ROOT_TABLE = 'CH6_CONDITION'; DROP ROLLUP ch6_condition_good; DROP ROLLUP ch6_condition_all; DROP TABLE ch6_condition; ``` 業務の品質基準が変わったら、条件と再集計計画も更新してください。 既存の集計が新しい条件に自動的に切り替わることはありません。 [制御](../ingestion-control-rollup/)と[再構築範囲](../rollup-rebuild/)を確認してください。 --- title: "6.6 Custom ROLLUP" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/custom-rollup/ language: ja kind: page --- # 6.6 Custom ROLLUP Standard Edition専用 ## Customと通常のROLLUP Custom ROLLUPは、SELECTの増分集計結果を事前作成した出力先TAGに追加します。 通常のROLLUPの内部統計を`rollup()`で読む方式とは異なり、出力先TAGを直接検索して部分集計を再結合する必要があります。 Cluster Editionでは作成できません。 ```text CREATE ROLLUP [IF NOT EXISTS] name INTO (destination_tag) AS (SELECT ... FROM source_tag [WHERE ...] GROUP BY ...) INTERVAL n (SEC|MIN|HOUR) [WAKEUP INTERVAL m (SEC|MIN|HOUR)]; ``` ソースは1つの時間軸TAGで、JOIN・FROMサブクエリは使用できません。 出力先は事前作成したTAGで、SELECTのカラム順序と型に互換性が必要です。 SELECT内のWHEREは使用できますが、BASETIMEの直接条件は許可されません。 通常のROLLUPのように、INTERVALの後に外側のWHEREを付けないでください。 作成間隔とSELECTが計算する時間バケットを一致させてください。 ジョブは新しい入力だけを処理するため、同じバケットに複数の結果行が存在し得ます。 行数をバケット数と解釈しないでください。 ## 1. 合計と有効件数の実習 ```sql CREATE TAG TABLE ch6_custom_src ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ); CREATE TAG TABLE ch6_custom_dst ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, sum_value DOUBLE, valid_count LONG, total_count LONG ); CREATE ROLLUP ch6_custom_ru INTO (ch6_custom_dst) AS ( SELECT name, DATE_TRUNC('minute', time) AS time, SUM(value), COUNT(value), COUNT(*) FROM ch6_custom_src GROUP BY name, time ) INTERVAL 1 MIN; INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:05', 'YYYY-MM-DD HH24:MI:SS'), 10); EXEC TABLE_FLUSH(ch6_custom_src); ALTER ROLLUP ch6_custom_ru FORCE; INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:10', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:15', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:20', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:25', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:35', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:40', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:45', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch6_custom_src VALUES ('S1', TO_DATE('2026-01-01 00:00:55', 'YYYY-MM-DD HH24:MI:SS'), NULL); EXEC TABLE_FLUSH(ch6_custom_src); ALTER ROLLUP ch6_custom_ru FORCE; SELECT name, DATE_TRUNC('minute', time) AS bucket, SUM(value), COUNT(value), COUNT(*), AVG(value) FROM ch6_custom_src GROUP BY name, bucket ORDER BY name, bucket; SELECT name, time, SUM(sum_value) AS sum_value, SUM(valid_count) AS valid_count, SUM(total_count) AS total_count, CASE WHEN SUM(valid_count) = 0 THEN NULL ELSE SUM(sum_value) / SUM(valid_count) END AS avg_value FROM ch6_custom_dst GROUP BY name, time ORDER BY name, time; ``` 1バケットの合計は180、有効値は10個、全行数は11、平均は18です。 部分平均10と20を単純平均した15とは異なります。 NULLを平均の分母に含めないようCOUNT(value)を使用し、NULLを含む行数はCOUNT(*)で別途保持します。 すべての値がNULLのバケットも処理する場合は、有効件数0で除算しない結果ポリシーも決めてください。 ### サンプル比率と時間稼働率 条件を満たすサンプル数を全サンプル数で割った値は、サンプル比率です。 時間稼働率として解釈するには、観測間隔・欠損処理・状態の継続時間を反映する必要があります。 比率も部分比率を平均せず、分子と分母をそれぞれ合算します。 ## 2. OHLCVと1分→10分のCustom階層 独立した実習です。FIRST/LASTの再集計のため、元の最初・最後の観測時刻も保存します。 ```sql CREATE TAG TABLE ch6_ticks ( code VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, price DOUBLE, volume DOUBLE ); CREATE TAG TABLE ch6_candle_min ( code VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, open_price DOUBLE, high_price DOUBLE, low_price DOUBLE, close_price DOUBLE, volume DOUBLE, cnt LONG, firsttime DATETIME, lasttime DATETIME ); CREATE TAG TABLE ch6_candle_10m ( code VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, open_price DOUBLE, high_price DOUBLE, low_price DOUBLE, close_price DOUBLE, volume DOUBLE, cnt LONG, firsttime DATETIME, lasttime DATETIME ); CREATE ROLLUP ch6_candle_ru_min INTO (ch6_candle_min) AS ( SELECT code, DATE_TRUNC('minute', time) AS time, FIRST(time, price), MAX(price), MIN(price), LAST(time, price), SUM(volume), COUNT(*), MIN(time), MAX(time) FROM ch6_ticks GROUP BY code, time ) INTERVAL 1 MIN; CREATE ROLLUP ch6_candle_ru_10m INTO (ch6_candle_10m) AS ( SELECT code, DATE_BIN('min', 10, time, TO_DATE('2000-01-01 00:00:00')) AS time, FIRST(firsttime, open_price), MAX(high_price), MIN(low_price), LAST(lasttime, close_price), SUM(volume), SUM(cnt), MIN(firsttime), MAX(lasttime) FROM ch6_candle_min GROUP BY code, time ) INTERVAL 10 MIN; INSERT INTO ch6_ticks VALUES ('AAPL', TO_DATE('2026-01-01 09:00:00'), 100, 2); INSERT INTO ch6_ticks VALUES ('AAPL', TO_DATE('2026-01-01 09:00:30'), 105, 3); INSERT INTO ch6_ticks VALUES ('AAPL', TO_DATE('2026-01-01 09:01:00'), 103, 1); INSERT INTO ch6_ticks VALUES ('AAPL', TO_DATE('2026-01-01 09:01:30'), 99, 4); EXEC TABLE_FLUSH(ch6_ticks); ALTER ROLLUP ch6_candle_ru_min FORCE; EXEC TABLE_FLUSH(ch6_candle_min); ALTER ROLLUP ch6_candle_ru_10m FORCE; SELECT code, time, FIRST(firsttime, open_price), MAX(high_price), MIN(low_price), LAST(lasttime, close_price), SUM(volume), SUM(cnt) FROM ch6_candle_10m GROUP BY code, time ORDER BY code, time; ``` 09:00の10分バケットは、Open=100、High=105、Low=99、Close=99、volume=10、cnt=4です。 価格や取引量がNULLの場合は、どの行の時刻と値を使用するか、別途規則とテストが必要です。 同時刻の複数の取引にも業務上の順序がある場合は、追加の識別基準を設計してください。 この10分Customは作成・検索の例です。現在のREBUILDのCustom時間範囲処理でサポートする間隔と同じだと考えないでください。 [REBUILDの制限](../rollup-rebuild/)を確認してください。 ## 状態とクリーンアップ 作成後は自動的に開始するため、直後にSTARTを繰り返さないでください。 STOP/STARTとFORCEはジョブの状態に応じて呼び出します。 ジョブが存在する出力先TAGのDROPは拒否されます。 ```sql SELECT DISTINCT ROLLUP_NAME, ROLLUP_TABLE, ROOT_TABLE, EXT_TYPE, INTERVAL_TIME, WAKEUP_INTERVAL FROM V$ROLLUP WHERE ROLLUP_NAME = 'CH6_CUSTOM_RU'; DROP ROLLUP ch6_candle_ru_10m; DROP ROLLUP ch6_candle_ru_min; DROP TABLE ch6_candle_10m; DROP TABLE ch6_candle_min; DROP TABLE ch6_ticks; DROP ROLLUP ch6_custom_ru; DROP TABLE ch6_custom_dst; DROP TABLE ch6_custom_src; ``` EXT_TYPE=2はCustomを表し、PREDICATEにはSELECT本文が記録されます。 クリーンアップでは、実行した実習のオブジェクトだけを対象にしてください。 元データの補正と上位の再集計の再試行・完了確認は、[制御と状態](../ingestion-control-rollup/)およびREBUILDの手順に従ってください。 --- title: "6.7 拡張ROLLUPとFIRST/LAST" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/extension-rollup/ language: ja kind: page --- # 6.7 拡張ROLLUPとFIRST/LAST ## EXTENSIONと元データのFIRST/LASTの違い EXTENSIONはROLLUPに最初・最後の値と関連する時刻情報を追加します。 通常の元データのGROUP BYでFIRST/LASTを使うことと、保存済みROLLUPからFIRST/LASTを取得することは異なります。 後者には、適用可能な拡張ROLLUPが必要です。 EXTENSIONが追加するのは最初・最後の値と時刻だけです。 MIN、MAX、SUM、COUNT、平方和のSUMSQは通常のROLLUPにも保存されます。 SUMSQから分散と標準偏差を計算する方法は、 [SUMSQと分散・標準偏差](../query-syntax-rollup/#query-sumsq-stddev-rollup)を参照してください。 ## 準備と入力 ```sql CREATE TAG TABLE ch6_ext ( code VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, price DOUBLE ); CREATE ROLLUP ch6_ext_first ON ch6_ext(price) INTERVAL 1 MIN EXTENSION; CREATE ROLLUP ch6_ext_plain ON ch6_ext(price) INTERVAL 1 MIN; INSERT INTO ch6_ext VALUES ('AAPL', TO_DATE('2026-01-01 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100); INSERT INTO ch6_ext VALUES ('AAPL', TO_DATE('2026-01-01 09:00:10', 'YYYY-MM-DD HH24:MI:SS'), 105); INSERT INTO ch6_ext VALUES ('AAPL', TO_DATE('2026-01-01 09:00:20', 'YYYY-MM-DD HH24:MI:SS'), 99); INSERT INTO ch6_ext VALUES ('AAPL', TO_DATE('2026-01-01 09:00:30', 'YYYY-MM-DD HH24:MI:SS'), 103); EXEC TABLE_FLUSH(ch6_ext); ALTER ROLLUP ch6_ext_first FORCE; ALTER ROLLUP ch6_ext_plain FORCE; ``` ## 元データとOHLCの比較 ```sql SELECT DATE_TRUNC('minute', time) AS bucket, FIRST(time, price) AS open_price, MAX(price) AS high_price, MIN(price) AS low_price, LAST(time, price) AS close_price FROM ch6_ext WHERE code = 'AAPL' GROUP BY bucket ORDER BY bucket; SELECT /*+ ROLLUP_TABLE(ch6_ext_first) */ rollup('min', 1, time) AS bucket, FIRST(time, price) AS open_price, MAX(price) AS high_price, MIN(price) AS low_price, LAST(time, price) AS close_price FROM ch6_ext WHERE code = 'AAPL' GROUP BY bucket ORDER BY bucket; ``` 両方のクエリは、09:00バケットにOpen=100、High=105、Low=99、Close=103を返します。 ROLLUPのFIRST/LASTの第1引数にはBASETIME、第2引数には集計対象カラムを使用します。 同じ時刻に複数の値がある場合に業務上の追加の順序が必要なら、別途設計してください。 ## 通常の候補と拡張候補が共存する場合 通常のROLLUPが拡張ROLLUPより無条件に優先されるわけではありません。 同じ条件・間隔の候補は、登録順序の影響を受けます。 この例では拡張を先に作成していますが、特定候補を使用する必要がある場合は上記のように明示してください。 拡張だけが適用可能な環境では、ヒントなしで選択される場合もあります。 次は通常のROLLUPを強制するため、意図的に失敗するクエリです。 ```sql SELECT /*+ ROLLUP_TABLE(ch6_ext_plain) */ rollup('min', 1, time) AS bucket, FIRST(time, price) FROM ch6_ext WHERE code = 'AAPL' GROUP BY bucket; ``` 自動階層に拡張が必要なら、別のテーブルのCREATEで`WITH ROLLUP (SEC) EXTENSION`を使用します。 FROMで階層を作成する場合も、拡張属性を一致させる必要があります。 Custom OHLCVの再集計は[Customの実習](../custom-rollup/)を参照してください。 ## クリーンアップ ```sql DROP ROLLUP ch6_ext_plain; DROP ROLLUP ch6_ext_first; DROP TABLE ch6_ext; ``` --- title: "6.8 JSON SUMMARIZED ROLLUP" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/json-summarized-rollup/ language: ja kind: page --- # 6.8 JSON SUMMARIZED ROLLUP ## JSONパスとドキュメント全体の集計 JSONパスROLLUPは指定パスの数値を集計します。 ドキュメント全体のROLLUPは、JSON SUMMARIZEDカラム内の数値パスごとの統計を保持します。 パスが存在しない値、JSON null、SQL NULL、配列を同じサンプルとして解釈しないでください。 ## 準備 ```sql CREATE TAG TABLE ch6_json ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value JSON SUMMARIZED ); CREATE ROLLUP ch6_json_metric ON ch6_json(value.metric) INTERVAL 1 MIN; CREATE ROLLUP ch6_json_whole ON ch6_json(value) INTERVAL 1 MIN; INSERT INTO ch6_json VALUES ('S1', TO_DATE('2026-01-01 00:00:00'), '{"metric":10,"nested":{"x":2},"status":"OK","items":[1,2]}'); INSERT INTO ch6_json VALUES ('S1', TO_DATE('2026-01-01 00:00:10'), '{"metric":20,"nested":{"x":4},"status":"WARN","items":[3,4]}'); INSERT INTO ch6_json VALUES ('S1', TO_DATE('2026-01-01 00:00:20'), '{"metric":null,"status":false}'); INSERT INTO ch6_json VALUES ('S1', TO_DATE('2026-01-01 00:00:30'), NULL); EXEC TABLE_FLUSH(ch6_json); ALTER ROLLUP ch6_json_metric FORCE; ALTER ROLLUP ch6_json_whole FORCE; ``` ## パス集計の比較 ```sql SELECT DATE_TRUNC('minute', time) AS bucket, COUNT(JSON_EXTRACT_DOUBLE(value, '$.metric')), AVG(JSON_EXTRACT_DOUBLE(value, '$.metric')) FROM ch6_json WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; SELECT /*+ ROLLUP_TABLE(ch6_json_metric) */ rollup('min', 1, time) AS bucket, COUNT(value.metric), AVG(value.metric) FROM ch6_json WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; SELECT /*+ ROLLUP_TABLE(ch6_json_metric) */ rollup('min', 1, time) AS bucket, AVG(value->'$.metric') FROM ch6_json WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; ``` metricの有効な数値サンプルは2個で、平均は15です。dotとarrowは同じパスを表します。 特定の配列要素をパスで指定することと、ドキュメント全体の集計が配列を自動展開することは異なります。 パス宣言の例として`value.items[0]."metric-id"`を使用できますが、対象のJSON構造と数値サンプルが実際に存在することを先に確認してください。 ## ドキュメント全体の集計とCOUNT ```sql SELECT COUNT(*) AS raw_rows, COUNT(value) AS raw_documents FROM ch6_json; SELECT /*+ ROLLUP_TABLE(ch6_json_whole) */ rollup('min', 1, time) AS bucket, COUNT(value), AVG(value), MIN(value), MAX(value), SUM(value) FROM ch6_json WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; ``` 元データのCOUNT(*)は4、COUNT(value)は3です。 ドキュメント全体のROLLUPのCOUNT(value)は、保存済みのドキュメント集計件数を合算します。 現在、この集計の件数は元データのCOUNT(*)で作成されるため、上記のように数値パスを持つドキュメントとSQL NULLが混在するバケットでは4です。 通常の元データのCOUNT(value)のNULL除外規則を、そのまま適用しないでください。 AVGの結果はmetricが15、nested.xが3で、各パスの有効な数値サンプルから計算します。 文字列・ブール値・JSON null・配列は数値集計から除外され、数値でないパスはnullまたは省略として現れる場合があります。 JSONシリアライズ時のキー順序を、固定の文字列結果として比較しないでください。 数値パスがないドキュメントやSQL NULLだけの区間は、別のサンプルを作成して確認してください。 JSONパス集計とドキュメント全体の集計は候補モードが異なります。 異なるモードのROLLUPをヒントで強制しても同じ結果になるとは考えないでください。 無効なJSONは入力エラーになります。 ## クリーンアップ ```sql DROP ROLLUP ch6_json_whole; DROP ROLLUP ch6_json_metric; DROP TABLE ch6_json; ``` --- title: "6.9 ROLLUPの制御と状態確認" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/ingestion-control-rollup/ language: ja kind: page --- # 6.9 ROLLUPの制御と状態確認 ## ジョブの状態と処理完了 ROLLUPは作成時に自動的に開始します。直後にSTARTを繰り返したり、停止済みのジョブに再度STOPを実行したりすると、状態エラーが発生する場合があります。 次の実習では、作成 → STOP → 入力 → START → WAKEUP → FORCEの順に状態を区別します。 ```sql CREATE TAG TABLE ch6_control ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_control_ru ON ch6_control(value) INTERVAL 1 MIN WAKEUP INTERVAL 10 SEC; ALTER ROLLUP ch6_control_ru STOP; INSERT INTO ch6_control VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_control VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_control VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_control VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); EXEC TABLE_FLUSH(ch6_control); SELECT DISTINCT ROLLUP_NAME, ENABLED, INTERVAL_TIME, WAKEUP_INTERVAL FROM V$ROLLUP WHERE ROLLUP_NAME = 'CH6_CONTROL_RU'; ALTER ROLLUP ch6_control_ru START; ALTER ROLLUP ch6_control_ru WAKEUP; ALTER ROLLUP ch6_control_ru FORCE; SELECT rollup('min', 1, time) AS bucket, AVG(value) FROM ch6_control WHERE name = 'TEMP_01' GROUP BY bucket ORDER BY bucket; ``` 停止状態のENABLEDは0、INTERVAL_TIMEは60000ms、WAKEUP_INTERVALは10000msです。 最後のクエリは、TEMP_01の00:00の平均15と00:01の平均30を返します。 | コマンド | 目的 | 完了の意味 | |---|---|---| | STOP | ジョブを停止 | 以後の未処理入力は残る | | START | 停止したジョブを再開 | 処理位置から続行 | | WAKEUP | ジョブを起動 | 処理完了は待たない | | FORCE | 対象ソースの処理範囲に追いつくまで待機 | 過去の修正分の再計算や将来の入力完了ではない | | ROLLUP_REBUILD | サポート対象の過去バケットを再計算 | 元データの補正後に集計を再構築 | SQL ALTERの代わりに、名前を指定した`EXEC ROLLUP_START(name)`、`ROLLUP_STOP(name)`、 `ROLLUP_FORCE(name)`も使用できます。同じ状態遷移を両方の形式で続けて実行しないでください。 名前を指定しない一括制御と、特定ジョブの制御の範囲を混同しないでください。 ## WAKEUP INTERVAL 省略時は作成時のINTERVALと同じです。正数で、集計間隔以下であり、集計間隔を割り切れる値にする必要があります。 起動頻度を高めると遅延を減らせますが、処理負荷も増加します。 ```sql ALTER ROLLUP ch6_control_ru SET WAKEUP INTERVAL 5 SEC; SELECT DISTINCT ROLLUP_NAME, INTERVAL_TIME, WAKEUP_INTERVAL FROM V$ROLLUP WHERE ROLLUP_NAME = 'CH6_CONTROL_RU'; ``` WAKEUP_INTERVALが5000msになります。次は60秒の約数でない値を使う意図的なエラーです。 ```sql ALTER ROLLUP ch6_control_ru SET WAKEUP INTERVAL 7 SEC; ``` ## V$ROLLUPの読み方 | カラム | 意味 | |---|---| | ROLLUP_NAME | 制御するジョブ名 | | ROLLUP_TABLE | 集計先テーブル。Customではユーザーの出力先TAG | | SOURCE_TABLE, ROOT_TABLE | 直接のソースと、ジョブを解釈するための元データの関係 | | COLUMN_NAME | 通常集計・パス集計の対象カラム | | INTERVAL_TIME, WAKEUP_INTERVAL | ミリ秒単位の作成間隔・実行間隔 | | LAST_WAKEUP_TIME, NEXT_WAKEUP_TIME | 直前の起動時刻と次の予定時刻 | | EXT_TYPE | 0: 通常、1: 拡張、2: Custom | | PREDICATE | 通常の条件式、またはCustomのSELECT本文 | | ENABLED | ジョブの有効状態 | | RUN_STATE | `I`: 初期、`S`: 待機、`R`: 処理中 | | END_RID | ソースの処理位置 | | LAST_ELAPSED_MSEC | 直前の処理時間(ms) | | DATABASE_NAME, USER_ID | データベース・所有者の識別 | ```sql SELECT ROLLUP_NAME, ROLLUP_TABLE, SOURCE_TABLE, ROOT_TABLE, INTERVAL_TIME, WAKEUP_INTERVAL, LAST_WAKEUP_TIME, NEXT_WAKEUP_TIME, ENABLED, RUN_STATE, LAST_ELAPSED_MSEC FROM V$ROLLUP WHERE ROLLUP_NAME = 'CH6_CONTROL_RU' ORDER BY ROLLUP_NAME; SHOW ROLLUPGAP; ``` SHOW ROLLUPGAPはmachsql専用のクライアントコマンドです。SDKの通常のSQL APIには送信しないでください。 GAPはソースとROLLUPの処理RIDの差です。時間遅延そのものではなく、すべての階層・関連ノードの状態と併せて確認します。 gap=0でも、集計済みの元データに対する補正が反映されたとは限りません。 継続入力中の値は観測時点で変わるため、再現実習では入力を止めて比較します。 停止中に元データが保持ポリシーで削除された場合、STARTだけでは復元できません。 FORCEは下位から上位の順に実行し、失敗したら最初のエラー、状態、ソースにアクセス可能かを確認してください。 ## クリーンアップ ```sql DROP ROLLUP ch6_control_ru; DROP TABLE ch6_control; ``` 詳細なコマンド仕様は[EXECリファレンス](../../reference/sql/syntax/execute-procedure-syntax/)と [ROLLUPのトラブルシューティング](../../troubleshooting/rollup/)を参照してください。 --- title: "6.10 ROLLUP_REBUILD" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/rollup-rebuild/ language: ja kind: page --- # 6.10 ROLLUP_REBUILD ROLLUP_REBUILDは、元データの過去の値を補正した後に集計を再計算するプロシージャで、Standard Edition専用です。 FORCEとは異なり、影響を受けるバケットを削除・再作成します。 すべてのROLLUP定義を任意に再構築する汎用コマンドではありません。 ## サポート対象の事前確認 | 対象 | 現在の対応 | |---|---| | WITH ROLLUPで作成した完全なSEC→MIN→HOUR階層 | 基本数値・拡張・ドキュメント全体JSONの処理 | | 元データに接続されたサポート対象のCustomツリー | 1 SEC・1 MIN・1 HOURの間隔と、再構築境界に合うSELECTを確認 | | 任意の名前・間隔で手動作成した通常のROLLUP | 自動階層と同じ対応を前提にしない | | SECがないMIN/HOURだけの自動階層 | 完全な基本階層とは見なさない | | 10 MINなど別の間隔のCustom | 現在の時間境界生成処理では未サポート | | Cluster Edition | 未サポート | CustomのSELECTが作るバケット、INTERVAL、基準タイムゾーンは、再構築境界と一致する必要があります。 未サポートのジョブがツリーに混在していないかを先に調べてください。 Customで作成できる式・間隔を、この関数ですべて再構築できるとは考えないでください。 ## 時間引数とバケット境界 時刻文字列、または定数文字列を使用するTO_DATEを指定します。 一般的なDATETIME式全体を評価する処理ではないため、NOWの算術式やバインドパラメーターで例を作成しないでください。 開始時刻と終了時刻が属するバケットを両方含め、バケット全体に範囲を広げます。 1分段階で00:00:30~00:01:00を指定すると、00:00と00:01の2バケット、 つまり[00:00:00, 00:02:00)の範囲が再計算されます。 開始=終了でもその時刻のバケットを再計算し、開始が終了より大きい場合はエラーになります。 上位の時間段階では、さらに広いバケットに拡張されます。 ## 基本階層とCustomの訂正実習 ### 1. 準備と初回集計 ```sql CREATE TAG TABLE ch6_rebuild ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ) WITH ROLLUP (SEC); CREATE TAG TABLE ch6_rebuild_dst ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, sum_value DOUBLE, cnt LONG ); CREATE ROLLUP ch6_rebuild_custom INTO (ch6_rebuild_dst) AS ( SELECT name, DATE_TRUNC('minute', time) AS time, SUM(value), COUNT(value) FROM ch6_rebuild GROUP BY name, time ) INTERVAL 1 MIN; INSERT INTO ch6_rebuild VALUES ('S1', TO_DATE('2026-01-01 00:00:00'), 1); INSERT INTO ch6_rebuild VALUES ('S1', TO_DATE('2026-01-01 00:00:30'), 200); INSERT INTO ch6_rebuild VALUES ('S1', TO_DATE('2026-01-01 00:01:00'), 300); INSERT INTO ch6_rebuild VALUES ('S1', TO_DATE('2026-01-01 00:01:30'), 4); EXEC TABLE_FLUSH(ch6_rebuild); SELECT DISTINCT ROLLUP_NAME, INTERVAL_TIME FROM V$ROLLUP WHERE ROOT_TABLE = 'CH6_REBUILD' ORDER BY INTERVAL_TIME, ROLLUP_NAME; ALTER ROLLUP _CH6_REBUILD_ROLLUP_SEC FORCE; ALTER ROLLUP _CH6_REBUILD_ROLLUP_MIN FORCE; ALTER ROLLUP _CH6_REBUILD_ROLLUP_HOUR FORCE; ALTER ROLLUP ch6_rebuild_custom FORCE; SELECT rollup('min', 1, time) AS bucket, AVG(value) FROM ch6_rebuild WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; ``` 制御コマンドの自動生成名が、上のV$ROLLUPの結果と一致することを確認してください。 他のオブジェクト名を推測して実行しないでください。最初の分平均は100.5と152です。 ### 2. 元データの補正と再構築 ```sql UPDATE ch6_rebuild SET value = 20 WHERE name = 'S1' AND time = TO_DATE('2026-01-01 00:00:30'); UPDATE ch6_rebuild SET value = 30 WHERE name = 'S1' AND time = TO_DATE('2026-01-01 00:01:00'); EXEC ROLLUP_REBUILD(ch6_rebuild, 'S1', TO_DATE('2026-01-01 00:00:30'), TO_DATE('2026-01-01 00:01:00')); ``` ### 3. 元データ・通常・Customの結果比較 ```sql SELECT DATE_TRUNC('minute', time) AS bucket, SUM(value), COUNT(value), AVG(value) FROM ch6_rebuild WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; SELECT rollup('min', 1, time) AS bucket, SUM(value), COUNT(value), AVG(value) FROM ch6_rebuild WHERE name = 'S1' GROUP BY bucket ORDER BY bucket; SELECT time, SUM(sum_value), SUM(cnt), SUM(sum_value) / SUM(cnt) FROM ch6_rebuild_dst WHERE name = 'S1' GROUP BY time ORDER BY time; SHOW ROLLUPGAP; ``` 3つの結果は、00:00が合計21・件数2・平均10.5、00:01が合計34・件数2・平均17です。 終了時刻より後の00:01:30の値4も、同じバケットを再計算するときに含まれる必要があります。 ## 運用への影響と障害復旧 関連ジョブは処理位置に追いついてから、停止・再計算・再開始されます。 元データを安定して検索するための内部処理も実行するため、「再構築中も通常処理がそのまま継続する」とは説明しません。 ユーザークエリと収集に許容できる遅延・停止時間を、先に検証環境で測定してください。 複数の段階が1つのアトミックなトランザクションとして取り消されるとは考えないでください。 失敗時の状態復旧はベストエフォートで実行されるため、実データとV$ROLLUPを確認します。 元の停止状態をそのまま復元する保証もありません。 再実行前に、サポート対象、元データの残存、再集計範囲を確認してください。 存在しないタグは、有効な再構築対象が準備された状況ではno-opになる場合があります。 成功応答だけで意図したタグを処理したと判断せず、実際の結果を比較してください。 元データが削除されている場合、元の統計は復元できません。 ## クリーンアップ ```sql DROP ROLLUP ch6_rebuild_custom; DROP TABLE ch6_rebuild_dst; DROP TABLE ch6_rebuild CASCADE; ``` Customの出力先は別途削除します。通常の定義自体を変更する必要がある場合や、このプロシージャの範囲外の場合は、 サポートされる新しい定義とデータ移行の手順を用意してください。 内部保存テーブルを任意に削除するSQLを、代替手順として提示しないでください。 正確な引数は[REBUILDリファレンス](../../reference/sql/syntax/rollup-rebuild-syntax/)を参照してください。 --- title: "6.11 ROLLUPのパフォーマンスチューニング" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/performance-tuning-rollup/ language: ja kind: page --- # 6.11 ROLLUPのパフォーマンスチューニング ## 同じ結果を確認してからコストを比較 ROLLUPの効果は、読み取る生データの行数を減らすことにあります。 まずタグ、時間区間、NULL処理、集計基準が同じ結果になることを確認し、実行時間・CPU・I/O・メモリを比較します。 小さな例の実行時間は、本番性能を保証しません。 ## 比較実習 ```sql CREATE TAG TABLE ch6_perf ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE, quality INTEGER ); CREATE ROLLUP ch6_perf_ru ON ch6_perf(value) INTERVAL 1 MIN; INSERT INTO ch6_perf VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10.0, 1); INSERT INTO ch6_perf VALUES ('TEMP_01', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), 20.0, 1); INSERT INTO ch6_perf VALUES ('TEMP_01', TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS'), 30.0, 1); INSERT INTO ch6_perf VALUES ('TEMP_02', TO_DATE('2026-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 100.0, 1); EXEC TABLE_FLUSH(ch6_perf); ALTER ROLLUP ch6_perf_ru FORCE; SELECT DATE_TRUNC('minute', time) AS bucket, SUM(value), COUNT(value), AVG(value), MIN(value), MAX(value) FROM ch6_perf WHERE name = 'TEMP_01' AND time >= TO_DATE('2026-01-01 00:00:00') AND time < TO_DATE('2026-01-01 00:02:00') GROUP BY bucket ORDER BY bucket; SELECT rollup('min', 1, time) AS bucket, SUM(value), COUNT(value), AVG(value), MIN(value), MAX(value) FROM ch6_perf WHERE name = 'TEMP_01' AND time >= TO_DATE('2026-01-01 00:00:00') AND time < TO_DATE('2026-01-01 00:02:00') GROUP BY bucket ORDER BY bucket; EXPLAIN SELECT rollup('min', 1, time) AS bucket, AVG(value) FROM ch6_perf WHERE name = 'TEMP_01' GROUP BY bucket; ``` 両方の結果は、00:00が合計30・件数2・平均15・最小値10・最大値20、 00:01が合計30・件数1・平均30・最小値30・最大値30です。 元データを読むDATE_TRUNCクエリの実行計画も、同じ方法で確認します。 ## 運用負荷の測定 | 項目 | 併せて記録する条件 | |---|---| | 入力スループット | タグ数・入力レート・行幅・同時入力クライアント数 | | クエリ遅延 | タグ範囲・バケット・同時クエリ数・コールドまたはウォームキャッシュ | | 集計遅延 | 階層別のgap・ジョブ状態・処理時間 | | 保存容量 | 元データ・集計・インデックス・圧縮・レプリカ | | 変更の影響 | WAKEUP周期と階層の変更前後の入力・検索コスト | WAKEUPを短くすると、同じバケットに部分集計がより頻繁に作成される場合があります。 集計バケットを小さくすると、保存量と再集計量が増えます。両方の間隔を同じチューニング項目として扱わないでください。 単独実行だけでなく、入力と検索が同時に進む状況も測定します。 ## 階層サイズの意味 1つのタグが30日間のすべての区間にデータを持つと仮定した場合の、論理バケット数です。 | 検索区間 | バケット数 | |---|---:| | 1秒 | 2,592,000 | | 1分 | 43,200 | | 1時間 | 720 | | 1日 | 30 | これは物理的な保存行数ではありません。 複数の部分集計、空の区間、NULL、条件フィルターを含む実際の保存量は、サンプルのロードで測定します。 最も粗い候補が常に正しい結果を作るわけでもないため、必要な解像度・origin・候補選択の制約を併せて確認してください。 日単位の結果には、適用可能なHOUR/MIN/SEC集計を再集計します。 24 HOUR ROLLUPを`rollup('day', 1, ...)`の代替保存階層として推奨しません。 [クエリ候補の規則](../query-syntax-rollup/)と実際のEXPLAINを基準にしてください。 ## 遅延と不一致の区別 gap=0は処理位置に追いついたことを表し、元データの補正が反映済みであることを意味しません。 性能比較の前に、集計の進行状況と過去の訂正状態を区別し、定義とフィルターが一致するか確認してください。 適用可能なROLLUPがない`rollup()`クエリを、元データの性能測定に使用しないでください。 ## クリーンアップ ```sql DROP ROLLUP ch6_perf_ru; DROP TABLE ch6_perf; ``` [制御と状態](../ingestion-control-rollup/)、[階層設計](../target-tag-table-design/)、 [トラブルシューティング](../../troubleshooting/rollup/)を参照して次の調整を選択してください。 --- title: "6.12 ROLLUPの活用シナリオ" url: https://docs.machbase.com/ja/dbms/tag-rollup-usage/patterns-scenarios/ language: ja kind: page --- # 6.12 ROLLUPの活用シナリオ ## センサー別の元データと区間統計 2つのセンサーが同時刻に測定しても、単位が異なる場合は平均を混在させません。 次は、現在の単位をメタデータで管理し、タグ別の集計を検索する独立した実習です。 ### 1. 作成と入力 ```sql CREATE TAG TABLE ch6_scenario ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE ) METADATA (unit VARCHAR(16)); INSERT INTO ch6_scenario METADATA VALUES ('TEMP_01', 'celsius'); INSERT INTO ch6_scenario METADATA VALUES ('PRESS_01', 'bar'); INSERT INTO ch6_scenario VALUES ('TEMP_01', TO_DATE('2026-01-01 10:00:00'), 20); INSERT INTO ch6_scenario VALUES ('TEMP_01', TO_DATE('2026-01-01 10:00:30'), 22); INSERT INTO ch6_scenario VALUES ('PRESS_01', TO_DATE('2026-01-01 10:00:00'), 1.02); CREATE ROLLUP ch6_scenario_ru ON ch6_scenario(value) INTERVAL 1 MIN; EXEC TABLE_FLUSH(ch6_scenario); ALTER ROLLUP ch6_scenario_ru FORCE; ``` 元データの入力後にROLLUPを作成しても、残っているデータを初期集計します。 作成の完了だけで、初期集計も完了したと判断しないでください。 ### 2. 結果の確認 ```sql SELECT name, unit FROM ch6_scenario METADATA ORDER BY name; SELECT name, DATE_TRUNC('minute', time) AS bucket, COUNT(value), AVG(value) FROM ch6_scenario GROUP BY name, bucket ORDER BY name, bucket; SELECT name, rollup('min', 1, time) AS bucket, COUNT(value), AVG(value) FROM ch6_scenario GROUP BY name, bucket ORDER BY name, bucket; SHOW ROLLUPGAP; ``` TEMP_01は2件・平均21°C、PRESS_01は1件・平均1.02barです。 メタデータ検索で得られるのは現在の単位であり、過去の単位変更履歴は自動的に保持されません。 ### 3. 個別の観測値の確認 固定時刻のデータを入力したため、同じ固定範囲を検索します。 このデータに現在時刻を基準にした「直近5分」の条件を適用すると、実行日に応じて結果が空になります。 ```sql SELECT name, time, value FROM ch6_scenario WHERE name = 'TEMP_01' AND time >= TO_DATE('2026-01-01 10:00:00') AND time < TO_DATE('2026-01-01 10:01:00') ORDER BY time; ``` 元の2つの値は20と22です。統計上の平均21から、個々の観測値や発生順序を復元することはできません。 ### 4. クリーンアップ ```sql DROP ROLLUP ch6_scenario_ru; DROP TABLE ch6_scenario; ``` ## 業務別の適用 | 要求 | 確認する設計 | |---|---| | 正常品質の統計 | 条件フィルターと候補ヒントを固定して元データと比較 | | OHLC | 拡張ROLLUPのFIRST/LAST、またはCustomの補助時刻による再集計 | | 複数センサーの比較 | タグ別の単位と同じバケット・検索範囲を使用 | | 累積メーターの消費量 | 境界の差、初期化・交換・欠損の規則。サンプル平均と区別 | | 稼働率 | サンプル比率と時間比率の区別、欠測区間のポリシー | | 最新の元データと長期集計の結合 | 集計完了を確認した基準点で区間が重複しないよう分割 | 元データとROLLUPの結果をUNION ALLで結合する場合は、境界の重複・欠落とサンプル数の違いを確認してください。 「直近2分は常に未集計」などの固定遅延を保証として使用しないでください。 部分結果を再結合して平均を求める場合は、合計と有効件数を渡します。 機能別の完結した実習は、[条件付き](../conditional-rollup/)、[拡張](../extension-rollup/)、 [JSON](../json-summarized-rollup/)、[Custom](../custom-rollup/)にあります。 問題が発生したら、[診断手順](../../troubleshooting/rollup/)に従って状態と意味を先に確認してください。 --- title: "7. LOGテーブルの活用" url: https://docs.machbase.com/ja/dbms/log-table-usage/ language: ja kind: section --- # 7. LOGテーブルの活用 ログを保存することと、必要なログを探し出すことは別の作業です。 障害分析では、「この時刻は発生時刻か収集時刻か」「メッセージ内の単語がなぜ検索されないか」など、 入力時には考えていなかった問題に直面します。 この章では、LOGテーブルの選択・設計から入力、検索、保持管理までを一連の流れで説明します。 コマンドの実行方法に加え、結果の確認基準も学びます。 LOGは元のイベントを継続的に追加するモデルであり、保存済みの行を繰り返し更新する業務テーブルとは使い方が異なります。 ## この章の構成 初めての場合は、概要とスキーマを読んでから、作成・入力・検索の順に進めてください。 時間条件を確認するなら7.10、メッセージ検索が目的なら7.11から読むこともできます。 | 節 | 学習内容 | |---|---| | [7.1 概要と選択基準](./overview-use-criteria/) | LOGと他のテーブルの用途の区別 | | [7.2 テーブル構造とスキーマ](./table-structure-schema/) | 発生時刻・検索フィールド・原文の分離 | | [7.3 作成、変更、削除](./create-alter-drop/) | 既存データを確認しながらスキーマを変更 | | [7.4 データ入力](./data-input-mutation/) | INSERT・Append・ファイルロードの選択 | | [7.5 クエリと分析](./query-analysis/) | 時間範囲検索とマスターデータの結合 | | [7.6 インデックスとパフォーマンス](./index-performance/) | インデックスの選択と実行計画の確認 | | [7.7 運用とデータライフサイクル](./operations-lifecycle/) | 削除境界の確認と保持ポリシーの適用 | | [7.8 制約、エラー、トラブルシューティング](./constraints-errors-troubleshooting/) | 症状から原因と対処を特定 | | [7.9 活用パターンとシナリオ](./patterns-scenarios/) | アプリケーションログの入力・検索・集計 | | [7.10 _arrival_timeの時間モデル](./arrival-time-model/) | 自動時刻・明示時刻・時刻逆転入力の区別 | | [7.11 テキスト検索とKEYWORDインデックス](./text-search-keyword-index/) | 検索方法による結果の違い | | [7.12 ネットワーク型のクエリ](./regex-network-query/) | IPV4・IPV6のアドレスと範囲の検索 | ## 実習環境 この章の例はDBMS 8.7の文書に基づき、特に断りのないSQL実習はStandard Editionの検証環境を対象とします。 テーブルとインデックスを作成できるアカウントを使用してください。 Cluster環境では、[Editionごとの違い](/ja/dbms/reference/support-scope-constraints/edition/)と該当する運用手順も確認する必要があります。 実習用オブジェクトは`ch7_`で始まります。各節で必要なテーブルを作成するため、他の節を実行せずに進められます。 同じ節を再実行する場合は、最後のクリーンアップSQLまで実行したことを確認してください。 意図的に失敗するSQLは通常の実習と分離しています。 注意: `DELETE`、`TRUNCATE`、`DROP`はデータを削除するコマンドです。 例の名前を本番テーブル名に置き換えて実行しないでください。 実習結果が異なる場合は、実行したSQLと実際の結果を比較してください。 どの段階から差が生じたかを確認すると、原因を絞り込みやすくなります。 --- title: "7.1 概要と選択基準" url: https://docs.machbase.com/ja/dbms/log-table-usage/overview-use-criteria/ language: ja kind: page --- # 7.1 概要と選択基準 時刻を持つデータをすべて同じテーブルに保存する必要はありません。 定期的に測定した温度と「デバイスが再接続した」というイベントでは、分析方法が異なります。 LOGを選ぶときは、時間カラムの有無より、1行が何を表すかを先に考えてください。 ## LOGテーブルの特性 アプリケーションエラー、セキュリティ機器の遮断記録、処理の開始・終了履歴など、イベントを1件ずつ追加するデータにLOGが適しています。 ユーザーカラムに加えて`_arrival_time`が自動的に作成され、時間範囲条件とメッセージ検索を併用できます。 次の例で、イベント発生時刻と入力時刻の違いを確認します。 ```sql CREATE LOG TABLE ch7_overview ( event_time DATETIME, device VARCHAR(32), message VARCHAR(128) ); INSERT INTO ch7_overview VALUES ( TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'DEV-01', 'connection restored' ); SELECT _arrival_time, event_time, device, message FROM ch7_overview; DROP TABLE ch7_overview; ``` 1行が返されます。`event_time`は例に指定した固定時刻、`_arrival_time`は今回の入力で自動的に決まった時刻です。 したがって、実行日が変わっても`event_time`は変わりません。 明示的な入力と補正規則については[時間モデル](../arrival-time-model/)で説明します。 ## 選択基準 「過去1時間のエラー」「このIPアドレスからのリクエスト」「timeoutを含むメッセージ」を頻繁に検索し、 保存済みの行を更新する必要がない場合は、まずLOGを検討してください。 継続入力にはAppend API、初期データやファイル群にはロードツールを使用できます。 入力後に更新できないことだけで、監査データの改ざん防止が保証されるわけではありません。 削除権限、アクセス制御、保持ポリシー、バックアップは別途設計する必要があります。 再送には注意が必要です。同じイベントを再送すると、別の行として保存される場合があります。 LOGにはPRIMARY KEY・UNIQUE制約がないため、自動的な重複排除は期待できません。 元のイベントIDを保持し、収集段階で再試行と重複処理のポリシーを定めてください。 ## 他のテーブルとの比較 | 主な用途 | 最初に検討するテーブル | 判断基準 | |---|---|---| | センサー名ごとの測定値と時系列集計 | TAG | 名前・時間軸による検索とROLLUPが中心 | | 機器名・設置場所などの現在のマスターデータ | LOOKUP | 小規模な参照データを検索・更新 | | 注文状態の変更・行削除・トランザクション処理 | TRANSACTION | 行を更新し、取引単位で処理 | | 再起動後に失われてもよいメモリ上の状態 | VOLATILE | 永続保存する元のログから分離 | LOGは一般的な`UPDATE`と任意条件の`DELETE WHERE`をサポートしていません。 訂正イベントを追加する設計は可能ですが、元のIDと訂正理由を保存し、 検索時にどの訂正を反映するかをアプリケーションで決める必要があります。 更新が日常的に発生する業務では、最初から別のテーブルを使うほうが明確です。 ## 設計基準 分析に必要なのが発生時刻か収集時刻かを、まず区別します。 続いて、デバイス・重要度・IPなど、頻繁に使用する条件を決めてください。 これらの値は毎回原文から切り出すより、別カラムに格納するとクエリを理解・管理しやすくなります。 保持期間もこの段階で決めてください。入力方法だけを用意して削除を後回しにすると、ディスク使用量が増え続けます。 次の[スキーマ設計](../table-structure-schema/)では、これらの観点を実際のカラムに反映します。 選択に迷う場合は、代表的なイベント数件と頻繁に使用するクエリを並べて比較してください。 --- title: "7.2 テーブル構造とスキーマ" url: https://docs.machbase.com/ja/dbms/log-table-usage/table-structure-schema/ language: ja kind: page --- # 7.2 テーブル構造とスキーマ メッセージ全体を1つのカラムに格納すれば、収集をすぐに開始できます。 しかし、後から機器別のエラー件数を求めるために毎回原文を解析すると、クエリが複雑になります。 この節では、原文を保持しつつ、繰り返し検索・集計する値を別カラムに取り出す方法を説明します。 ## カラム構成 次は、セキュリティイベントを1件保存して確認する独立した実習です。 ```sql CREATE LOG TABLE ch7_schema ( event_time DATETIME, event_id VARCHAR(64), device VARCHAR(32), severity SHORT, src_ip IPV4, dst_port INTEGER, message TEXT ); INSERT INTO ch7_schema VALUES ( TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'evt-0001', 'FW-01', 3, '192.0.2.10', 65535, 'connection blocked by policy' ); SELECT event_id, device, severity, src_ip, dst_port, message FROM ch7_schema; ``` `evt-0001`の1行とポート`65535`が返されます。 ここでの`event_id`は追跡用の値であり、重複入力を防ぐキー制約ではありません。 `event_time`には、入力元が記録した発生時刻を保存します。 自動カラムの`_arrival_time`をDDLで再宣言しないでください。 ネットワーク遅延や一括移行があると、2つの時刻が異なるのは自然なことです。 ## データ型の選択 | 値 | 選択する型 | 確認事項 | |---|---|---| | デバイス名・短いコード・イベントID | `VARCHAR(n)` | LOGの宣言範囲は1~32,767バイトであり、文字数ではない | | 長い原文メッセージ | `TEXT` | 最大64MiB。原文自体のソート・グループ化は未サポート | | エラーの重要度・小さなコード | `SHORT`または`INTEGER` | 各コードの意味を収集側と検索側で統一 | | ポート | `INTEGER` | `USHORT`の65535はNULLの予約値のため、ポート全範囲には不適切 | | 累積バイト数 | `LONG` | 想定最大値とNULLの予約値を確認 | | アドレス | `IPV4`または`IPV6` | アドレス形式と元の文字列の保存要否を区別 | LOGでは、VARCHARとTEXTの両方でKEYWORDインデックスによる単語検索が可能です。 全文検索を行うという理由だけで、短いコードまでTEXTにする必要はありません。 文字列長には注意が必要です。`VARCHAR(100)`は韓国語100文字を意味しません。 UTF-8サンプルのバイト数を確認し、長さを超える値を実際の入力方法で送ってください。 長さ超過が切り詰めとエラーのどちらになるかは、使用するSDKやロードツールも含めて確認する必要があります。 ## ソート・集計用カラム 上のスキーマでは、`device`・`severity`を検索条件と集計基準に使用し、 `message`を原文の読み取りや単語検索に使用します。 `ORDER BY message`や`GROUP BY message`のようにTEXT自体を対象にするとエラーになります。 メッセージ全体をソートするより、デバイス、エラーコード、発生時刻から実際に必要な基準を決めてください。 KEYWORDインデックスは、形態素解析器や検索スコアに基づく検索エンジンと同じものではありません。 単語検索と原文の部分文字列検索の違いは、[テキスト検索](../text-search-keyword-index/)で確認できます。 ## スキーマ変更と入力マッピング LOGはカラムの追加・削除・名前変更と、限定的な属性変更をサポートしています。 ただし、保存した行の値をUPDATEで変更できるわけではありません。 特にカラム順に送信するAppenderとCSVマッピングはDDL変更の影響を受けるため、変更時刻と入力プログラムの展開を併せて計画してください。 実習テーブルを削除してから、[カラム変更の実習](../create-alter-drop/)に進みます。 ```sql DROP TABLE ch7_schema; ``` どの値をカラムに取り出すべきか迷う場合は、実際に答える必要がある問いを書き出してください。 その問いをSQLで表現すると、必要なカラムも明確になります。 --- title: "7.3 作成、変更、削除" url: https://docs.machbase.com/ja/dbms/log-table-usage/create-alter-drop/ language: ja kind: page --- # 7.3 作成、変更、削除 カラム追加のSQLは短くても、運用では既存行に表示される値と、既存の入力プログラムが引き続き動作するかを確認する必要があります。 この節では、データがある状態でスキーマを変更し、その結果を確認します。 ## LOGテーブルの作成 テーブル型を省略した`CREATE TABLE`はTRANSACTIONテーブルを作成します。 この実習では`CREATE LOG TABLE`を使用してください。 ```sql CREATE LOG TABLE ch7_ddl ( event_id INTEGER, category VARCHAR(32), severity SHORT, message VARCHAR(128) ); INSERT INTO ch7_ddl VALUES (1, 'network', 3, 'connection timeout'); ``` 自動カラム`_arrival_time`はDDLに再宣言しません。 実際の発生時刻が必要なら、別のDATETIMEカラムを用意してください。 LOGではPRIMARY KEY・UNIQUE制約をサポートしていません。 ## カラム追加とデフォルト値 ```sql ALTER TABLE ch7_ddl ADD COLUMN (host_name VARCHAR(64)); ALTER TABLE ch7_ddl ADD COLUMN (source_kind VARCHAR(16) DEFAULT 'agent'); ALTER TABLE ch7_ddl ADD COLUMN (channels INT32[3] DEFAULT [1, NULL, 3]); SELECT event_id, host_name, source_kind, channels FROM ch7_ddl ORDER BY event_id; ``` 既存の行1では、`host_name`がNULL、`source_kind`が`agent`、 `channels`が`[1, NULL, 3]`として返されます。 DEFAULTを持つカラムと持たないカラムの違いを確認してください。 ARRAYのDEFAULTは、要素数が宣言した長さと一致する必要があります。 続いて、カラム名を変更し、文字列長を拡張します。 ```sql ALTER TABLE ch7_ddl RENAME COLUMN category TO event_category; ALTER TABLE ch7_ddl MODIFY COLUMN (message VARCHAR(4096)); ALTER TABLE ch7_ddl MODIFY COLUMN severity SET MINMAX_CACHE_SIZE = 1048576; SELECT event_id, event_category, severity, message FROM ch7_ddl; ``` 既存行の値は保持されます。名前の変更後は、検索SQLでも`event_category`を使用する必要があります。 MINMAXの例は数値カラムに1MiBを指定したもので、すべてのテーブルに推奨する値ではありません。 型変更には注意が必要です。VARCHARの長さの拡張は、TEXTをVARCHARに変換する操作ではありません。 `MINMAX_CACHE_SIZE`もVARCHAR・TEXTなどの可変長カラムには設定できません。 ## NOT NULLと既存データ 現在の`event_category`には値があるため、次の変更が可能です。 ```sql ALTER TABLE ch7_ddl MODIFY COLUMN event_category NOT NULL; ALTER TABLE ch7_ddl MODIFY COLUMN event_category NULL; ``` オプションなしの`NOT NULL`は既存行を検査します。 NULLを含む`host_name`には適用できません。次のSQLは、失敗を確認する場合にのみ個別に実行してください。 ```sql -- 意図的に失敗: 既存行のhost_nameはNULLです。 ALTER TABLE ch7_ddl MODIFY COLUMN host_name NOT NULL; ``` `NOT NULL NOCHECK`は既存のNULL検査を省略します。 既存のNULLを埋めたり、過去のデータも条件を満たすと保証したりするオプションではありません。 この実習の通常の手順では使用しません。 ## インデックスとカラムの削除 ```sql CREATE INDEX ch7_ddl_host_idx ON ch7_ddl(host_name) INDEX_TYPE LSM; DROP INDEX ch7_ddl_host_idx; ALTER TABLE ch7_ddl DROP COLUMN (host_name); ALTER TABLE ch7_ddl DROP COLUMN (source_kind); ALTER TABLE ch7_ddl DROP COLUMN (channels); SELECT event_id, event_category, severity, message FROM ch7_ddl; ``` インデックスが参照するカラムを削除するには、先にインデックスを削除してください。 内部カラム`_ARRIVAL_TIME`・`_RID`は削除・名前変更・属性変更の対象にできず、 ユーザーカラムは少なくとも1つ残す必要があります。 VARCHARの長さは既存より大きくすることだけが可能で、最大32,767バイトの範囲内にする必要があります。 ## データの削除とテーブルの削除 注意: 次のコマンドは実習データを削除します。 LOGデータはTRANSACTIONテーブルの`ROLLBACK`では元に戻せません。 ```sql TRUNCATE TABLE ch7_ddl; SELECT COUNT(*) AS remaining_rows FROM ch7_ddl; DROP TABLE ch7_ddl; ``` TRUNCATE後の件数は0になり、定義は残ります。最後のDROPは定義も削除します。 古いデータの一部だけを削除するには、[保持期間に基づく削除](../operations-lifecycle/)を使用してください。 ## DDL運用上の注意事項 変更前に入力処理とDDLの実行時刻を調整し、変更後にSQL・Appender・ファイルマッピングの カラム名・順序・型を確認します。リソース使用中エラーが発生したら、繰り返し実行する前に、 対象テーブルを使用している処理を確認してください。 どの変更で問題が起きたか不明な場合は、変更前のDDLと失敗したSQLを用意してください。 この2つがあると、原因をより早く絞り込めます。 --- title: "7.4 データ入力" url: https://docs.machbase.com/ja/dbms/log-table-usage/data-input-mutation/ language: ja kind: page --- # 7.4 データ入力 1、2行の入力に成功しても、収集の準備が完了したとは限りません。 継続的な収集では、送信バッファ、一部の行の失敗、切断後の再送も考慮する必要があります。 まずSQLでカラムと時刻を確認し、実際のスループットに適した入力方法を選択してください。 ## SQL INSERT ```sql CREATE LOG TABLE ch7_input ( event_time DATETIME, event_id VARCHAR(32), device VARCHAR(32), message VARCHAR(128) ); INSERT INTO ch7_input(event_time, event_id, device, message) VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'evt-001', 'DEV-01', 'connection timeout'); SELECT _arrival_time, event_time, event_id, device, message FROM ch7_input; ``` 1行が返され、`event_time`は固定の発生時刻です。 `_arrival_time`を省略したため、入力処理でサーバー時刻が使用されます。 デフォルト設定では時刻逆転時に補正が発生し得るため、常に実際の受信時刻と正確に一致するとは限りません。 詳細な規則は[時間モデル](../arrival-time-model/)を参照してください。 同じイベントを再度入力した場合の動作も確認します。 ```sql INSERT INTO ch7_input(event_time, event_id, device, message) VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'evt-001', 'DEV-01', 'connection timeout'); SELECT event_id, COUNT(*) AS received_rows FROM ch7_input GROUP BY event_id; DROP TABLE ch7_input; ``` `evt-001`の件数は2です。名前が同じでもLOGは重複を除去しません。 収集アプリケーションの「送信完了」と、元のイベントを「一度だけ保存すること」は別の問題です。 ## 入力方法の選択 | 状況 | 最初に検討する方法 | 併せて確認する項目 | |---|---|---| | 少量入力・機能確認 | SQL INSERT | カラムリスト、型、日付書式 | | アプリケーションからの継続的な大量入力 | SDK Append | バッファ送信、行単位の失敗、再接続ポリシー | | クライアントが読み込むCSV | csvimport・machloader | カラムマッピング、失敗行ファイル | | サーバーから読み込めるロード用ファイル | LOAD DATA INFILE | サーバー上のパスとファイルアクセス権限 | SQL INSERTには文ごとの処理コストがあります。継続的な大量入力には、複数行をまとめて送信するAppend APIを検討してください。 言語別の実行コードは[開発とアプリケーション連携](/ja/dbms/development-tools-integration/)から選択できます。 ## Appendの送信とエラー処理 Appenderに行を渡した時点では、データがクライアントバッファに残っている場合があります。 使用するSDKのflush・closeの動作を確認し、正常終了時だけでなく例外発生時にも、残りのバッファと接続を処理してください。 呼び出しが成功しても、すべての行が保存されたとは限りません。 SDKによって、戻り値、エラーコールバック、終了時の成功・失敗件数など、結果の確認方法が異なります。 長さ超過、NULL、日付変換エラーを意図的に含めた小さなバッチで、先に確認することを推奨します。 応答を受け取る前に接続が切れる場合は特に注意が必要です。 保存済みのバッチを再送する可能性があるため、元のイベントIDと処理位置を記録してください。 LOGのINSERT・Appendは、TRANSACTIONテーブルのトランザクションのROLLBACK対象でもありません。 ## ファイルロードとマッピング 韓国語・空文字列・NULL・長いメッセージ・異なるタイムゾーンを含むサンプルを用意してください。 元のフィールド数と対象カラムの順序が一致することを確認してから、ファイル全体を処理します。 同じエラーを再分析できるよう、失敗行ファイルとログも保存してください。 コマンド全体は[データ入力・ロード・エクスポート](/ja/dbms/development-tools-integration/data-input-load-export/)を参照してください。 過去データの移行で`_arrival_time`を保持するには、ソート順と移行先の既存データも確認する必要があります。 通常の収集で過去の発生時刻を扱う場合は、別の`event_time`に保存するほうが安全です。 問題が起きたら、バッチ全体より先に、失敗した元の1行を確認してください。 フィールド値、対象の型、使用した入力APIを合わせて確認すると原因を特定しやすくなります。 --- title: "7.5 クエリと分析" url: https://docs.machbase.com/ja/dbms/log-table-usage/query-analysis/ language: ja kind: page --- # 7.5 クエリと分析 時間範囲を少し変えるだけでも検索件数は変わります。 特に日単位の集計では、終了時刻を両方の区間に含めると境界上の行が重複します。 この節では、固定時刻のデータで範囲と結果の順序を確認し、マスターデータを結合します。 ## 実習データの準備 ```sql CREATE LOG TABLE ch7_query ( event_id INTEGER, device VARCHAR(32), value DOUBLE ); INSERT INTO ch7_query(_arrival_time, event_id, device, value) VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1, 'DEV-01', 10); INSERT INTO ch7_query(_arrival_time, event_id, device, value) VALUES (TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 2, 'DEV-01', 20); INSERT INTO ch7_query(_arrival_time, event_id, device, value) VALUES (TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3, 'DEV-02', 30); INSERT INTO ch7_query(_arrival_time, event_id, device, value) VALUES (TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 4, 'DEV-02', 40); SELECT _arrival_time, event_id, device, value FROM ch7_query ORDER BY _arrival_time, event_id; ``` 結果はイベント1・2・3・4の順です。イベント2と3のように同時刻の行もあるため、 順序を固定するには、時刻に加えてイベント番号もソート条件に指定します。 この番号は例の中で明示的に管理する値で、LOGの自動的な一意キーではありません。 ## 連続区間と時間境界 ```sql SELECT event_id, value FROM ch7_query WHERE _arrival_time >= TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') AND _arrival_time < TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; ``` イベント1・2・3が選択されます。次の区間を12:00から始めると、イベント4はその区間でのみ集計されます。 `BETWEEN`は両端を含むため、このような連続区間とは意味が異なります。 ユーザー定義の`event_time`を基準に分析する場合も、同じWHEREパターンを使用できます。 ## DURATIONによる検索 ```sql SELECT event_id FROM ch7_query DURATION 1 HOUR BEFORE TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; SELECT event_id FROM ch7_query DURATION 1 HOUR AFTER TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; SELECT event_id FROM ch7_query DURATION FROM TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') TO TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; ``` | クエリ | 時間範囲 | 選択されるevent_id | |---|---|---| | 12:00以前の1時間 | 11:00~12:00、両端を含む | 2, 3, 4 | | 10:00以後の1時間 | 10:00~11:00、両端を含む | 1, 2, 3 | | 10:00から12:00まで | 両端を含む | 1, 2, 3, 4 | `DURATION 1 HOUR`のように基準時刻を省略すると、現在時刻を基準にします。 そのため、過去の固定時刻を使う実習にそのまま適用すると、結果が得られない場合があります。 構文上の位置はWHEREの後、GROUP BY・ORDER BYの前です。 DURATIONがすべての時間カラムに適用される条件だと誤解しないでください。 DURATIONはLOG専用で、`_arrival_time`を使用します。 TAGの時間カラムやユーザー定義DATETIMEの条件はWHEREで指定してください。 詳細な構文は[相対時間・DURATIONリファレンス](/ja/dbms/reference/sql/relative-time/#log-duration)を参照してください。 ## スキャン方向とソート DURATIONのBEFOREは新しい側から、AFTERは古い側から読み取る方向を指定します。 FROM … TOは、2つの時刻の順序によって方向が変わります。 次の例では、逆順の範囲と同時刻の境界を確認します。 ```sql SELECT event_id FROM ch7_query DURATION FROM TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') TO TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id DESC; SELECT event_id FROM ch7_query DURATION FROM TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS') TO TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; ``` 最初の結果はイベント4・3・2・1、同じ時刻を指定した2番目の結果はイベント2・3です。 ここではスキャン方向とは別にORDER BYを明示し、出力順序を固定しています。 集計や結合を含む最終結果の順序が必要な場合は、ORDER BYを明示してください。 特にLIMITだけを指定して、どの行が返されるかを推測しないでください。 グローバル設定`TABLE_SCAN_DIRECTION`は他のクエリにも影響する場合があります。 画面の出力順序を変えるために、先にサーバー設定を変更しないでください。 [クエリチューニング](/ja/dbms/performance-tuning/performance-query-tuning/)で実行計画を確認してから、必要なアクセス経路を調整してください。 ## LOOKUPとの結合 ```sql CREATE LOOKUP TABLE ch7_query_device ( device VARCHAR(32) PRIMARY KEY, label VARCHAR(64) ); INSERT INTO ch7_query_device VALUES ('DEV-01', 'Boiler'); INSERT INTO ch7_query_device VALUES ('DEV-02', 'Pump'); SELECT q.event_id, d.label, q.value FROM ch7_query q JOIN ch7_query_device d ON q.device = d.device WHERE q._arrival_time >= TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') AND q._arrival_time < TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY q.event_id; ``` 結果は`(1, Boiler, 10)`、`(2, Boiler, 20)`、`(3, Pump, 30)`です。 LOGとLOOKUPを組み合わせるクエリのため、DURATIONの代わりにLOGカラムのWHERE範囲条件を使用します。 このINNER JOINでは、対応するマスターデータがないイベントは結果から除外される点も確認してください。 また、現在のLOOKUP値を結合しても、過去の機器説明が復元されるわけではありません。 履歴が必要なら、その時点の説明をイベントに保存するか、有効期間を持つ履歴を別途設計する必要があります。 ```sql DROP TABLE ch7_query_device; DROP TABLE ch7_query; ``` 検索件数が予想と異なる場合は、時間境界と結合前の件数を先に確認してください。 条件を1つずつ追加すると、どこで行が除外されるかを見つけやすくなります。 --- title: "7.6 インデックスとパフォーマンス" url: https://docs.machbase.com/ja/dbms/log-table-usage/index-performance/ language: ja kind: page --- # 7.6 インデックスとパフォーマンス インデックスを作成してもクエリが速くならない場合は、まずそのクエリがインデックスを使用できるか確認します。 インデックスは読み取りコストを減らす一方、入力・保存・バックグラウンド処理のコストを増やします。 カラムごとに作成するより、代表的な検索条件を決めるところから始めてください。 ## インデックスの選択 | 検索条件 | 検討するインデックス | 確認事項 | |---|---|---| | 数値・DATETIMEなどの値と範囲 | LSM | 条件に適したサポート型と実際の実行計画 | | VARCHAR・TEXTの単語・トークンパターン | KEYWORD | SEARCH・ESEARCHを使用し、LIKEとの結果の意味の違いを確認 | | サポート型の繰り返し値の分析 | BITMAP | 値の分布とエンコーディング、入力・保存コスト | LOGの`_arrival_time`範囲には、まず標準の時間アクセス経路を利用します。 同じ目的のインデックスを慣習的に追加する必要はありません。 サポート型と属性は[INDEX構文](/ja/dbms/reference/sql/syntax/index-syntax/)で確認してください。 一般的なRDBMSの複合インデックス設計をそのまま適用しないでください。 ## インデックス作成前後の比較 ```sql CREATE LOG TABLE ch7_index ( event_id INTEGER, event_time DATETIME, severity SHORT, message VARCHAR(256) ); INSERT INTO ch7_index VALUES ( 1, TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1, 'service started'); INSERT INTO ch7_index VALUES ( 2, TO_DATE('2026-01-01 10:01:00', 'YYYY-MM-DD HH24:MI:SS'), 3, 'database timeout'); INSERT INTO ch7_index VALUES ( 3, TO_DATE('2026-01-01 10:02:00', 'YYYY-MM-DD HH24:MI:SS'), 3, 'connection timeout'); EXPLAIN SELECT event_id FROM ch7_index WHERE severity = 3; CREATE INDEX ch7_index_time ON ch7_index(event_time) INDEX_TYPE LSM; CREATE INDEX ch7_index_message ON ch7_index(message) INDEX_TYPE KEYWORD; CREATE INDEX ch7_index_severity ON ch7_index(severity) INDEX_TYPE BITMAP BITMAP_ENCODE = RANGE; EXEC TABLE_FLUSH(ch7_index); EXEC INDEX_FLUSH(ch7_index); EXPLAIN SELECT event_id FROM ch7_index WHERE severity = 3; EXPLAIN SELECT event_id FROM ch7_index WHERE message SEARCH 'timeout'; SELECT event_id FROM ch7_index WHERE message SEARCH 'timeout' ORDER BY event_id; SHOW INDEXES; ``` 検索結果はイベント2と3です。実行計画で値条件とSEARCHが使用するアクセス経路を比較し、 SHOW INDEXESで作成された名前を確認してください。 この3行は動作を理解するためのサンプルであり、性能測定用のデータではありません。 ## データとインデックスの反映 `TABLE_FLUSH`はテーブルデータを反映する操作、`INDEX_FLUSH`はインデックス構築が進むまで待機する操作です。 実習で作成前後の計画と時間を比較するときは、上記のように区別して使用してください。 インデックスが存在しても、入力データ全体のインデックスへの反映が完了したとは限りません。 構築の遅延は検索コストに影響し得ます。ただし、行を入力するたびに両方のコマンドを呼ぶと、バッチ入力の利点が減ります。 運用では入力レートとバックグラウンド処理速度を併せて監視し、必要な同期タイミングだけを決めてください。 インデックスへの反映が遅いことを理由に、同じデータを再入力しないよう注意してください。 重複を避けるため、再入力前に元データの検索件数とインデックス状態を個別に確認する必要があります。 ## 性能測定の基準 作成前後で同じデータ量・条件値・同時入力負荷を使用してください。 1回の実行時間だけでなく、繰り返し検索の時間、入力スループット、インデックス容量、構築遅延を併せて記録します。 LIKE・REGEXPは元の文字列に対して条件を評価するため、先に時間範囲を制限すると検査対象を減らせます。 KEYWORDインデックスが存在しても、LIKEがSEARCHに変わるわけではありません。 ```sql DROP INDEX ch7_index_severity; DROP INDEX ch7_index_message; DROP INDEX ch7_index_time; DROP TABLE ch7_index; ``` 計画を読み取りにくい場合は、クエリとEXPLAINの結果を比較してください。 [インデックスチューニング](/ja/dbms/performance-tuning/index-tuning/)の診断手順が、次の確認箇所を決める参考になります。 --- title: "7.7 運用とデータライフサイクル" url: https://docs.machbase.com/ja/dbms/log-table-usage/operations-lifecycle/ language: ja kind: page --- # 7.7 運用とデータライフサイクル 入力は正常でもディスク使用量が増え続ける場合は、削除基準を確認します。 LOGは業務条件で特定の行を選んで削除するモデルではなく、古い領域から削除するモデルです。 保持期間と、実際に削除される境界を併せて確認する必要があります。 ## 削除方法の選択 | 目的 | コマンド | 基準 | |---|---|---| | 古いN行を削除 | OLDEST n ROWS | 古い入力行から削除 | | 最新のN行のみ保持 | EXCEPT n ROWS | 残す行数 | | 直近の期間のみ保持 | EXCEPT n DAYなど | サーバーの現在時刻から期間を引いた境界 | | 固定時刻まで削除 | BEFORE datetime_expr | 指定した_arrival_timeの境界を含む | | 全データを削除 | 条件なしのDELETEまたはTRUNCATE | 全行 | | 定期的な期間管理 | Retention Policy | 保持期間と実行周期 | 注意: 削除を元に戻せると考えないでください。LOGデータはTRANSACTIONテーブルのROLLBACK対象ではありません。 本番環境では、バックアップと実際の対象範囲を確認してから実行してください。 ## 削除方式の比較 コマンドを連続して実行すると、先の削除が次の結果に影響します。 ここでは、同じ3行を別々のテーブルにコピーして比較します。 ```sql CREATE LOG TABLE ch7_lifecycle (event_id INTEGER); CREATE LOG TABLE ch7_oldest (event_id INTEGER); CREATE LOG TABLE ch7_keep (event_id INTEGER); CREATE LOG TABLE ch7_before (event_id INTEGER); INSERT INTO ch7_lifecycle(_arrival_time, event_id) VALUES (TO_DATE('2026-01-01', 'YYYY-MM-DD'), 1); INSERT INTO ch7_lifecycle(_arrival_time, event_id) VALUES (TO_DATE('2026-01-02', 'YYYY-MM-DD'), 2); INSERT INTO ch7_lifecycle(_arrival_time, event_id) VALUES (TO_DATE('2026-01-03', 'YYYY-MM-DD'), 3); INSERT INTO ch7_oldest(_arrival_time, event_id) SELECT _arrival_time, event_id FROM ch7_lifecycle ORDER BY _arrival_time; INSERT INTO ch7_keep(_arrival_time, event_id) SELECT _arrival_time, event_id FROM ch7_lifecycle ORDER BY _arrival_time; INSERT INTO ch7_before(_arrival_time, event_id) SELECT _arrival_time, event_id FROM ch7_lifecycle ORDER BY _arrival_time; SELECT COUNT(*) AS delete_candidates FROM ch7_before WHERE _arrival_time <= TO_DATE('2026-01-02', 'YYYY-MM-DD'); DELETE FROM ch7_oldest OLDEST 1 ROWS; DELETE FROM ch7_keep EXCEPT 1 ROWS; DELETE FROM ch7_before BEFORE TO_DATE('2026-01-02', 'YYYY-MM-DD'); SELECT event_id FROM ch7_oldest ORDER BY event_id; SELECT event_id FROM ch7_keep ORDER BY event_id; SELECT event_id FROM ch7_before ORDER BY event_id; ``` 削除前に確認した件数は2です。各テーブルに残るイベントは次のとおりです。 | テーブル | 残るevent_id | |---|---| | ch7_oldest | 2, 3 | | ch7_keep | 3 | | ch7_before | 3 | BEFOREという名前には注意が必要です。 現在のLOGの削除では、指定時刻と等しい行も含まれます。 `WHERE _arrival_time < 境界`で事前に件数を数えると削除対象と異なる場合があるため、上記のように`<=`で確認してください。 ```sql DELETE FROM ch7_lifecycle; SELECT COUNT(*) AS remaining_rows FROM ch7_lifecycle; DROP TABLE ch7_before; DROP TABLE ch7_keep; DROP TABLE ch7_oldest; DROP TABLE ch7_lifecycle; ``` 全件DELETE後の件数は0になり、テーブル定義は残ります。 ## 相対期間による削除 ```sql CREATE LOG TABLE ch7_period (event_id INTEGER); INSERT INTO ch7_period(_arrival_time, event_id) VALUES (SYSDATE - 2d, 1); INSERT INTO ch7_period(_arrival_time, event_id) VALUES (SYSDATE, 2); DELETE FROM ch7_period EXCEPT 1 DAY; SELECT event_id FROM ch7_period ORDER BY event_id; DROP TABLE ch7_period; ``` 作成から検索まで続けて実行すると、イベント2だけが残ります。 基準は「最後に入力された行の時刻」ではなく、サーバーの現在時刻です。 入力が停止していても時間は進むことを、保持ポリシーにも反映してください。 ## Retention Policy 次は保持期間1日・実行周期1分の検証用の例です。 本番環境の推奨値ではありません。ポリシーの作成とテーブルへの適用に必要な権限を持つアカウントを使用してください。 ```sql CREATE LOG TABLE ch7_retention (event_id INTEGER); INSERT INTO ch7_retention(_arrival_time, event_id) VALUES (SYSDATE - 2d, 1); INSERT INTO ch7_retention(_arrival_time, event_id) VALUES (SYSDATE, 2); CREATE RETENTION ch7_policy DURATION 1 DAY INTERVAL 1 MIN; ALTER TABLE ch7_retention ADD RETENTION ch7_policy; SELECT * FROM M$RETENTION WHERE POLICY_NAME = 'CH7_POLICY'; SELECT TABLE_NAME, POLICY_NAME, STATE, LAST_DELETED_TIME FROM V$RETENTION_JOB WHERE TABLE_NAME = 'CH7_RETENTION'; SELECT event_id FROM ch7_retention ORDER BY event_id; ``` DURATIONは保持する期間、INTERVALは削除を実行する周期です。 適用直後は2行が表示される場合があります。1周期と処理時間が経過した後、次のクエリを再実行してイベント2だけが残るか確認してください。 LAST_DELETED_TIMEは削除の基準時刻であり、実時計における処理の完了時刻ではありません。 ```sql SELECT TABLE_NAME, STATE, LAST_DELETED_TIME FROM V$RETENTION_JOB WHERE TABLE_NAME = 'CH7_RETENTION'; SELECT event_id FROM ch7_retention ORDER BY event_id; ``` 実習が終わったら、適用を解除してからポリシーとテーブルを削除します。 ```sql ALTER TABLE ch7_retention DROP RETENTION; SELECT TABLE_NAME FROM V$RETENTION_JOB WHERE TABLE_NAME = 'CH7_RETENTION'; DROP RETENTION ch7_policy; DROP TABLE ch7_retention; ``` 解除後のジョブ検索結果は0件です。削除済みの行は復元されません。 1つのテーブルには1つのポリシーを適用します。使用中のポリシーは、先に解除してから削除してください。 運用基準の全体は[データ保持ポリシー](/ja/dbms/operations-configuration-recovery/policy-data-retention/)を参照してください。 ## 削除前のバックアップ検証 バックアップファイルが存在するだけでは、復旧の準備が完了したとはいえません。 削除対象の期間を、Mountまたは隔離したRestore環境で実際に検索してください。 元データ、バックアップ、別途作成した集計データの保持期間も、それぞれ定める必要があります。 環境別のコマンドは[バックアップ・リストア・マウント](/ja/dbms/operations-configuration-recovery/backup-restore-mount/)に従ってください。 ## データとディスク領域 行が検索結果から消える時点と、OS上のファイル領域が回収される時点は異なる場合があります。 入力量、残っている行の最古の時刻、インデックスとストレージのクリーンアップ状態、ディスク使用量を併せて確認してください。 削除直後にディスク使用量が減らないことを理由に、さらに広い期間を削除しないでください。 削除結果が予想と異なる場合は、境界時刻と適用されたポリシーを確認してください。 保存義務があるデータでは追加の削除を止め、担当者と対象範囲を先に確認することを推奨します。 --- title: "7.8 制約、エラー、トラブルシューティング" url: https://docs.machbase.com/ja/dbms/log-table-usage/constraints-errors-troubleshooting/ language: ja kind: page --- # 7.8 制約、エラー、トラブルシューティング 失敗したSQLを繰り返しても原因は解消せず、状態が複雑になることがあります。 まず未サポートの操作か、入力値やオブジェクトの状態の問題かを区別してください。 この節では、症状に応じて確認箇所を絞り込みます。 ## 機能のサポート範囲 | 要求 | LOGの対応 | 代替方法 | |---|---|---| | 一般的なUPDATE | 未サポート | 訂正イベントを設計するか、更新可能なテーブルを選択 | | 任意条件のDELETE WHERE | 未サポート | BEFORE・OLDEST・EXCEPTを使用するか、モデルを変更 | | PRIMARY KEY・UNIQUE制約 | 未サポート | 収集段階で重複を処理するか、別のテーブルを選択 | | 値・範囲インデックス | LSMをサポート | 型と条件に合わせて選択 | | 単語検索 | KEYWORDをサポート | VARCHAR・TEXTに作成し、SEARCH・ESEARCHを使用 | | 分析用BITMAPインデックス | サポート条件内で使用 | 型・エンコーディング・値の分布を確認 | | TEXT自体のORDER BY・GROUP BY | 未サポート | コード・重要度・時刻を別カラムに格納 | ## 症状別の診断 | 症状 | 最初の確認事項 | 対処 | |---|---|---| | 指定した到着時刻と保存時刻が異なる | 直前の時刻とTIME_INVERSION_MODE | 補正の有無を確認し、発生時刻は別に保持 | | SEARCHでインデックス関連エラー | 対象カラムのKEYWORDインデックス | 型・テーブル・インデックス名を確認 | | 単語があるのに検索されない | SEARCHのトークンとLIKEの部分文字列の違い | 元の1行で両方の結果を比較 | | インデックス作成後も検索が遅い | 実行計画・構築状態・時間範囲 | 反映状態を確認後、代表的な負荷を測定 | | カラム長の変更に失敗 | 既存の型と新しい長さ | VARCHARの拡張のみ使用し、最大長を確認 | | MINMAXの変更に失敗 | 可変長型かどうか | LOGで対応する固定長カラムのみを対象にする | | NOT NULLへの変更に失敗 | 既存のNULL行 | 既存データの検査とNOCHECKの意味を区別 | | 同じイベントが複数表示される | 元のID・再試行・ファイル再処理 | 再送ポリシーを確認し、任意行の削除で解決しない | | DDL実行中にリソース使用中エラー | 入力・検索とDDLの競合 | 実行時刻を調整して再確認 | サーバー設定とインデックス一覧は次のように確認できます。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME IN ('DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE', 'TABLE_SCAN_DIRECTION'); SHOW INDEXES; ``` 設定の確認と変更は別の操作です。 原因を特定する前に、本番サーバーのグローバル設定を変更しないでください。 ## エラーの再現と解決 ```sql CREATE LOG TABLE ch7_error (event_id INTEGER, message TEXT); INSERT INTO ch7_error VALUES (1, 'connection timeout'); SELECT event_id, message FROM ch7_error; ``` 1行が返されます。以下のSQLはそれぞれ意図的に失敗します。 通常の実習とまとめて実行せず、確認したい文だけを個別に実行してください。 ```sql -- KEYWORDインデックスがない状態です。 SELECT event_id FROM ch7_error WHERE message SEARCH 'timeout'; -- TEXT自体のソート・グループ化はサポートしていません。 SELECT message FROM ch7_error ORDER BY message; SELECT message, COUNT(*) FROM ch7_error GROUP BY message; -- LOGは一般的なUPDATE・条件付きDELETEをサポートしていません。 UPDATE ch7_error SET message = 'fixed' WHERE event_id = 1; DELETE FROM ch7_error WHERE event_id = 1; -- TEXTをVARCHARに変換するコマンドではありません。 ALTER TABLE ch7_error MODIFY COLUMN (message VARCHAR(4096)); ``` インデックスを作成し、サポートされる検索方法で確認します。 ```sql CREATE INDEX ch7_error_msg ON ch7_error(message) INDEX_TYPE KEYWORD; EXEC TABLE_FLUSH(ch7_error); EXEC INDEX_FLUSH(ch7_error); SELECT event_id, message FROM ch7_error WHERE message SEARCH 'timeout' ORDER BY event_id; DROP TABLE ch7_error; ``` 行1が返されることを確認してください。インデックスを追加しても、TEXTのソートやLOGのUPDATEは使用できません。 ## 保持ポリシーの診断 期限切れの行が残る場合は、適用ポリシー、実行周期、LAST_DELETED_TIME、実際の`_arrival_time`を合わせて確認してください。 `event_time`だけを見て削除失敗と判断しないでください。 関連する実習は[運用とデータライフサイクル](../operations-lifecycle/)にあります。 問題が続く場合は、サーバーバージョンとEdition、テーブルDDL、失敗したSQL、エラー全文、代表的な入力値を用意してください。 パスワードと機密ログを伏せて共有してください。 全データを送るより、同じ症状を再現する小さな例のほうが原因の特定に役立ちます。 --- title: "7.9 活用パターンとシナリオ" url: https://docs.machbase.com/ja/dbms/log-table-usage/patterns-scenarios/ language: ja kind: page --- # 7.9 活用パターンとシナリオ 実際の分析では、時刻、ホスト、重要度、メッセージを併せて確認します。 各機能を個別に試したら、「どのサーバーでどのエラーが増えたか」という問いに結び付けてみましょう。 この実習は、前の節のテーブルがなくても実行できます。 ## 元のイベントと現在の状態 LOGにはイベントが発生するたびに新しい行を追加します。 機器の現在の名前・場所などの変更可能なマスターデータはLOOKUPに分離できますが、 過去の状態も必要なら、その時点の値をイベントに記録するか、履歴を別途設計する必要があります。 セキュリティイベントや処理の追跡にも同じ方法を適用できます。 センサー名ごとの計測値の集計が中心ならTAG、業務行の更新やトランザクションが中心ならTRANSACTIONを先に検討してください。 ## ログとインデックスの作成 実行日に依存せず時間条件を比較できるよう、到着時刻を明示します。 空のテーブルに昇順で入力する実習です。通常の収集では、元の発生時刻を別のDATETIMEカラムに保持することを推奨します。 ```sql CREATE LOG TABLE ch7_app ( event_id INTEGER, host VARCHAR(32), level VARCHAR(16), message TEXT ); CREATE INDEX ch7_app_message ON ch7_app(message) INDEX_TYPE KEYWORD; INSERT INTO ch7_app(_arrival_time, event_id, host, level, message) VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1, 'web-01', 'INFO', 'service started'); INSERT INTO ch7_app(_arrival_time, event_id, host, level, message) VALUES (TO_DATE('2026-01-01 10:10:00', 'YYYY-MM-DD HH24:MI:SS'), 2, 'web-01', 'WARN', 'slow response'); INSERT INTO ch7_app(_arrival_time, event_id, host, level, message) VALUES (TO_DATE('2026-01-01 10:20:00', 'YYYY-MM-DD HH24:MI:SS'), 3, 'web-02', 'ERROR', 'database timeout'); INSERT INTO ch7_app(_arrival_time, event_id, host, level, message) VALUES (TO_DATE('2026-01-01 10:30:00', 'YYYY-MM-DD HH24:MI:SS'), 4, 'web-02', 'ERROR', 'connection refused'); INSERT INTO ch7_app(_arrival_time, event_id, host, level, message) VALUES (TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 5, 'web-01', 'INFO', 'normal service'); EXEC TABLE_FLUSH(ch7_app); EXEC INDEX_FLUSH(ch7_app); SELECT COUNT(*) AS received_rows FROM ch7_app; ``` 入力件数は5です。実習を繰り返す前に、最後のDROPまで実行したことを確認してください。 単純な再送は重複行につながる場合があります。 ## エラーと時間帯による検索 ```sql SELECT event_id, host, message FROM ch7_app WHERE _arrival_time >= TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') AND _arrival_time < TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS') AND message SEARCH 'timeout' ORDER BY event_id; SELECT event_id, host, level, message FROM ch7_app WHERE _arrival_time >= TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') AND _arrival_time < TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS') AND level = 'ERROR' ORDER BY event_id; ``` 最初のクエリはweb-02のイベント3、2番目はイベント3と4を選択します。 特定の単語から検索を始め、分析では同じホスト・時間帯の他のエラーも確認する流れです。 検索範囲を広げるときは、時間条件をすべて外すのではなく、必要な区間だけを広げてください。 ## 時間別・重要度別の集計 ```sql SELECT TO_CHAR(_arrival_time, 'YYYY-MM-DD HH24') AS event_hour, level, COUNT(*) AS event_count FROM ch7_app WHERE _arrival_time >= TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS') AND _arrival_time < TO_DATE('2026-01-01 12:00:00', 'YYYY-MM-DD HH24:MI:SS') GROUP BY TO_CHAR(_arrival_time, 'YYYY-MM-DD HH24'), level ORDER BY event_hour, level; ``` | event_hour | level | event_count | |---|---|---| | 2026-01-01 10 | ERROR | 2 | | 2026-01-01 10 | INFO | 1 | | 2026-01-01 10 | WARN | 1 | | 2026-01-01 11 | INFO | 1 | このクエリは元のLOGを読み取って集計します。TAGのROLLUPを自動的に使用するクエリではありません。 データが増えたら、検索区間と実行計画を確認し、事前集計が必要かを別途判断してください。 固定時刻のデータに`DURATION 1 HOUR`を適用しないよう注意してください。 この条件は現在時刻を基準にするため、実行日が変わるとサンプルが選択されない場合があります。 運用時の直近ログ検索と、再現用の固定時刻検索を区別してください。 ## 収集と保持の管理 継続的な収集は[Append入力](../data-input-mutation/)を参照して構成できます。 長期運用では[保持ポリシー](../operations-lifecycle/)も定めてください。 元のログ、バックアップ、別途作成する集計データでは、必要な保持期間が異なる場合があります。 ```sql DROP TABLE ch7_app; ``` ここまでの結果が一致したら、実際のログ数件でフィールドとメッセージを置き換えてください。 収集全体を一度に移行するより、小さなサンプルで同じ問いに答えられるか確認すると、問題を見つけやすくなります。 --- title: "7.10 _arrival_timeの時間モデル" url: https://docs.machbase.com/ja/dbms/log-table-usage/arrival-time-model/ language: ja kind: page --- # 7.10 _arrival_timeの時間モデル 元のログには昨日の時刻が記録されていても、クエリでは今日収集したデータとして扱われることがあります。 発生時刻と収集時刻を混同すると、正常に取り込まれたデータも欠落したように見えます。 LOGのクエリと保持ポリシーを設計するには、まずこの2つの時刻を区別します。 ## 発生時刻と到着時刻 `event_time`などのユーザー定義DATETIMEカラムは、イベントが発生した時刻を表します。 自動生成される`_arrival_time`は、LOGの時間範囲アクセスと保持期間に基づく削除の基準です。 省略するとサーバー時刻が使われますが、明示的な入力や時刻逆転の補正もあるため、 常に実際のネットワーク受信時刻を表すとは限りません。 DATETIMEはナノ秒単位の値を表現します。サーバーの時計が毎回ナノ秒精度で時刻を測定するという意味ではありません。 保存後にLOGテーブルのUPDATEで時刻を修正することもできません。 ## 遅延イベントの検索 次の例では、空の実習用テーブルに到着時刻を昇順で指定して挿入します。 ```sql CREATE LOG TABLE ch7_time ( event_id INTEGER, event_time DATETIME, message VARCHAR(64) ); INSERT INTO ch7_time(_arrival_time, event_id, event_time, message) VALUES (TO_DATE('2026-01-02 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1, TO_DATE('2026-01-02 09:59:00', 'YYYY-MM-DD HH24:MI:SS'), 'normal arrival'); INSERT INTO ch7_time(_arrival_time, event_id, event_time, message) VALUES (TO_DATE('2026-01-02 10:01:00', 'YYYY-MM-DD HH24:MI:SS'), 2, TO_DATE('2026-01-01 23:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'delayed arrival'); SELECT event_id FROM ch7_time WHERE event_time >= TO_DATE('2026-01-01', 'YYYY-MM-DD') AND event_time < TO_DATE('2026-01-02', 'YYYY-MM-DD') ORDER BY event_id; SELECT event_id FROM ch7_time DURATION FROM TO_DATE('2026-01-02 10:00:00', 'YYYY-MM-DD HH24:MI:SS') TO TO_DATE('2026-01-02 10:01:00', 'YYYY-MM-DD HH24:MI:SS'); ``` 発生時刻による検索ではイベント2だけが、到着時刻による検索ではイベント1と2が選択されます。 遅れて到着したイベントの発生時刻を変更する必要はありません。 ## 時刻逆転と補正 `DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE`は、直前の到着時刻より小さい値が入力された場合の処理を指定します。 現在のStandard実装の動作は次のとおりです。 | 値 | 時刻が逆転した入力の処理 | |---|---| | 1(デフォルト) | 直前に保存した`_arrival_time`より1ns大きい値に補正 | | 0 | 時刻逆転エラーとして入力を拒否 | 同じ時刻は逆転に該当しないため、この規則だけで各行の時刻が一意になるわけではありません。 同時刻の行にも固定の順序が必要なら、イベント番号などの追加条件をORDER BYに指定してください。 次の任意の実習では、先ほどのテーブルを使います。 まず設定を確認し、値が1の検証環境でのみ実行してください。 この例のために本番サーバーの設定を変更しないでください。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME = 'DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE'; ``` ```sql -- 設定値1で実行します。値が0の場合は入力エラーが想定されます。 INSERT INTO ch7_time(_arrival_time, event_id, event_time, message) VALUES (TO_DATE('2026-01-02 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3, TO_DATE('2026-01-02 08:59:00', 'YYYY-MM-DD HH24:MI:SS'), 'inverted arrival'); SELECT event_id, TO_CHAR(_arrival_time, 'YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn') AS stored_time FROM ch7_time ORDER BY event_id; ``` 設定値が1の場合、イベント3の保存時刻は入力した09:00ではなく、 `2026-01-02 10:01:00 000:000:001`になります。発生時刻は入力値のままです。 したがって、時刻逆転の「許可」は、過去の時刻を無条件に保持するという意味ではありません。 ## データ移行時の注意事項 元の`_arrival_time`を保持するには、空の移行先に昇順で入力することが基本です。 ソート済みでも、移行先により新しい時刻の行がある場合や、別の入力が割り込む場合は補正やエラーが発生し得ます。 同じテーブルで移行と通常のリアルタイム収集を混在させないでください。 `DURATION`は`event_time`ではなく`_arrival_time`を使用します。 タイムゾーンと日付書式を合わせても範囲が異なる場合は、クエリが参照する時間カラムを再確認してください。 境界と出力順序については、[クエリの実習](../query-analysis/)で説明します。 ```sql DROP TABLE ch7_time; ``` 時刻に関する問題を問い合わせる際は、元の時刻、保存された時刻、設定値を用意してください。 3つを比較すると、変換と補正のどちらの段階で差が生じたかを判断しやすくなります。 --- title: "7.11 テキスト検索とKEYWORDインデックス" url: https://docs.machbase.com/ja/dbms/log-table-usage/text-search-keyword-index/ language: ja kind: page --- # 7.11 テキスト検索とKEYWORDインデックス メッセージに同じ文字が含まれていても、SEARCHとLIKEの結果は異なる場合があります。 SEARCHは索引化された単語を検索し、LIKEは元の文字列にパターンを適用するためです。 性能を比較する前に、どの行を検索するかを明確にします。 ## 検索データの準備 ```sql CREATE LOG TABLE ch7_search ( event_id INTEGER, message TEXT ); CREATE INDEX ch7_search_msg ON ch7_search(message) INDEX_TYPE KEYWORD; INSERT INTO ch7_search VALUES (1, 'ERROR connection timeout'); INSERT INTO ch7_search VALUES (2, 'connection slowly refused'); INSERT INTO ch7_search VALUES (3, 'pretimeout marker'); INSERT INTO ch7_search VALUES (4, 'normal service'); INSERT INTO ch7_search VALUES (5, NULL); INSERT INTO ch7_search VALUES (6, '대한민국 연결 오류'); INSERT INTO ch7_search VALUES (7, 'ERR-1001 network'); INSERT INTO ch7_search VALUES (8, 'timeout refused connection'); EXEC TABLE_FLUSH(ch7_search); EXEC INDEX_FLUSH(ch7_search); ``` サンプルの`event_id`で結果を比較します。メッセージはTEXTなので、ソート基準には使用しません。 LOGのVARCHARでも同じKEYWORD検索を使用できます。 ## SEARCHとNOT SEARCH ```sql SELECT event_id FROM ch7_search WHERE message SEARCH 'timeout' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message SEARCH 'connection refused' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message SEARCH 'connection' AND message SEARCH 'refused' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message NOT SEARCH 'timeout' ORDER BY event_id; ``` | 条件 | 選択されるevent_id | 理由 | |---|---|---| | SEARCH 'timeout' | 1, 8 | pretimeoutは別の単語 | | SEARCH 'connection refused' | 2, 8 | 両方の単語が存在する | | 2つのSEARCH条件をANDで結合 | 2, 8 | 同じメッセージ内の両方の単語を確認 | | NOT SEARCH 'timeout' | 2, 3, 4, 6, 7 | 対象の単語がなく、NULL行は除外 | 複数単語のSEARCHは、語順や隣接性を保証するフレーズ検索ではありません。 イベント2には間に別の単語があり、イベント8は逆順ですが、両方とも選択されます。 他のカラムにもSEARCHを使用するには、そのカラムにも対応するインデックスが必要です。 デフォルトのトークン化では、通常のASCII単語は小文字に正規化されます。 例えば、イベント1の`ERROR`は`SEARCH 'error'`でも検索されます。 これをすべてのUnicode文字に対する言語別の大文字・小文字処理と解釈しないでください。 ### 韓国語のトークン分割 ```sql SELECT event_id FROM ch7_search WHERE message SEARCH '대한' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message SEARCH '연결' ORDER BY event_id; ``` どちらもイベント6が選択されます。デフォルトモードでは、`대한민국`は`대한`、`한민`、`민국`のような 重複する2-gramとして索引化されます。形態素や文の意味を理解する検索ではありません。 空白・句読点・1文字の値・英語と韓国語の混在値ではトークン境界が変わる場合があるため、実際のサンプルで確認してください。 MODEなどのインデックスオプションを変更すると、トークン化も変わる場合があります。 ## ESEARCHによる拡張検索 ```sql SELECT event_id FROM ch7_search WHERE message ESEARCH 'time%' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message ESEARCH '%time%' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message ESEARCH 'err%' ORDER BY event_id; ``` | パターン | 選択されるevent_id | 意味 | |---|---|---| | time% | 1, 8 | timeで始まる単語 | | %time% | 1, 3, 8 | timeを含む単語 | | err% | 1, 7 | errorやerrのようにerrで始まる単語 | `time%`は単語の途中にあるtimeまで検索するものではありません。 また、ESEARCHは原文全体にLIKEを適用することと同じではありません。 空白や句読点をまたぐ原文パターンを、そのままESEARCHに移さないでください。 複雑な複数条件は、個別のSEARCH・ESEARCH条件をAND・ORで結合し、意味を明示してください。 現在の比較処理では、ESEARCHはASCIIの大文字と小文字を区別しません。 対象キーワードが広く一致するほど検索コストも増えるため、常にLIKEより高速とは限りません。 この例はASCIIキーワードのパターンを対象としています。 `NOT ESEARCH`構文はサポートしていません。`NOT SEARCH`や`NOT LIKE`に変更すると、検索の意味も変わります。 除外する行を再定義し、NULLの扱いまで確認してください。 ## LIKEとNOT LIKE ```sql SELECT event_id FROM ch7_search WHERE message LIKE '%TIMEOUT%' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message LIKE 'ERR-____' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message NOT LIKE '%timeout%' ORDER BY event_id; ``` 最初のクエリはイベント1・3・8、2番目は0件、3番目はイベント2・4・6・7を返します。 イベント7のメッセージは`ERR-1001`の後にも文字列があるため、全体パターン`ERR-____`に一致しません。 `%`は0文字以上、`_`は1文字を表します。 リテラルの`%`・`_`・バックスラッシュを検索する場合は、バックスラッシュのエスケープ規則も確認してください。 LIKEも現在のASCII比較では大文字と小文字を区別しません。 KEYWORDインデックスは使用しませんが、WHEREの他の条件や時間範囲で検査する行を減らせます。 したがって、LIKEがあるという理由だけで常にテーブル全体を読むと説明するのも正確ではありません。 ## REGEXPとREGEXP_LIKE ```sql SELECT event_id FROM ch7_search WHERE message REGEXP '^ERR-[0-9]+' ORDER BY event_id; SELECT event_id FROM ch7_search WHERE message NOT REGEXP 'timeout' ORDER BY event_id; ``` 最初のクエリはイベント7、2番目はイベント2・4・6・7を返します。 REGEXPは正規表現パターンに一致する部分があるかを検査します。 文字列の先頭や末尾を制限するには、`^`・`$`を明示してください。 関数として使用する場合は`REGEXP_LIKE`を使用します。 現在、この関数の入力はVARCHARである必要があり、パターンとオプションも定数VARCHARである必要があります。 先ほどのTEXTカラムをそのまま渡すと型エラーになるため、別のサンプルを用意します。 ```sql CREATE LOG TABLE ch7_regexp_fn (event_id INTEGER, message VARCHAR(200)); INSERT INTO ch7_regexp_fn VALUES (1, 'ERROR connection timeout'); INSERT INTO ch7_regexp_fn VALUES (5, NULL); SELECT event_id, REGEXP_LIKE(message, 'error') AS case_sensitive, REGEXP_LIKE(message, 'error', 'i') AS case_insensitive FROM ch7_regexp_fn WHERE event_id IN (1, 5) ORDER BY event_id; ``` イベント1の結果はそれぞれ0・1、メッセージがNULLのイベント5は両方ともNULLです。 デフォルトの正規表現比較は大文字と小文字を区別し、`i`オプションは区別しない比較です。 区別する比較を明示するには`c`を使用できます。 正規表現はKEYWORDインデックスで直接処理されません。 時間条件やSEARCHで対象を絞れますが、先行条件で必要な行を除外すると、後続の正規表現でその行を取り戻すことはできません。 ## TEXTの制約と検索性能 TEXTは最大64MiBの原文を格納できますが、TEXT自体のORDER BY・GROUP BYはサポートしていません。 ソート・集計するデバイス・エラーコード・重要度は別カラムに格納してください。 同じデータでインデックスの有無、構築状態、検索範囲を確認してから性能を比較します。 ```sql DROP TABLE ch7_regexp_fn; DROP TABLE ch7_search; ``` 検索結果が異なる場合は、元の1行と使用したパターンを併せて確認してください。 単語を探すのか、原文の一部を探すのかを区別するだけで解決する場合も多くあります。 --- title: "7.12 ネットワーク型のクエリ" url: https://docs.machbase.com/ja/dbms/log-table-usage/regex-network-query/ language: ja kind: page --- # 7.12 ネットワーク型のクエリ IPアドレスを文字列で保存すると読みやすい反面、文字列のソート順とアドレス範囲の順序が同じだと考えがちです。 アドレスの比較が目的ならIPV4・IPV6型を使用し、元の表記も必要な場合だけ別の文字列を併せて保存してください。 ## ネットワークデータの準備 ```sql CREATE LOG TABLE ch7_network ( event_id INTEGER, src_ip IPV4, dst_ip IPV6, dst_port INTEGER ); INSERT INTO ch7_network VALUES (1, '192.0.2.1', '2001:db8::1', 80); INSERT INTO ch7_network VALUES (2, '192.0.2.255', '2001:db8::2', 65535); INSERT INTO ch7_network VALUES (3, '198.51.100.1', '2001:db8::3', 443); INSERT INTO ch7_network VALUES (4, NULL, NULL, NULL); SELECT event_id, src_ip, dst_ip, dst_port FROM ch7_network ORDER BY event_id; ``` 4行が返されます。ポートにはINTEGERを使用します。 USHORTの最大値65535はNULLの予約値なので、ポートの全範囲をそのまま表現する用途には適しません。 ## 等価比較と範囲検索 ```sql SELECT event_id FROM ch7_network WHERE src_ip BETWEEN '192.0.2.1' AND '192.0.2.255' ORDER BY event_id; SELECT event_id FROM ch7_network WHERE src_ip IN ('192.0.2.1', '198.51.100.1') ORDER BY event_id; SELECT event_id FROM ch7_network WHERE dst_ip = '2001:db8::2' ORDER BY event_id; SELECT event_id FROM ch7_network WHERE dst_ip BETWEEN '2001:db8::1' AND '2001:db8::2' ORDER BY event_id; SELECT event_id FROM ch7_network WHERE src_ip IS NULL ORDER BY event_id; ``` | 条件 | 選択されるevent_id | |---|---| | IPv4 BETWEEN | 1, 2 | | IPv4 IN | 1, 3 | | IPv6等価比較 | 2 | | IPv6 BETWEEN | 1, 2 | | IPv4 IS NULL | 4 | BETWEENは両端のアドレスを含みます。この例のIPv4範囲はCIDRの意味を自動適用するものではなく、 明示的に指定した2つのアドレス間の範囲です。 ネットワーク範囲への所属を判定する場合は、次の`CONTAINED`を使用してください。 NULLは`= NULL`ではなく`IS NULL`で検査します。 ## CIDRによる判定 アドレスが特定のネットワークに属するかを検査するには、`CONTAINED`を使用します。 範囲は必ず`アドレス/prefix`形式で指定します。IPv4とIPv6の両方で使用できます。 ```sql SELECT event_id FROM ch7_network WHERE src_ip CONTAINED '192.0.2.0/24' ORDER BY event_id; SELECT event_id FROM ch7_network WHERE dst_ip CONTAINED '2001:db8::/32' ORDER BY event_id; SELECT event_id FROM ch7_network WHERE src_ip NOT CONTAINED '192.0.2.0/24' ORDER BY event_id; ``` | 条件 | 選択されるevent_id | |---|---| | IPv4 `CONTAINED '192.0.2.0/24'` | 1, 2 | | IPv6 `CONTAINED '2001:db8::/32'` | 1, 2, 3 | | IPv4 `NOT CONTAINED '192.0.2.0/24'` | 3 | 向きを逆にした`'192.0.2.0/24' CONTAINS src_ip`も同じ意味です。 左辺にネットワーク、右辺にアドレスを指定する形式が`CONTAINS`で、その逆が`CONTAINED`です。 prefixを省略して`CONTAINED '192.0.2.0'`と書くと、ネットワークとして解釈できずエラーになります。 アドレスがNULLのイベント4はいずれの条件でも選択されません。 未収集のアドレスも数える場合は、`IS NULL`条件を別途指定してください。 ## アドレス形式と元の表記の保持 IPv4だけを入力する場合はIPV4、IPv6を入力する場合はIPV6でスキーマを定義します。 両方を扱う場合は、入力変換とカラム分離のポリシーを先に定め、実際のサンプルで検証してください。 暗黙の変換が常に意図どおりに元のアドレスを正規化するとは限りません。 出力文字列には注意が必要です。同じIPv6アドレスでも、元の圧縮表記と検索結果の表記が異なる場合があります。 原文を証跡として残す必要がある場合は、アドレス型カラムと原文カラムを分離すると明確です。 大量データでは、アドレス条件に加えて`_arrival_time`の範囲を制限し、実行計画を確認してください。 メッセージの正規表現検索は[テキスト検索](../text-search-keyword-index/#regex)と [SQL関数リファレンス](/ja/dbms/reference/sql/functions/)を参照してください。 ```sql DROP TABLE ch7_network; ``` アドレス検索の結果が予想と異なる場合は、元の文字列、入力型、範囲の両端を並べて比較してください。 文字列表現の違いか、実際のアドレス範囲の違いかを区別しやすくなります。 --- title: "8. TRANSACTIONテーブルの活用" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/ language: ja kind: section --- # 8. TRANSACTIONテーブルの活用 元のログを蓄積する処理と、注文状態・在庫・機器情報を変更する処理では性質が異なります。 状態を変更する業務では、「何行が変わったか」「途中で失敗するとどこまで戻るか」 「別の接続が同時に更新するとどうなるか」も確認する必要があります。 TRANSACTIONテーブルは、このようなリレーショナルなクエリと変更のためのStandard Edition専用テーブルです。 この章では、小さなサンプルで結果を確認しながら、スキーマ、更新、トランザクション、同時アクセス、復旧を説明します。 内部ではSQLiteストレージを使用しますが、公開構文とサポート範囲はMachbase SQLを基準にしてください。 SQLiteや他のRDBMSの全機能をそのまま使用できるわけではありません。 ## この章の構成 | 節 | 確認内容 | |---|---| | [8.1 概要と選択基準](./overview-use-criteria/) | LOG・TAG・LOOKUPとの役割の区別 | | [8.2 テーブル構造とスキーマ](./table-structure-schema/) | 識別子・業務キー・型・制約の設計 | | [8.3 作成、変更、削除](./create-alter-drop/) | DDLの実行と既存データの確認 | | [8.4 データ入力と変更](./data-input-mutation/) | 条件付き更新・削除・コピー・Append | | [8.5 クエリと分析](./query-analysis/) | フィルター・ソート・集計・JSON検索 | | [8.6 インデックスとパフォーマンス](./index-performance/) | PK・UNIQUE・複合・JSONパスインデックス | | [8.7 運用とデータライフサイクル](./operations-lifecycle/) | バッチ削除と運用確認の基準 | | [8.8 制約、エラー、トラブルシューティング](./constraints-errors-troubleshooting/) | 症状別の確認と再試行判断 | | [8.9 トランザクション](./transaction/) | 文の失敗・ROLLBACK・コミットの保証範囲 | | [8.10 ロック、競合、busy timeout](./locking-conflict-timeout/) | 2接続の競合とスナップショットの再試行 | | [8.11 JOINとリレーショナルクエリの設計](./join-relational-query/) | 結合で増加・除外される行の確認 | | [8.12 バックアップ、リストア、マウント](./backup-restore-mount/) | バックアップ時点のデータの実検証 | | [8.13 INSERT ON DUPLICATE KEY UPDATE](./insert-on-duplicate-key-update/) | 挿入・更新の分岐と重複処理 | 自動採番の共通構文は[AUTO_INCREMENT](/ja/dbms/reference/sql/syntax/auto-increment-syntax/)を参照してください。 ## 実習環境と実行単位 SQL実習はDBMS 8.7 Standard Editionの検証環境を対象にします。 各節で`ch8_`接頭辞のオブジェクトを準備・削除するため、他の節の実行結果には依存しません。 テーブル・インデックスの作成権限が必要で、バックアップの実習には別途権限とサーバー上のパスが必要です。 BEGINからCOMMIT・ROLLBACKまでは同じ接続で実行してください。 2セッションの実習では、指定したA・Bの順序に従ってください。 意図的に失敗するSQLは通常の流れと分離しています。 実習を再実行する前に、クリーンアップSQLまで完了したことを確認してください。 注意: テーブル名にTRANSACTIONが含まれていても、すべての操作とすべての障害を一括で戻せるわけではありません。 DDL、他のタイプへの書き込み、障害時の複数テーブルのコミット境界は、[8.9 トランザクション](./transaction/)で先に確認してください。 --- title: "8.1 概要と選択基準" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/overview-use-criteria/ language: ja kind: page --- # 8.1 概要と選択基準 機器の測定値は継続的に蓄積されますが、点検状態や在庫数量は既存値を変更する必要があります。 両方を同じモデルで処理すると、元データの保持と状態変更の要件が混在しがちです。 変更可能な業務データをTRANSACTIONに、元の時系列データをTAG・LOGに格納する構成を先に検討してください。 ## TRANSACTIONテーブルの特性 TRANSACTIONはSELECT・INSERT・UPDATE・DELETE、PRIMARY KEY、UNIQUE INDEX、セカンダリインデックスをサポートします。 Standard Edition専用で、次の3つの構文は同じテーブルを作成します。 | 構文 | 意味 | |---|---| | CREATE TABLE | タイプを省略したデフォルトのTRANSACTION作成 | | CREATE TRANSACTION TABLE | タイプを明示した作成 | | CREATE TXN TABLE | 短縮形による作成 | 公開文書と運用スクリプトでは、タイプが明確なCREATE TRANSACTION TABLEを推奨します。 CREATE RDB TABLE・CREATE TRX TABLEはサポートしていません。 Clusterでは上の3つの作成構文をすべて使用できません。LOGはCREATE LOG TABLEで明示します。 ## 状態変更とロールバック ```sql CREATE TRANSACTION TABLE ch8_overview ( item_id LONG PRIMARY KEY, qty INTEGER NOT NULL ); INSERT INTO ch8_overview VALUES (42, 10); BEGIN; UPDATE ch8_overview SET qty = qty - 3 WHERE item_id = 42 AND qty >= 3; SELECT item_id, qty FROM ch8_overview; ROLLBACK; SELECT item_id, qty FROM ch8_overview; DROP TABLE ch8_overview; ``` 同じ接続では、トランザクション内の検索は数量7、ROLLBACK後の検索は10を返します。 `qty >= 3`は、在庫不足の場合に変更しないための業務条件です。 UPDATEがエラーなしで終了すれば業務も成功した、と判断しないよう注意してください。 条件に一致する行がなければ、変更件数は0になり得ます。 アプリケーションでは影響行数が想定した1であることを確認し、次の処理かロールバックかを決める必要があります。 SQL例の数値を置き換えることより、この確認手順が重要です。 ## 他のテーブルとの比較 | 主な要件 | 最初に検討するテーブル | |---|---| | センサー名ごとの測定値とROLLUP | TAG | | 更新しないログ・イベントの元データ | LOG | | 小規模な現在のマスターデータ | LOOKUP | | リレーショナルなDMLと明示的トランザクション | TRANSACTION | | 再起動後に消失してもよいメモリ上の状態 | VOLATILE | TRANSACTIONには、機器の点検状態、業務履歴、別途作成した要約結果などを格納できます。 大量の元データの収集では、TAG・LOGとスループット・取り込み方法を比較してください。 TRANSACTIONもAppendをサポートしますが、TAG・LOGと同じスループットやバッチ境界を前提にしないでください。 [取り込み方式](../data-input-mutation/)で具体的に区別します。 LOOKUPは、TRANSACTIONの全機能を代替するテーブルではありません。 Clusterでリレーショナルトランザクションが必須の場合は、別のRDBMSを含む構成を検討する必要があります。 ## 設計基準 1行を識別するキーと、重複を防ぐ業務キーを区別してください。 内部番号にはPRIMARY KEY、外部システムのコードなど別の一意値にはUNIQUE INDEXが必要な場合があります。 自動採番を使用しても、業務キーの重複は自動的には防げません。 続いて、頻繁に実行するWHERE条件と業務の成功基準を決めます。 トランザクションの終了位置とエラー時の確認事項まで決めておくと、同時要求や接続障害が発生しても対応を一貫させられます。 [スキーマ](../table-structure-schema/)と[トランザクション](../transaction/)を併せて確認してください。 --- title: "8.2 テーブル構造とスキーマ" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/table-structure-schema/ language: ja kind: page --- # 8.2 テーブル構造とスキーマ 自動採番があれば重複の問題は解決したと考えがちです。 しかし、同じ外部機器が異なる番号で2回登録されることは依然として可能です。 行の識別キーと業務上の重複を防ぐキーを区別することが、スキーマ設計の出発点です。 ## 内部識別子と業務キー 次の例では、内部番号と外部機器コードを別々に管理します。 ```sql CREATE TRANSACTION TABLE ch8_schema ( id LONG PRIMARY KEY AUTO_INCREMENT, external_code VARCHAR(64) NOT NULL, device_name VARCHAR(128) NOT NULL, price DECIMAL(18,2), state JSON, updated_at DATETIME ); CREATE UNIQUE INDEX ch8_schema_code ON ch8_schema(external_code); INSERT INTO ch8_schema(external_code, device_name, price, state, updated_at) VALUES ('ERP-01', 'Pump A', 19900.25, '{"status":"NORMAL"}', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS')); SELECT external_code, device_name, price, state->'$.status' AS status FROM ch8_schema; ``` ERP-01の1行、価格19900.25、状態NORMALが返されます。 idはサーバーが付与します。連続番号や欠番のない発行を業務条件にしないでください。 発行番号の取得方法は、使用するSDKと[AUTO_INCREMENT](/ja/dbms/reference/sql/syntax/auto-increment-syntax/)を確認してください。 ## PRIMARY KEYとUNIQUE TRANSACTIONのPRIMARY KEYはテーブルごとに1つで、単一列です。 列の後にPRIMARY KEYを指定するか、既存テーブルにCREATE PRIMARY KEY INDEXで追加できます。 NULLや重複を含むデータには作成できません。 複数列の組み合わせを一意にするには、複合UNIQUE INDEXを使用します。 他のDBMSのCREATE TABLE内のUNIQUE・FOREIGN KEY・テーブルレベルPRIMARY KEY構文を、そのまま持ち込まないでください。 一意性はテーブル作成後にCREATE UNIQUE INDEXで指定します。 UNIQUE INDEXのキーにNULLが含まれる場合、NULLを含むキー同士は重複とは見なされません。 コードが必須かつ一意である必要がある場合は、例のようにNOT NULLも宣言してください。 空文字列にも注意が必要です。Machbaseの空文字列とNULLの扱いも実際の取り込み方法で確認し、必須コードは収集段階で検証してください。 次のSQLはUNIQUE違反を確認する任意の実習です。通常の入力とは分けて実行してください。 ```sql -- 意図的に失敗: external_codeの重複 INSERT INTO ch8_schema(external_code, device_name) VALUES ('ERP-01', 'Duplicate Pump'); ``` 失敗後もERP-01は1行のままである必要があります。 重複時に更新するには、[UPSERT](../insert-on-duplicate-key-update/)の別の規則を使用します。 ## データ型の選択 | 値 | 型の選択 | 確認事項 | |---|---|---| | 識別子・数量 | SHORT・INTEGER・LONGとサポートされる符号なし型 | 範囲とNULL予約値 | | 測定値・近似値 | FLOAT・DOUBLE | 浮動小数点の丸め | | 金額・正確な小数 | DECIMAL(M,D)とNUMERICなどの別名 | 精度・小数桁数・入力変換 | | コード・名前 | VARCHAR(n) | 文字数ではなくバイト長 | | 長い文字列・バイナリ | TEXT/CLOB・BINARY/BLOB | 保存の対応とソート・関数・インデックスの対応を区別 | | 発生・変更時刻 | DATETIME | 元のタイムゾーンと変換書式 | | ネットワークアドレス | IPV4・IPV6 | アドレス形式と比較の意味 | | 追加属性 | JSON | 頻繁に検索するパスと型 | | 固定長の数値群 | 数値ARRAY | 要素型・長さ・列全体のNULLと要素のNULL | 全体の範囲は[データ型リファレンス](/ja/dbms/reference/sql/types/)、 金額は[DECIMAL](/ja/dbms/reference/sql/types/decimal-numeric-fixed-point/)を基準に確認してください。 例のDOUBLEを慣習的にすべての金額列に使用しないでください。 ## 制約と入力検証 TRANSACTIONには少なくとも1つのユーザー列が必要です。 LOGの自動到着時刻や、TAGのMETADATA・BASETIME・BASEDISTANCEは使用できません。 外部キーが自動的に参照整合性を検査すると考えず、必要な関係の検証をアプリケーションとデータ点検手順に含めてください。 例のUNIQUE INDEXがあっても、機器名や価格の業務上の有効性まで検査されるわけではありません。 必須値、許可する状態、数量範囲は別途定義する必要があります。 ```sql SELECT COUNT(*) AS device_count FROM ch8_schema; DROP TABLE ch8_schema; ``` クリーンアップ前の件数は1です。 スキーマ変更は[作成・変更・削除](../create-alter-drop/)、クエリのアクセス経路は [インデックス設計](../index-performance/)で引き続き確認してください。 --- title: "8.3 作成、変更、削除" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/create-alter-drop/ language: ja kind: page --- # 8.3 作成、変更、削除 スキーマ変更では、コマンドの成否と同じくらい、既存データと取り込みプログラムの状態が重要です。 名前を変更した後に古いSQLを実行したり、インデックスが参照する列を先に削除したりするとエラーになります。 この節ではサンプルを入力した状態で、変更前後を確認します。 ## テーブルの作成 ```sql CREATE TRANSACTION TABLE ch8_ddl ( id LONG, code VARCHAR(32), qty INTEGER ); INSERT INTO ch8_ddl VALUES (1, 'P-01', 10); ``` ## キーとインデックスの作成 ```sql CREATE PRIMARY KEY INDEX ch8_ddl_pk ON ch8_ddl(id); CREATE UNIQUE INDEX ch8_ddl_code ON ch8_ddl(code); CREATE INDEX ch8_ddl_qty ON ch8_ddl(qty); SHOW INDEX ch8_ddl_code; ``` idは単一のPRIMARY KEY、codeは別の業務キーです。 既存データに重複やPRIMARY KEYのNULLがある場合は、作成に失敗することがあります。 複合的な一意性はCREATE UNIQUE INDEXで設定します。CREATE TABLE内のUNIQUE制約構文は未サポートです。 自動採番が必要な場合は、作成時に`LONG PRIMARY KEY AUTO_INCREMENT`を指定します。 この節のidは直接入力した値で、自動採番列ではありません。 2つの作成方式を同じオブジェクトに重複して実行しないでください。 [AUTO_INCREMENT](/ja/dbms/reference/sql/syntax/auto-increment-syntax/)に別の実習があります。 ## 列の追加とデフォルト値 ```sql ALTER TABLE ch8_ddl ADD COLUMN (label VARCHAR(64)); ALTER TABLE ch8_ddl ADD COLUMN (status VARCHAR(16) DEFAULT 'NEW'); ALTER TABLE ch8_ddl ADD COLUMN (limits DECIMAL(12)[2] DEFAULT [10, 20]); SELECT id, label, status, limits FROM ch8_ddl ORDER BY id; ``` 行1のlabelはNULL、statusはNEW、limitsは[10, 20]です。 DEFAULTのないARRAY列を追加すると、既存行では配列全体がNULLになります。 `ADD COLUMN`の`DEFAULT`と`CREATE TABLE`の`DEFAULT`は許可範囲が異なります。 上記のように`ADD COLUMN`では型に合う値を指定できますが、`CREATE TABLE`の列定義では、 `DATETIME`列の`DEFAULT SYSDATE`だけを使用できます。 他の型や値を指定すると、それぞれ`ERR-02346`、`ERR-02347`で拒否されます。 作成時にデフォルト値が必要なら、先に列を作成してから`ADD COLUMN`で追加するか、入力文で値を指定してください。 配列内の一部の要素がNULLの場合とは区別してください。 列定義は括弧で囲みます。他のDBMSのALTER TABLE形式と混同しないでください。 TRANSACTIONはMODIFY COLUMNによる長さ・型の変更をサポートしていません。 必要なら、新しいスキーマへの移行手順を別途用意してください。 ## 列の変更と依存オブジェクト ```sql DROP INDEX ch8_ddl_qty; ALTER TABLE ch8_ddl DROP COLUMN (qty); ALTER TABLE ch8_ddl DROP COLUMN (label); ALTER TABLE ch8_ddl DROP COLUMN (limits); ALTER TABLE ch8_ddl RENAME COLUMN code TO product_code; SELECT id, product_code, status FROM ch8_ddl; SHOW INDEX ch8_ddl_code; ``` 既存の行1のP-01・NEWという値と業務キーのインデックスは保持されます。 PRIMARY KEY・UNIQUE・一般・JSONパスインデックスが参照する列では、該当するインデックスを先に確認する必要があります。 最後のユーザー列は削除できません。 VIEWがテーブルや列を参照している場合、関連する名前変更・削除が拒否される場合があります。 VIEWだけでなくアプリケーションSQLとプリペアドステートメントも変更の影響を受けます。 DDL後に既存のプリペアドステートメントを無条件に再使用せず、再準備の必要性を確認してください。 ```sql ALTER TABLE ch8_ddl RENAME TO ch8_product; SELECT id, product_code, status FROM ch8_product; ``` テーブル名の変更後は、ch8_productで検索します。 ## 全件削除とテーブル削除 ```sql BEGIN; TRUNCATE TABLE ch8_product; SELECT COUNT(*) AS during_delete FROM ch8_product; ROLLBACK; SELECT COUNT(*) AS after_rollback FROM ch8_product; DROP TABLE ch8_product; ``` 件数はそれぞれ0と1です。現在のTRANSACTIONのTRUNCATEは全行削除として処理され、明示的なトランザクション内でロールバックできます。 この動作をLOG・TAGのTRUNCATEに拡大して適用しないでください。 最後のDROPは、データ・定義・関連インデックスを削除します。 ## DDL運用上の注意事項 上記のTRUNCATEの動作と、CREATE・ALTER・DROPなどのスキーマ操作を区別する必要があります。 スキーマ変更をBEGIN内に置けば後でROLLBACKできるとは考えないでください。 同じテーブルのアクティブなトランザクションや開いているカーソルはDDLを妨げる場合があるため、先に結果セットと業務トランザクションを終了します。 ADD・DROP COLUMNはカタログと別の保存ファイルを併せて変更します。 処理中にサーバーが停止した場合は、再起動時の復旧が完了する前に同じDDLを繰り返さないでください。 復旧後にDESC、代表的なSELECT・INSERT、インデックス・VIEWを確認し、サーバーログも点検します。 内部保存ファイルを直接移動・変更・削除して復旧しようとしないでください。 予想と異なるスキーマが表示される場合は、変更前のDDL、実行順序、最初のエラーを併せて確認してください。 最後のエラーだけを見るより原因を特定しやすくなります。 --- title: "8.4 データ入力と変更" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/data-input-mutation/ language: ja kind: page --- # 8.4 データ入力と変更 UPDATEの成功応答と、注文1件が意図した状態に変わったことは別です。 条件に一致する行がなければ、エラーなしで0行が処理される場合があるためです。 変更前の対象、影響行数、変更後の値を併せて確認する習慣が必要です。 ## 条件付きUPDATEとDELETE ```sql CREATE TRANSACTION TABLE ch8_mutation ( order_id LONG PRIMARY KEY, amount DECIMAL(18,2), status VARCHAR(16), ordered DATETIME ); INSERT INTO ch8_mutation VALUES ( 1001, 19900.25, 'PENDING', TO_DATE('2026-01-01', 'YYYY-MM-DD')); INSERT INTO ch8_mutation VALUES ( 1002, 29900.50, 'CANCELLED', TO_DATE('2026-01-02', 'YYYY-MM-DD')); BEGIN; UPDATE ch8_mutation SET status = 'SHIPPED' WHERE order_id = 1001 AND status = 'PENDING'; SELECT order_id, status FROM ch8_mutation ORDER BY order_id; COMMIT; ``` 1001はSHIPPED、1002はCANCELLEDです。 同じUPDATEを再実行すると、PENDINGではないため影響行数は0です。 アプリケーションはSDKの影響行数を確認し、処理成功・処理済み・対象なしなどを業務規則に合わせて区別する必要があります。 次の削除も、対象件数を確認してからトランザクション内で実行します。 ```sql BEGIN; SELECT COUNT(*) AS delete_candidates FROM ch8_mutation WHERE status = 'CANCELLED'; DELETE FROM ch8_mutation WHERE status = 'CANCELLED'; SELECT order_id, amount, status FROM ch8_mutation ORDER BY order_id; COMMIT; ``` 対象は1行で、削除後は1001の1行だけが残ります。 WHEREのないUPDATE・DELETEは全行が対象です。 運用では事前SELECTと実際の変更の間に他のセッションがデータを変更し得るため、事前件数だけを成功の根拠にしないでください。 ## INSERT SELECTと自己参照 ```sql CREATE TRANSACTION TABLE ch8_archive ( order_id LONG PRIMARY KEY, amount DECIMAL(18,2), status VARCHAR(16), ordered DATETIME ); INSERT INTO ch8_archive(order_id, amount, status, ordered) SELECT order_id, amount, status, ordered FROM ch8_mutation WHERE ordered < TO_DATE('2026-02-01', 'YYYY-MM-DD'); INSERT INTO ch8_mutation(order_id, amount, status, ordered) SELECT order_id + 10000, amount, status, ordered FROM ch8_mutation WHERE order_id = 1001; SELECT order_id FROM ch8_archive ORDER BY order_id; SELECT order_id FROM ch8_mutation ORDER BY order_id; ``` アーカイブには1001、元テーブルには1001・11001があります。 自身のテーブルから読んだ結果を再挿入しても、この例では新しい行を無限に再入力することはありません。 ただし、キーを変えずにコピーすると一意性違反が起こり得ます。 出力先の列数と型を合わせ、コピー範囲を再実行可能な単位に分けてください。 通常の制約エラーと接続障害を同じ失敗として扱わないでください。 文の失敗はBEGIN全体を自動的にロールバックせず、コミット応答を失った場合は反映の有無を再検索する必要があります。 [トランザクション](../transaction/)で処理境界を説明します。 ```sql DROP TABLE ch8_archive; DROP TABLE ch8_mutation; ``` ## 大量取り込みとバッチ境界 TRANSACTIONもAppend APIをサポートしています。 古いファイル名やアンカーにreject・unsupportedが残っていることを理由に、現在も未サポートと判断しないでください。 言語別の公開APIは、[SDK機能のサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-append)を基準に選択します。 | 取り込み方式 | 確認基準 | |---|---| | SQL INSERT・プリペアド実行 | 文ごとのエラーと明示的トランザクション境界 | | ドライバーのbatch | 実際の送信単位、部分成功、自動コミット | | Append | SDKバッファ・サーバーバッチの境界、エラーコールバック・戻り値 | | machloader | マッピングと失敗行、処理区間の記録 | 現在のSQLCLI SQLAppendBatch処理は、別のアクティブなトランザクションがなければ、サーバーバッチをトランザクションとして扱います。 この処理の制約エラーの回帰検証では、失敗したバッチ全体がロールバックされます。 これを、すべてのSDKの論理バッチ、複数回のflush、Appenderの全ライフサイクルにわたる単一のアトミック操作と解釈しないでください。 AUTO_INCREMENTとDECIMALの取り込みでは、[SQLCLIとODBC](/ja/dbms/development-tools-integration/cli-odbc/)の専用規則も確認してください。 Appendプロトコルの到着時刻フィールドが、TRANSACTIONにLOGの自動時間列を作るわけではありません。 導入前には、正常行に重複キー・NULLエラーの行を1行混ぜ、成功・失敗件数と保存結果を確認してください。 ネットワークエラー後の再送では、コミット済みデータの重複処理も考慮する必要があります。 --- title: "8.5 クエリと分析" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/query-analysis/ language: ja kind: page --- # 8.5 クエリと分析 クエリの構文が正しくても、入力した状態値と条件が異なれば結果は0件になります。 ソート基準が不十分だと、同時刻の行が検索ごとに異なる順序で表示される場合もあります。 さまざまな状態と境界時刻を持つサンプルで、フィルター・ソート・集計を確認します。 ## 実習データの準備 ```sql CREATE TRANSACTION TABLE ch8_query ( order_id LONG PRIMARY KEY, customer VARCHAR(32), item_id LONG, amount DECIMAL(18,2), status VARCHAR(16), ordered DATETIME ); CREATE TRANSACTION TABLE ch8_query_product (id LONG PRIMARY KEY, name VARCHAR(64)); INSERT INTO ch8_query_product VALUES (42, 'Pump'); INSERT INTO ch8_query_product VALUES (43, 'Valve'); INSERT INTO ch8_query VALUES ( 1001, 'C-01', 42, 10.25, 'PENDING', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS')); INSERT INTO ch8_query VALUES ( 1002, 'C-01', 43, 20.50, 'PENDING', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS')); INSERT INTO ch8_query VALUES ( 1003, 'C-02', 42, 30.75, 'SHIPPED', TO_DATE('2026-01-02', 'YYYY-MM-DD')); SELECT order_id, amount, status FROM ch8_query WHERE order_id = 1001; ``` 1001・10.25・PENDINGが返されます。 ## 時間条件とソート ```sql SELECT order_id, amount FROM ch8_query WHERE ordered >= TO_DATE('2026-01-01', 'YYYY-MM-DD') AND ordered < TO_DATE('2026-01-02', 'YYYY-MM-DD') AND status = 'PENDING' ORDER BY ordered DESC, order_id DESC LIMIT 1; ``` 1002の1行が選択されます。orderedが同じでも、order_idで順序を固定しています。 LIMITだけを指定して意図した順序を期待しないでください。 連続する日別集計では、開始を含み終了を除く条件で境界の重複を避けられます。 LOG専用のDURATIONや自動_arrival_timeは、TRANSACTIONには適用しません。 ## マスターデータとの結合 ```sql SELECT o.order_id, p.name, o.amount FROM ch8_query o JOIN ch8_query_product p ON o.item_id = p.id WHERE o.customer = 'C-01' ORDER BY o.order_id; ``` 結果は(1001, Pump, 10.25)、(1002, Valve, 20.50)です。 このINNER JOINでは、対応するマスターデータがない注文は除外されます。 結合先に同じキーの行が複数あると結果が増えるため、キーの一意性も確認する必要があります。 他のタイプとの結合は[JOINの実習](../join-relational-query/)で説明します。 ## 集計クエリ ```sql SELECT status, COUNT(*) AS cnt, SUM(amount) AS total_amount FROM ch8_query GROUP BY status ORDER BY status; ``` PENDINGは2件・30.75、SHIPPEDは1件・30.75です。 インデックスがあっても、すべての集計が自動的に高速化するわけではありません。 範囲・グループ数・結果量を確認し、繰り返す業務では別途サマリーの作成を検討してください。 ## JSONパスのクエリ ```sql CREATE TRANSACTION TABLE ch8_query_json (id INTEGER PRIMARY KEY, state JSON); INSERT INTO ch8_query_json VALUES (1, '{"status":"ALARM","score":90}'); INSERT INTO ch8_query_json VALUES (2, '{"status":"NORMAL","score":10}'); INSERT INTO ch8_query_json VALUES (3, '{"score":20}'); SELECT id, state->'$.status' AS status FROM ch8_query_json WHERE state->'$.status' = 'ALARM' ORDER BY id; ``` 行1だけが選択されます。パスが存在しない行と、条件値が異なる行を区別してサンプルを用意してください。 矢印パスによる文字列比較と、数値抽出関数による比較を混同しないでください。 頻繁に使うパスには、[JSONパスインデックス](../index-performance/#index-strategy-rdb-json-path)を検討できます。 ## インデックスと実行計画 ```sql CREATE INDEX ch8_query_status_time ON ch8_query(status, ordered); EXPLAIN SELECT order_id FROM ch8_query WHERE status = 'PENDING' AND ordered >= TO_DATE('2026-01-01', 'YYYY-MM-DD'); ``` 複合インデックスの先頭列と条件を合わせ、実際の使用はEXPLAINで確認してください。 Machbaseがリレーショナルクエリ全体を内部SQLiteにそのまま渡すと考えると、インデックス選択や関数条件を誤解する場合があります。 ```sql DROP TABLE ch8_query_json; DROP TABLE ch8_query_product; DROP TABLE ch8_query; ``` 結果が異なる場合は、集計やJOINを複雑に分析する前に、元の件数、WHERE条件、ソート基準を順に確認してください。 --- title: "8.6 インデックスとパフォーマンス" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/index-performance/ language: ja kind: page --- # 8.6 インデックスとパフォーマンス インデックスは検索速度だけでなく、データの一意性も決定する場合があります。 業務キーを保証するインデックスと読み取り量を減らすインデックスを区別し、性能調整中に必要な制約を誤って削除しないようにします。 ## インデックスの種類 | 種類 | 用途 | 複合列 | NULL | |---|---|---|---| | PRIMARY KEY | 行の識別。テーブルごとに1つ | 未サポート | 不可 | | UNIQUE INDEX | 業務キーの一意性 | サポート | NULLを含むキー同士は重複ではない | | 一般インデックス | 条件検索のアクセス経路 | サポート | 一意性検査なし | TRANSACTIONのインデックスはBTREEと表示されます。 列のPRIMARY KEY、または作成後のCREATE PRIMARY KEY INDEXを使用できます。 LOGのLSM・KEYWORDインデックス構文を、TRANSACTIONにそのまま適用しないでください。 ## UNIQUE INDEXとNULL ```sql CREATE TRANSACTION TABLE ch8_index_account ( id LONG PRIMARY KEY, email VARCHAR(120), tenant INTEGER NOT NULL, login VARCHAR(64) ); INSERT INTO ch8_index_account VALUES (1, 'a@example.com', 1, 'alpha'); INSERT INTO ch8_index_account VALUES (2, 'b@example.com', 1, 'beta'); INSERT INTO ch8_index_account VALUES (3, NULL, 2, NULL); INSERT INTO ch8_index_account VALUES (4, NULL, 2, NULL); CREATE UNIQUE INDEX ch8_index_email ON ch8_index_account(email); CREATE UNIQUE INDEX ch8_index_login ON ch8_index_account(tenant, login); SELECT id FROM ch8_index_account WHERE email IS NULL ORDER BY id; SHOW INDEX ch8_index_email; ``` 行3と4は両方存在し、インデックスも作成されます。 値が必須の業務キーでは、UNIQUEに加えて各列のNOT NULLも必要です。 CREATE TABLE内にUNIQUEを付けず、別のCREATE UNIQUE INDEXを使用してください。 次の2文は、それぞれ一意性違反を確認する任意の実習です。 ```sql -- 意図的に失敗: emailの重複 INSERT INTO ch8_index_account VALUES (5, 'a@example.com', 1, 'gamma'); UPDATE ch8_index_account SET email = 'a@example.com' WHERE id = 2; ``` 失敗後も4行と、行2のb@example.comが保持される必要があります。 現在、一般的なUNIQUE違反はERR-01418として報告されます。 エラーメッセージだけでどの業務キーが重複したかを断定せず、インデックスと入力値を併せて確認してください。 ## UNIQUE INDEXの削除 ```sql DROP INDEX ch8_index_email; INSERT INTO ch8_index_account VALUES (5, 'a@example.com', 1, 'gamma'); SELECT id, email FROM ch8_index_account WHERE email = 'a@example.com' ORDER BY id; ``` これで行1と5が両方保存されます。 重複がある状態でインデックスを再作成すると失敗します。 ```sql -- 意図的に失敗: 既存データに重複があります。 CREATE UNIQUE INDEX ch8_index_email ON ch8_index_account(email); ``` 実習で追加した行5を削除してから、再作成します。 ```sql DELETE FROM ch8_index_account WHERE id = 5; CREATE UNIQUE INDEX ch8_index_email ON ch8_index_account(email); SELECT COUNT(*) AS remaining_rows FROM ch8_index_account; ``` 件数は4です。 運用ではインデックスを削除する前に、性能用か一意性保証用かを確認する必要があります。 ## 一般・複合インデックス ```sql CREATE TRANSACTION TABLE ch8_index_event ( id LONG PRIMARY KEY, status VARCHAR(16), created DATETIME, state JSON ); INSERT INTO ch8_index_event VALUES ( 1, 'OPEN', TO_DATE('2026-01-01', 'YYYY-MM-DD'), '{"status":"ALARM","code":500}'); INSERT INTO ch8_index_event VALUES ( 2, 'CLOSED', TO_DATE('2026-01-02', 'YYYY-MM-DD'), '{"status":"NORMAL","code":200}'); INSERT INTO ch8_index_event VALUES ( 3, 'OPEN', TO_DATE('2026-01-03', 'YYYY-MM-DD'), '{"code":500}'); EXPLAIN SELECT id FROM ch8_index_event WHERE status = 'OPEN' AND created >= TO_DATE('2026-01-01', 'YYYY-MM-DD'); CREATE INDEX ch8_index_status_time ON ch8_index_event(status, created); EXPLAIN SELECT id FROM ch8_index_event WHERE status = 'OPEN' AND created >= TO_DATE('2026-01-01', 'YYYY-MM-DD'); SELECT id FROM ch8_index_event WHERE status = 'OPEN' AND created >= TO_DATE('2026-01-01', 'YYYY-MM-DD') ORDER BY id; ``` 結果の意味は作成前後で同じである必要があり、最後のクエリは行1と3を返します。 先頭列を条件に合わせますが、すべての複合条件が必ずそのインデックスを使用するとは断定しないでください。 Machbaseの計画選択とサポートされる条件形式をEXPLAINで確認します。 3行の実行時間は性能ベンチマークではありません。 ## JSONパスインデックス ```sql CREATE INDEX ch8_index_json_status ON ch8_index_event(state->'$.status'); CREATE INDEX ch8_index_json_code ON ch8_index_event(state->'$.code'); EXPLAIN SELECT id FROM ch8_index_event WHERE state->'$.status' = 'ALARM'; SELECT id FROM ch8_index_event WHERE state->'$.status' = 'ALARM' ORDER BY id; SELECT id FROM ch8_index_event WHERE state->'$.code' = '500' ORDER BY id; ``` 状態検索は行1、code検索は行1と3を返します。 インデックスを作成しても、すべてのJSON関数式がこの経路を使用するわけではありません。 矢印パスと数値抽出関数は、結果型と比較の意味を区別してください。 複雑な条件を頻繁に繰り返す場合は、通常の列に分離する設計も比較できます。 JSONパスのUNIQUE INDEXを作成できる場合でも、TRANSACTION UPSERTの競合選択キーには使用しません。 [UPSERTの制約](../insert-on-duplicate-key-update/)を確認してください。 ## 読み取り・書き込みコスト インデックス作成前後では、同じデータ量・条件値・同時入力レートを使用してください。 クエリ時間だけでなく、INSERT・UPDATE・DELETEのスループットとインデックス容量も比較します。 LIMITは結果量を減らしますが、返す行を固定するにはORDER BYが必要です。 ```sql DROP TABLE ch8_index_event; DROP TABLE ch8_index_account; ``` 性能のためにUNIQUE INDEXを一般インデックスに変更すると、一意性の保証は失われます。 チューニング前後で結果と制約が同じであることを、先に確認してください。 --- title: "8.7 運用とデータライフサイクル" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/operations-lifecycle/ language: ja kind: page --- # 8.7 運用とデータライフサイクル 古い業務データを削除するときは、日付だけの確認では不十分です。 キャンセル済みの注文と処理中の注文では保持基準が異なり、削除処理自体も他の書き込みと競合し得ます。 業務条件と処理単位を先に決めてから削除してください。 ## データの保持基準 TAG・LOGには元の時系列データ、TRANSACTIONには変更可能な状態や要約結果を格納できます。 両方の保持期間が同じである必要はありません。 TRANSACTIONにはTAG・LOGのRetention Policyをそのまま適用しません。 業務条件に適したDELETEと外部ジョブスケジュールを設計してください。 ## 削除とロールバック ```sql CREATE TRANSACTION TABLE ch8_cleanup ( id LONG PRIMARY KEY, status VARCHAR(16), created DATETIME ); INSERT INTO ch8_cleanup VALUES (1, 'CANCELLED', TO_DATE('2025-12-01', 'YYYY-MM-DD')); INSERT INTO ch8_cleanup VALUES (2, 'PENDING', TO_DATE('2025-12-01', 'YYYY-MM-DD')); INSERT INTO ch8_cleanup VALUES (3, 'CANCELLED', TO_DATE('2026-02-01', 'YYYY-MM-DD')); BEGIN; SELECT COUNT(*) AS delete_candidates FROM ch8_cleanup WHERE status = 'CANCELLED' AND created < TO_DATE('2026-01-01', 'YYYY-MM-DD'); DELETE FROM ch8_cleanup WHERE status = 'CANCELLED' AND created < TO_DATE('2026-01-01', 'YYYY-MM-DD'); SELECT id, status FROM ch8_cleanup ORDER BY id; ROLLBACK; SELECT COUNT(*) AS after_rollback FROM ch8_cleanup; ``` 対象は1件で、削除中は行2・3、ロールバック後は3件です。 確認用の実習ではロールバックしていますが、運用で確定する場合は業務承認と結果確認後にCOMMITを選択します。 結果カーソルは終了前に閉じる必要があります。 事前の検索件数と実際の影響行数を同じものと見なさないよう注意してください。 同時変更とスナップショット競合を考慮し、実行時に得た影響行数と最終状態まで記録してください。 [ロックと再試行](../locking-conflict-timeout/)で関連する状況を確認できます。 ## バッチ処理と再開 削除全体を1つの長いトランザクションで処理するより、日付区間や一意キー範囲で分割してください。 各区間の境界、処理件数、コミット結果を記録します。 途中の障害後に、どこから処理を再開するか分かる必要があります。 マスターデータの移動で、他のテーブルへコピーしてから元データを削除する場合も注意が必要です。 現在、障害時に複数のTRANSACTIONテーブルのアトミックコミットが保証されるとは考えないでください。 [トランザクションの保証範囲](../transaction/)に合わせてコピー結果の確認と再開手順を設計します。 外部API呼び出しや長いファイル処理をBEGIN内で待たないことも重要です。 ## バックアップの検証 バックアップコマンドの成功だけでなく、マウントしたバックアップで業務キー・行数・合計・インデックスを点検してください。 マウントしたデータの検索には、`マウント名.所有者.テーブル名`の3部構成の名前を使用します。 2部構成の名前を使い、本番データと混同しないでください。 TRANSACTIONは、増分バックアップでもその時点のテーブルストレージ全体のスナップショットを含みます。 変更行数に比例してだけ容量が増えると計算しないでください。 具体的な実習は[バックアップ・リストア・マウント](../backup-restore-mount/)にあります。 ## 削除後の運用点検 行数が減っても、OS上のファイルサイズが直ちに同じ割合で減るわけではありません。 業務データの件数、実際のファイル使用量、バックアップ保持量を個別に確認してください。 ファイルサイズを減らすために、内部SQLiteファイルへ直接接続したり、ファイルを任意に削除したりしないでください。 ```sql DROP TABLE ch8_cleanup; ``` 削除処理が失敗したら、追加削除を試す前に、最後に成功した区間とコミット結果を確認してください。 これらの記録が、データの欠落と重複処理を減らすために必要です。 --- title: "8.8 制約、エラー、トラブルシューティング" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/constraints-errors-troubleshooting/ language: ja kind: page --- # 8.8 制約、エラー、トラブルシューティング 他のRDBMSのSQLを移行するときは、名前が似ていることを理由に同じ機能を期待しがちです。 まずEditionと公開構文を確認し、次にデータ制約と同時アクセスの問題を分けて調べてください。 ## 機能のサポート範囲 TRANSACTIONはStandard Edition専用です。 ClusterではCREATE TABLE・CREATE TRANSACTION TABLE・CREATE TXN TABLEはすべて拒否されます。 LOGはCREATE LOG TABLEで明示する必要があります。 | 要求 | 対応・代替方法 | |---|---| | 一般的なSELECT・INSERT・UPDATE・DELETE | サポート。WHEREなしの変更は全行が対象 | | 単一のPRIMARY KEY | サポート。テーブルごとに1つ | | 単一・複合UNIQUE INDEX | サポート。テーブル作成後に別途作成 | | 列の後のUNIQUE・テーブルレベルPRIMARY KEY | 該当する作成構文は未サポート | | FOREIGN KEY・Trigger・Stored Procedure | 未サポート | | BEGIN・COMMIT・ROLLBACK | サポート。ネストしたBEGIN・SAVEPOINTは未サポート | | ADD・DROP・RENAME COLUMN、RENAME TO | サポート条件を確認 | | MODIFY COLUMN | 未サポート | | Append | SDK別の公開手段とバッチ境界を確認 | | TAGのMETADATA・BASETIME・BASEDISTANCE | TRANSACTIONには適用しない | Clusterで小規模なマスターデータを変更する場合はLOOKUPを検討できますが、明示的なリレーショナルトランザクションの完全な代替ではありません。 元のイベントはLOG・TAG、リレーショナルトランザクションは別のRDBMSなど、要件に応じて分ける必要があります。 ## エラー別の診断 | 症状 | 確認箇所 | 次の対処 | |---|---|---| | ERR-01418 一意性違反 | PK・UNIQUEキーと既存データ | 入力修正またはUPSERT規則の確認 | | NOT NULL違反 | 省略・NULL・空文字列・DEFAULT | 入力値と制約を確認 | | UPDATEの処理が0行 | キーと現在状態の条件 | 対象なし・処理済みなどの業務状態を確認 | | Resource busy | 他の書き込み、古い読み取りスナップショット、開いたカーソル | 原因に応じて待機・新規トランザクション・カーソル終了 | | COMMIT・ROLLBACKがbusy | 同じ接続の開いた結果セット | 結果セットを閉じて終了を再試行 | | エラー後の後続SQLも拒否 | ロールバック専用状態か | ROLLBACK後に新しい処理を開始 | | DDL失敗 | 参照インデックス・VIEW・アクティブなトランザクション | 依存関係と変更タイミングを調整 | | マウント先の値が予想と異なる | マウント名・所有者・テーブル名 | 本番データとバックアップデータを区別 | 同じResource busyでも、再試行の方法は異なります。 2接続による詳細な実習は、[ロックとbusy timeout](../locking-conflict-timeout/)を参照してください。 エラー文字列にTRANSACTIONがあることだけを理由に、繰り返し実行しないでください。 ## 制約エラーとデータ保持 ```sql CREATE TRANSACTION TABLE ch8_error ( id LONG PRIMARY KEY, code VARCHAR(32) NOT NULL, value INTEGER ); CREATE UNIQUE INDEX ch8_error_code ON ch8_error(code); INSERT INTO ch8_error VALUES (1, 'A', 10); ``` 以下は、それぞれ意図的に失敗する任意の実習です。 正常なSQLとまとめず、確認する文だけを実行してください。 ```sql -- PRIMARY KEYの重複 INSERT INTO ch8_error VALUES (1, 'B', 20); -- UNIQUEの重複 INSERT INTO ch8_error VALUES (2, 'A', 20); -- 必須値の違反 INSERT INTO ch8_error VALUES (3, NULL, 30); -- 未サポートのスキーマ変更 ALTER TABLE ch8_error MODIFY COLUMN (code VARCHAR(64)); ``` ```sql SELECT id, code, value FROM ch8_error ORDER BY id; DROP TABLE ch8_error; ``` 最後のクエリには(1, A, 10)だけが残ります。 単一文の失敗で状態が保持されることと、BEGIN内で先に成功した文まで自動的に取り消されるわけではないことを区別する必要があります。 [トランザクション](../transaction/)に比較例があります。 ## 診断情報の収集 サーバーバージョン・Edition、DDLとインデックス、実行SQL、エラーコードとメッセージ全文、実際の影響行数を併せて用意してください。 接続障害では、COMMITの要求・応答時刻と業務キーも必要です。 パスワード・個人情報・機密の業務値を伏せ、再現に必要な最小限のサンプルだけを共有してください。 復旧のために内部保存ファイルを直接変更したり、本番テーブルを再作成したりしないでください。 先に原因と反映状態を確認することが、データ損失の低減につながります。 --- title: "8.9 トランザクション" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/transaction/ language: ja kind: page --- # 8.9 トランザクション 複数のSQLを実行中に途中の文が失敗すると、それまでの変更も消えたと考えがちです。 しかし、通常の制約エラーでは、失敗した文とトランザクション全体を区別して処理します。 この節では、同じテーブル内の変更でCOMMIT・ROLLBACKの境界を先に確認します。 ## トランザクションの実行 ```sql CREATE TRANSACTION TABLE ch8_tx ( item_id LONG PRIMARY KEY, qty INTEGER NOT NULL ); INSERT INTO ch8_tx VALUES (1, 10); INSERT INTO ch8_tx VALUES (2, 20); BEGIN; UPDATE ch8_tx SET qty = qty - 3 WHERE item_id = 1 AND qty >= 3; UPDATE ch8_tx SET qty = qty + 3 WHERE item_id = 2; SELECT item_id, qty FROM ch8_tx ORDER BY item_id; ROLLBACK; SELECT item_id, qty FROM ch8_tx ORDER BY item_id; ``` トランザクション内では7・23、ROLLBACK後は10・20が返されます。 アプリケーションは、2つのUPDATEがそれぞれ想定した1行を処理したことを確認する必要があります。 条件不一致で更新が0行になるのはSQLエラーではないため、データベースが業務失敗を自動判定することはありません。 次は同じ変更を確定する通常の実習です。 ```sql BEGIN; UPDATE ch8_tx SET qty = qty - 3 WHERE item_id = 1 AND qty >= 3; UPDATE ch8_tx SET qty = qty + 3 WHERE item_id = 2; COMMIT; SELECT item_id, qty FROM ch8_tx ORDER BY item_id; ``` 確定後の値は7・23です。 公開構文はBEGINであり、BEGIN TRANSACTION、ネストしたBEGIN、SAVEPOINTはサポートしていません。 明示的なトランザクションがなければ、TRANSACTIONのDMLは文単位で処理されます。 ドライバーの自動コミット・トランザクションAPIは別途確認してください。 ## 文のエラーとロールバック 次はエラー処理を学ぶための流れです。重複INSERTは意図的に失敗します。 SQL実行ツールがエラーで停止した場合は、必ず同じ接続でROLLBACKまで実行してください。 ```sql BEGIN; UPDATE ch8_tx SET qty = 100 WHERE item_id = 1; ``` ```sql -- 意図的に失敗: item_idの重複 INSERT INTO ch8_tx VALUES (1, 999); ``` ```sql SELECT item_id, qty FROM ch8_tx ORDER BY item_id; ROLLBACK; SELECT item_id, qty FROM ch8_tx ORDER BY item_id; ``` 最初の検索結果は100・23、ROLLBACK後は7・23です。 通常の制約エラーで失敗した文が取り消されても、先に成功した文はトランザクション内に残ります。 業務全体を取り消すには、アプリケーションがROLLBACKを選ぶ必要があります。 すべてのエラー後に続行できるわけではありません。復旧処理でロールバック専用状態になった場合は、ROLLBACKで終了する必要があります。 ## TRUNCATEとロールバック ```sql BEGIN; TRUNCATE TABLE ch8_tx; SELECT COUNT(*) AS during_truncate FROM ch8_tx; ROLLBACK; SELECT COUNT(*) AS after_rollback FROM ch8_tx; ``` 結果は0と2です。 現在のTRANSACTIONのTRUNCATEは全行削除として、明示的トランザクションに含まれます。 LOG・TAGのデータ削除や、CREATE・ALTER・DROPなどのスキーマ変更と混同しないでください。 スキーマ操作は業務トランザクションの外で行うことが運用基準です。 ## テーブルタイプ別のトランザクション範囲 アクティブなTRANSACTIONトランザクション内でも、LOG・TAG・LOOKUP・VOLATILEの検索と混合結合は許可されます。 一方、これらのタイプへの書き込みを同じトランザクションにまとめることはできません。 検索が許可されても、そのタイプがTRANSACTIONと同じスナップショット・ロールバック保証を得るわけではありません。 元データの収集と業務状態の変更の間の整合性は、別途設計してください。 TRANSACTIONテーブルの読み取りには、他のセッションの未コミット変更が見えないスナップショットを使用します。 BEGIN呼び出し時に、すべてのテーブルで共通の読み取り時点が一括で固定されるとは考えないでください。 読み取りから書き込みへの移行時の競合は、[ロックと再試行](../locking-conflict-timeout/)で説明します。 ## 複数テーブルのコミットと障害 複数のTRANSACTIONテーブルのDMLをBEGINでまとめ、通常どおりCOMMIT・ROLLBACKすることはできます。 ただし、現在のストレージはテーブルごとにハンドルを使用し、COMMITもハンドルごとに順次処理します。 したがって、コミット中に障害が発生しても、複数テーブル全体が必ず一緒に確定または取り消されるアトミックコミットを保証すると解釈しないでください。 複数テーブルの不可分な処理が必須の業務では、この制限を先に検討してください。 コミット失敗や応答消失後にROLLBACKを送信したことだけで、すべてのテーブルが元に戻ったと判断せず、 業務キーで反映状態を再確認する必要があります。 この節の基本実習を1つのテーブルの2行で構成したのも、このためです。 ## カーソルとトランザクション終了 開いているTRANSACTIONカーソルがある場合、COMMIT・ROLLBACKがResource busyで失敗することがあります。 SDKの結果セット・ステートメントを終了してから、終了文を再実行してください。 接続終了時に未コミット変更はロールバックされますが、接続を失う前にサーバーですでにコミットされたかどうかは、クライアントが別途確認する必要があります。 ```sql DROP TABLE ch8_tx; ``` BEGIN内で外部API呼び出しや長い計算を待たないでください。 トランザクションを短く保ち、失敗時に再実行するのか、先に結果を確認するのかを区別すると、運用中の判断が明確になります。 --- title: "8.10 ロック、競合、busy timeout" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/locking-conflict-timeout/ language: ja kind: page --- # 8.10 ロック、競合、busy timeout 別々の行を変更しているのにResource busyが発生する場合、行ロックだけを考えると原因を特定しにくくなります。 TRANSACTIONの書き込み競合は、同じテーブルの異なる行の間でも発生し得ます。 待てば解消する競合と、トランザクションを再開始する必要がある競合を区別します。 ## 実習環境 この実習は、デフォルトのWAL設定を使用する検証用Standard環境を対象とします。 A・Bは同じアカウント・データベースに接続した別々の接続です。 各コードブロックを示した順に実行し、SELECT結果は最後まで読み取ってカーソルを閉じてください。 スナップショット実習のために、本番サーバーのジャーナルモードを変更しないでください。 Aで準備します。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME = 'TRANSACTION_JOURNAL_MODE'; CREATE TRANSACTION TABLE ch8_lock (id INTEGER PRIMARY KEY, val INTEGER); INSERT INTO ch8_lock VALUES (1, 10); INSERT INTO ch8_lock VALUES (2, 20); ``` TRANSACTION_JOURNAL_MODE=4がWALです。 他の値の場合は、次のWALスナップショット実習と同じ結果を期待せず、環境を先に確認してください。 ## 同時書き込みの競合 Aでトランザクションを開始し、終了せずに待ちます。 ```sql BEGIN; UPDATE ch8_lock SET val = 11 WHERE id = 1; ``` 続いてBで検索します。実習用のB接続だけ、待機時間を0に変更します。 ```sql ALTER SESSION SET TRANSACTION_BUSY_TIMEOUT_MS = 0; SELECT id, val FROM ch8_lock ORDER BY id; ``` Bには、Aの未コミット値11ではなく、既存値10・20が見えます。 次のBのUPDATEは、意図的にResource busyエラーを発生させる段階です。 ```sql -- B: Aとは異なる行でも、同じテーブルへの書き込みのため失敗が想定されます。 UPDATE ch8_lock SET val = val + 1 WHERE id = 2; ``` AでCOMMITしてから、BのUPDATEを再実行します。 ```sql -- A COMMIT; ``` ```sql -- B UPDATE ch8_lock SET val = val + 1 WHERE id = 2; SELECT id, val FROM ch8_lock ORDER BY id; ``` 値は11・21になります。 これは、同じテーブルの書き込み競合を一般的な行単位ロックと解釈してはいけないことを示します。 ## WALスナップショット競合 前の手順がすべて完了したら、Aで読み取りトランザクションを開始します。 ```sql -- A BEGIN; SELECT val FROM ch8_lock WHERE id = 1; ``` Aが11を読み取った後、Bで値を変更します。Bには明示的なトランザクションがない状態です。 ```sql -- B UPDATE ch8_lock SET val = val + 10 WHERE id = 1; ``` 続いてAが書き込みに移行すると、スナップショット競合が想定されます。 ```sql -- A: 意図的に失敗する段階 UPDATE ch8_lock SET val = val + 1 WHERE id = 1; ``` 別の接続がすでにコミットしたため、Aの古い読み取りスナップショットをそのまま書き込みに移行できません。 現在、この競合はbusy timeoutを延長したり-1に設定したりしても、待機では解決しません。 同じUPDATEだけを繰り返さず、Aのトランザクションを終了して新しい状態で再判断します。 ```sql -- A ROLLBACK; BEGIN; UPDATE ch8_lock SET val = val + 1 WHERE id = 1; COMMIT; SELECT id, val FROM ch8_lock ORDER BY id; ``` 最終値は22・21です。 業務で読み取った値を使って次の変更を計算した場合は、新しいトランザクションで読み取りと判断からやり直す必要があります。 ## busy timeout サーバーのデフォルトのTRANSACTION_BUSY_TIMEOUT_MSは30000msで、新しいセッションにコピーされます。 現在のセッションではALTER SESSIONで変更できます。 | 値 | 一時的なロック競合の処理 | |---|---| | -1 | キャンセル・接続終了またはロック解放まで待機 | | 0 | 待機せずbusyを返す | | 正数 | 指定ミリ秒の範囲内で待機し、処理するかbusyを返す | スナップショット移行競合のように、再試行で解消できない場合はこのポリシーの例外です。 -1をすべての競合に対する無限再試行と解釈しないでください。 DDL_LOCK_TIMEOUTは別のDDLロック待機設定で、変更してもスナップショット競合は解決しません。 ## エラーと再試行 メッセージにTRANSACTIONがあることだけで再試行すると、型・制約・権限エラーまで繰り返してしまいます。 ドライバーのエラーコード、診断全文、操作の種類を併せて確認し、再試行可能なロック競合かを区別してください。 明示的なトランザクションで再試行するには、開いている結果セットを閉じてROLLBACKした後、 回数と要求全体の時間に上限を設け、新しいトランザクションで再実行します。 接続消失やCOMMIT応答の消失は別のケースです。 業務キーで処理済みかを確認せず、カウンター増加や注文処理を再実行すると、重複して反映される場合があります。 ## 競合の診断 ```sql SELECT id, user_name, user_ip, transaction_busy_timeout_ms FROM V$SESSION WHERE closed = 0 ORDER BY id; SELECT id, sess_id, state, query FROM V$STMT WHERE state LIKE 'Execute in progress%' OR state LIKE 'Fetch in progress%'; ``` このクエリはロック所有者を直接対応付けるものではありません。 V$MUTEXもサーバー内部のミューテックス統計であり、業務行のロック一覧ではありません。 接続情報とアプリケーションのBEGIN・終了記録を併せて確認してください。 セッションの強制終了は未コミット業務を取り消す場合があるため、最初の対処にはしないでください。 両方の接続に開いたトランザクションがないことを確認してから、Aでクリーンアップします。 ```sql DROP TABLE ch8_lock; ``` 実習用接続A・Bを終了すると、Bに指定したセッション単位のtimeoutも影響しなくなります。 運用では、外部API呼び出しや長い計算をBEGINの外へ移すだけでも、待機の原因を減らせます。 --- title: "8.11 JOINとリレーショナルクエリの設計" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/join-relational-query/ language: ja kind: page --- # 8.11 JOINとリレーショナルクエリの設計 JOINを追加して注文件数が減少・増加した場合は、まず関係の形を確認する必要があります。 INNER JOINは対応する行がない行を除外し、1件に複数の行が一致すると結果を増やします。 SQLがエラーなしで実行されることと、業務件数を正しく集計することは別です。 ## TRANSACTION–LOOKUP結合 ```sql CREATE TRANSACTION TABLE ch8_join_order ( order_id LONG PRIMARY KEY, item_id LONG, qty INTEGER ); CREATE LOOKUP TABLE ch8_join_product (id LONG PRIMARY KEY, name VARCHAR(64)); CREATE TRANSACTION TABLE ch8_join_payment (order_id LONG PRIMARY KEY, status VARCHAR(16)); INSERT INTO ch8_join_order VALUES (1, 42, 2); INSERT INTO ch8_join_order VALUES (2, 99, 1); INSERT INTO ch8_join_product VALUES (42, 'Pump'); INSERT INTO ch8_join_payment VALUES (1, 'PAID'); SELECT o.order_id, p.name, o.qty FROM ch8_join_order o JOIN ch8_join_product p ON o.item_id = p.id ORDER BY o.order_id; SELECT o.order_id, p.name, o.qty FROM ch8_join_order o LEFT JOIN ch8_join_product p ON o.item_id = p.id ORDER BY o.order_id; ``` INNER JOINは注文1だけ、LEFT JOINは注文1・2を返します。 注文2の製品名はNULLです。製品99が存在しなくても、注文の入力自体は外部キーで拒否されないため、必要な参照検証は別途設計する必要があります。 LEFT JOIN後に右側テーブルの条件をWHEREに指定しないよう注意してください。 例えば`WHERE p.name = 'Pump'`を追加すると、NULL行が除外されます。 結合先を探す条件なのか、最終結果をフィルタリングする条件なのかを区別してください。 ## TRANSACTION間の結合 ```sql SELECT o.order_id, o.qty, p.status FROM ch8_join_order o JOIN ch8_join_payment p ON o.order_id = p.order_id ORDER BY o.order_id; ``` (1, 2, PAID)の1行が返されます。 実際の支払い履歴が注文ごとに複数行あれば、この結果も複数行になります。 結合後に注文金額を合計するとき、重複集計を避けるために関係と集計単位を確認してください。 ## TAGの近接時刻結合 次は、アラームの前後5秒以内にあるすべての測定値を結合する例です。 ```sql CREATE TRANSACTION TABLE ch8_join_alarm ( alarm_id LONG PRIMARY KEY, sensor VARCHAR(32), occurred DATETIME ); CREATE TAG TABLE ch8_join_sensor ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); INSERT INTO ch8_join_alarm VALUES ( 1, 'TEMP-01', TO_DATE('2026-01-01 10:00:05', 'YYYY-MM-DD HH24:MI:SS')); INSERT INTO ch8_join_sensor VALUES ( 'TEMP-01', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10); INSERT INTO ch8_join_sensor VALUES ( 'TEMP-01', TO_DATE('2026-01-01 10:00:10', 'YYYY-MM-DD HH24:MI:SS'), 20); INSERT INTO ch8_join_sensor VALUES ( 'TEMP-01', TO_DATE('2026-01-01 10:00:11', 'YYYY-MM-DD HH24:MI:SS'), 30); SELECT a.alarm_id, s.time, s.value FROM ch8_join_alarm a JOIN ch8_join_sensor s ON a.sensor = s.name WHERE s.time >= a.occurred - 5s AND s.time <= a.occurred + 5s ORDER BY a.alarm_id, s.time; ``` アラーム1に値10・20の2行が結合されます。両側の境界を含み、値30は除外されます。 このクエリは最も近い測定値1つや、完全に同じ時刻の値を選ぶ機能ではありません。 1つの値だけが必要なら、直前値・最短距離などの選択基準と同順位の処理規則を別途定めてください。 ## 結合の設計基準 結合キーの型と値の形式を合わせ、時間範囲を制限してから実行計画を確認します。 必要な列だけを返し、結合キーへの不用意な関数・型変換の追加でアクセス経路が変わらないか比較してください。 結合順序やアルゴリズムが他のRDBMSと同じだと考えないでください。 混合結合が許可されても、他のテーブルタイプがTRANSACTIONと同じトランザクションスナップショットを共有するわけではありません。 また、現在のLOOKUPの説明を付加しても、過去の時点の説明までは再現しません。 ```sql DROP TABLE ch8_join_sensor; DROP TABLE ch8_join_alarm; DROP TABLE ch8_join_payment; DROP TABLE ch8_join_product; DROP TABLE ch8_join_order; ``` 結果件数が一致しない場合は、結合前の件数とキーごとの結合先行数を先に比較してください。 この2つが確認できると、クエリの修正方法も明確になります。 --- title: "8.12 TRANSACTIONのバックアップ、リストア、マウント" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/backup-restore-mount/ language: ja kind: page --- # 8.12 TRANSACTIONのバックアップ、リストア、マウント バックアップコマンドに成功しても、復旧の準備が完了したとは限りません。 特に本番テーブルとバックアップテーブルが同名だと、誤った方を検索して検証完了と考えがちです。 バックアップ後に本番の値を変更し、両方の結果が異なることを確認する方法で検証します。 ## バックアップ・リストアのサポート範囲 | 操作 | TRANSACTIONに関する基準 | |---|---| | BACKUP DATABASE | 対象範囲の永続的なTRANSACTIONデータを含む | | BACKUP TABLE | 指定テーブルと必要なメタデータをバックアップ | | 増分バックアップ | TRANSACTIONストレージは、その時点の全体スナップショットとして含まれる | | MOUNT DATABASE | バックアップを読み取り専用で検索 | | オフラインインスタンス復旧 | サーバーを停止しmachadmin -rを使用 | | オンライン論理データベース復旧 | サポートされる論理バックアップをRESTORE DATABASEで復元 | 増分バックアップのTRANSACTIONデータを、変更行だけの差分として見積もらないでください。 内部ファイルの直接コピーではなく、サポートされるバックアップコマンドを使用する必要があります。 TRANSACTIONを含むバックアップを、Clusterで使用するための迂回手段にすることもできません。 ## バックアップとマウントの検証 この実習は、検証用Standard環境のSYSアカウントを対象にします。 バックアップ・マウント権限と、サーバーファイルへのアクセス権限が必要です。 パスはサーバー上の例であり、実行するたびに存在しない新しいパスに変更してください。 親ディレクトリと空き容量を確認し、パスを再使用するために既存のバックアップを削除しないでください。 ```sql CREATE TRANSACTION TABLE ch8_backup ( id LONG PRIMARY KEY, code VARCHAR(32) NOT NULL, amount DECIMAL(18,2) ); CREATE UNIQUE INDEX ch8_backup_code ON ch8_backup(code); INSERT INTO ch8_backup VALUES (1, 'A', 10.25); INSERT INTO ch8_backup VALUES (2, 'B', 20.50); BACKUP TABLE ch8_backup INTO DISK = '/backup/ch8_table_20260907_a'; UPDATE ch8_backup SET amount = 99.00 WHERE id = 1; MOUNT DATABASE '/backup/ch8_table_20260907_a' TO ch8_bak; SELECT id, code, amount FROM ch8_bak.SYS.ch8_backup ORDER BY id; SELECT id, code, amount FROM ch8_backup ORDER BY id; ``` バックアップ側は10.25・20.50、本番側は99.00・20.50です。 マウントしたデータの検索には、`マウント名.所有者.テーブル名`の3部構成の名前を使用します。 別の所有アカウントで実習した場合は、SYSも実際の所有者に合わせる必要があります。 `SELECT ... FROM ch8_backup`だけを実行しないよう注意してください。 これはマウントしたバックアップの検証ではなく、現在の接続の本番テーブルを検索します。 バックアップに含めなかった他のテーブルも存在するはずだと期待しないでください。 マウントは読み取り専用であり、UPDATE・DDLを行う復旧環境ではありません。 検証を終え、開いているカーソルを閉じてからマウントを解除します。 ```sql UMOUNT DATABASE ch8_bak; DROP TABLE ch8_backup; ``` このクリーンアップは、実習テーブルとマウントだけを削除します。 バックアップディレクトリは残るため、以後の保持ポリシーに従って別途管理してください。 ## リストアの検証項目 隔離した復旧環境では、所有者、行数、業務キー、金額合計、代表的なJSON値を確認してください。 PRIMARY KEY・UNIQUE INDEXが残っているか、必要な権限とアプリケーションのCOMMIT・ROLLBACKの流れが正常かも点検します。 マウント検索だけでは、実際の書き込み復旧の検証まで完了したことにはなりません。 オンラインRESTORE DATABASEは、論理バックアップと対象データベースの条件に従います。 複数のデータベースを含むインスタンス全体のイメージと混同しないでください。 既存インスタンスを削除するオフライン復旧やREPLACEは、この実習には含めません。 [リストア構文](/ja/dbms/reference/sql/syntax/backup-restore-mount-syntax/)と [運用手順](/ja/dbms/operations-configuration-recovery/backup-restore-mount/)で、 権限・停止・対象置換の条件を確認してから別途実行してください。 複数テーブルの業務整合性まで検証する場合は、バックアップコマンドの成功だけで判断しないでください。 書き込み停止・業務の基準時点と、テーブル間の検証基準を併せて定めることを推奨します。 --- title: "8.13 TRANSACTION INSERT ON DUPLICATE KEY UPDATE" url: https://docs.machbase.com/ja/dbms/rdb-table-usage/insert-on-duplicate-key-update/ language: ja kind: page --- # 8.13 TRANSACTION INSERT ON DUPLICATE KEY UPDATE 「なければ追加し、あれば更新する」操作は単純に見えますが、何を重複と見なすかによって更新される行が変わります。 特にカウンター増加を再送すると、同じイベントが2回反映される場合があります。 キー、更新対象、再試行ポリシーを併せて確認してください。 TRANSACTIONの`INSERT ... ON DUPLICATE KEY UPDATE`は、PRIMARY KEYまたは一般のUNIQUE INDEXの競合時に既存行を更新します。 次の実習は、このページ内で必要なオブジェクトを準備します。 エラー確認SQLは通常の流れと分離し、最後のクリーンアップまで実行してから再実行してください。 ## サポートする構文 TRANSACTIONテーブルでは、`INSERT ... VALUES ...`形式のUPSERTをサポートします。 ```text INSERT INTO table_name VALUES (...) ON DUPLICATE KEY UPDATE; INSERT INTO table_name VALUES (...) ON DUPLICATE KEY UPDATE SET column_name = expression [, ...]; INSERT INTO table_name(column_name, ...) VALUES (...) ON DUPLICATE KEY UPDATE; INSERT INTO table_name(column_name, ...) VALUES (...) ON DUPLICATE KEY UPDATE SET column_name = expression [, ...]; ``` 競合判定キーとして認められる対象は次のとおりです。 - TRANSACTION PRIMARY KEY - TRANSACTION UNIQUE INDEX - TRANSACTION複合UNIQUE INDEX ## 基本動作 重複がなければ、通常のINSERTと同様に新しい行を追加します。 ```sql CREATE TRANSACTION TABLE ch8_up_device_state ( device_id INTEGER PRIMARY KEY, status VARCHAR(16), alarm_count INTEGER, updated_at DATETIME ); INSERT INTO ch8_up_device_state VALUES (1, 'NORMAL', 0, TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET status = 'NORMAL', updated_at = TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'); ``` PRIMARY KEYが重複すると、既存行をUPDATEします。 ```sql INSERT INTO ch8_up_device_state VALUES (1, 'ALARM', 1, TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET status = 'ALARM', alarm_count = alarm_count + 1, updated_at = TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'); ``` `SET`句ではPRIMARY KEYを変更できません。右辺の式は競合した既存行を基準に評価します。 したがって、`alarm_count = alarm_count + 1`は挿入しようとした値ではなく、既存行のalarm_countに1を加算します。 ```sql SELECT device_id, status, alarm_count, updated_at FROM ch8_up_device_state WHERE device_id = 1; ``` 想定する結果形式は次のとおりです。 ```text DEVICE_ID STATUS ALARM_COUNT UPDATED_AT --------- ------ ----------- ----------------------------- 1 ALARM 1 2026-07-10 09:05:00 000:000:000 ``` `ON DUPLICATE KEY UPDATE`の後の`SET`句は省略できます。 ```sql CREATE TRANSACTION TABLE ch8_up_asset_cache ( asset_id INTEGER PRIMARY KEY, asset_name VARCHAR(80), location VARCHAR(80), keep_value INTEGER ); INSERT INTO ch8_up_asset_cache VALUES (1, 'compressor-a', 'plant-1', 100); INSERT INTO ch8_up_asset_cache(asset_id, asset_name, location) VALUES (1, 'compressor-a-renamed', 'plant-2') ON DUPLICATE KEY UPDATE; ``` `SET`句がない場合は、INSERT対象列のうちPRIMARY KEY以外の列だけを既存行に反映します。 上の例では`asset_name`、`location`が更新され、列リストにない`keep_value`は既存値を保持します。 ```sql SELECT asset_id, asset_name, location, keep_value FROM ch8_up_asset_cache ORDER BY asset_id; ``` 想定する結果形式は次のとおりです。 ```text ASSET_ID ASSET_NAME LOCATION KEEP_VALUE -------- -------------------- -------- ---------- 1 compressor-a-renamed plant-2 100 ``` PRIMARY KEY列だけのテーブルで、重複行に`SET`なしのUPSERTを実行すると、更新対象列がないため行は変更されません。 ## UNIQUE INDEXの重複処理 PRIMARY KEYだけでなく、UNIQUE INDEXの競合でも更新処理が実行されます。 ```sql CREATE TRANSACTION TABLE ch8_up_account_profile ( id INTEGER PRIMARY KEY, email VARCHAR(120), display_name VARCHAR(80), login_count INTEGER ); CREATE UNIQUE INDEX ch8_up_uidx_account_profile_email ON ch8_up_account_profile(email); INSERT INTO ch8_up_account_profile VALUES (1, 'ops@example.com', 'ops-user', 1); INSERT INTO ch8_up_account_profile VALUES (2, 'ops@example.com', 'ops-renamed', 1) ON DUPLICATE KEY UPDATE SET display_name = 'ops-renamed', login_count = login_count + 1; SELECT id, email, display_name, login_count FROM ch8_up_account_profile ORDER BY id; ``` `email`のUNIQUE INDEXが重複するため、`id = 1`の行がUPDATEされます。 挿入しようとした`id = 2`の行は新規追加されません。 複合UNIQUE INDEXは、キーの組み合わせ全体が同じ場合に重複として処理します。 ```sql CREATE TRANSACTION TABLE ch8_up_daily_device_summary ( id INTEGER PRIMARY KEY, device_id INTEGER, summary_day VARCHAR(10), event_count INTEGER, last_status VARCHAR(16) ); CREATE UNIQUE INDEX ch8_up_uidx_daily_device_summary ON ch8_up_daily_device_summary(device_id, summary_day); INSERT INTO ch8_up_daily_device_summary VALUES (1, 101, '2026-07-10', 3, 'NORMAL'); INSERT INTO ch8_up_daily_device_summary VALUES (2, 101, '2026-07-10', 1, 'ALARM') ON DUPLICATE KEY UPDATE SET event_count = event_count + 1, last_status = 'ALARM'; INSERT INTO ch8_up_daily_device_summary VALUES (3, 101, '2026-07-11', 1, 'NORMAL') ON DUPLICATE KEY UPDATE SET event_count = event_count + 1; ``` 最初のUPSERTは`(device_id, summary_day) = (101, '2026-07-10')`の行をUPDATEします。 2番目のUPSERTは日付が異なるため、新しい行をINSERTします。 UNIQUE KEYにNULLを含む行同士は、重複として処理しません。 次の2つの入力は互いを上書きせず、それぞれ新しい行になります。 ```sql INSERT INTO ch8_up_daily_device_summary VALUES (4, NULL, '2026-07-10', 1, 'NORMAL') ON DUPLICATE KEY UPDATE; INSERT INTO ch8_up_daily_device_summary VALUES (5, NULL, '2026-07-10', 2, 'ALARM') ON DUPLICATE KEY UPDATE; SELECT id, device_id, summary_day, event_count FROM ch8_up_daily_device_summary ORDER BY id; ``` 結果のidは1・3・4・5、event_countはそれぞれ4・1・1・2です。 必須の業務キーでは、UNIQUE INDEXに加えて構成列のNOT NULLも必要です。 ## 活用例 TAGテーブルに時系列の測定値を継続的に蓄積し、TRANSACTIONテーブルに機器別の最新状態だけを維持できます。 ```sql CREATE TRANSACTION TABLE ch8_up_latest_device_status ( device_name VARCHAR(80) PRIMARY KEY, last_value DOUBLE, last_state VARCHAR(16), event_count LONG, updated_at DATETIME ); INSERT INTO ch8_up_latest_device_status VALUES ('compressor-a', 72.5, 'NORMAL', 1, TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET last_value = 72.5, last_state = 'NORMAL', event_count = event_count + 1, updated_at = TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'); INSERT INTO ch8_up_latest_device_status VALUES ('compressor-a', 91.2, 'ALARM', 1, TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET last_value = 91.2, last_state = 'ALARM', event_count = event_count + 1, updated_at = TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'); ``` このパターンは、ダッシュボードが最新状態だけを高速に検索する場合に使用できます。 外部システムが同じ業務キーでマスターデータを繰り返し送信する場合は、UNIQUE INDEXを基準にUPSERTできます。 ```sql CREATE TRANSACTION TABLE ch8_up_customer_device ( id LONG PRIMARY KEY AUTO_INCREMENT, external_device_id VARCHAR(64), device_name VARCHAR(80), owner_name VARCHAR(80), enabled INTEGER ); CREATE UNIQUE INDEX ch8_up_uidx_customer_device_external_id ON ch8_up_customer_device(external_device_id); INSERT INTO ch8_up_customer_device(external_device_id, device_name, owner_name, enabled) VALUES ('ERP-DEV-10001', 'compressor-a', 'line-1', 1) ON DUPLICATE KEY UPDATE SET device_name = 'compressor-a', owner_name = 'line-1', enabled = 1; INSERT INTO ch8_up_customer_device(external_device_id, device_name, owner_name, enabled) VALUES ('ERP-DEV-10001', 'compressor-a-renamed', 'line-2', 1) ON DUPLICATE KEY UPDATE SET device_name = 'compressor-a-renamed', owner_name = 'line-2', enabled = 1; ``` 最初のINSERTは新しい行を作成し、2番目のINSERTは`external_device_id`のUNIQUE INDEX競合によって既存行をUPDATEします。 内部の`id`は保持されます。 ソースデータの列値をそのまま最新キャッシュに反映する場合は、`SET`句なしのUPSERTを使用できます。 ```sql CREATE TRANSACTION TABLE ch8_up_tag_alias_cache ( alias_name VARCHAR(80) PRIMARY KEY, tag_name VARCHAR(80), unit VARCHAR(16), description VARCHAR(160), manually_checked INTEGER ); INSERT INTO ch8_up_tag_alias_cache VALUES ('compressor-a-temp', 'comp_a.temp', 'celsius', 'main compressor temp', 1); INSERT INTO ch8_up_tag_alias_cache(alias_name, tag_name, unit, description) VALUES ('compressor-a-temp', 'comp_a.temperature', 'celsius', 'renamed tag') ON DUPLICATE KEY UPDATE; ``` 上の文は`tag_name`、`unit`、`description`だけを更新します。 列リストにない`manually_checked`は既存値を保持します。 集計テーブルでキーごとの発生回数を累積できます。 ```sql CREATE TRANSACTION TABLE ch8_up_alarm_counter ( alarm_code VARCHAR(32) PRIMARY KEY, first_seen DATETIME, last_seen DATETIME, hit_count LONG ); INSERT INTO ch8_up_alarm_counter VALUES ( 'OVER_TEMP', TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1 ) ON DUPLICATE KEY UPDATE SET last_seen = TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), hit_count = hit_count + 1; INSERT INTO ch8_up_alarm_counter VALUES ( 'OVER_TEMP', TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'), 1 ) ON DUPLICATE KEY UPDATE SET last_seen = TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'), hit_count = hit_count + 1; ``` `hit_count = hit_count + 1`は既存行を基準に計算するため、累積カウンターに使用できます。 JSON列も更新対象列として使用できます。 ```sql CREATE TRANSACTION TABLE ch8_up_device_json_state ( device_id INTEGER PRIMARY KEY, state JSON, updated_at DATETIME ); INSERT INTO ch8_up_device_json_state VALUES ( 1, '{"status":"NORMAL","score":10}', TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS') ) ON DUPLICATE KEY UPDATE SET state = '{"status":"NORMAL","score":10}', updated_at = TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS'); INSERT INTO ch8_up_device_json_state VALUES ( 1, '{"status":"ALARM","score":90}', TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS') ) ON DUPLICATE KEY UPDATE SET state = '{"status":"ALARM","score":90}', updated_at = TO_DATE('2026-07-10 09:05:00', 'YYYY-MM-DD HH24:MI:SS'); SELECT JSON_EXTRACT_STRING(state, '$.status') AS status, JSON_EXTRACT_INTEGER(state, '$.score') AS score FROM ch8_up_device_json_state WHERE device_id = 1; ``` 制限: JSONパスのUNIQUE INDEXは、競合判定キー候補から除外されます。 JSONパスのUNIQUE INDEX競合はUPSERTの更新処理に切り替わらず、一意性制約エラーとして処理されます。 ## トランザクションと権限 TRANSACTIONのUPSERTは、通常のINSERT/UPDATEと同様にトランザクション内でCOMMITまたはROLLBACKされます。 ```sql CREATE TRANSACTION TABLE ch8_up_tx_device_state ( id INTEGER PRIMARY KEY, status VARCHAR(16), count_value INTEGER ); INSERT INTO ch8_up_tx_device_state VALUES (1, 'NORMAL', 10); BEGIN; INSERT INTO ch8_up_tx_device_state VALUES (2, 'NORMAL', 1) ON DUPLICATE KEY UPDATE SET count_value = count_value + 1; INSERT INTO ch8_up_tx_device_state VALUES (1, 'ALARM', 1) ON DUPLICATE KEY UPDATE SET status = 'ALARM', count_value = count_value + 1; ROLLBACK; SELECT id, status, count_value FROM ch8_up_tx_device_state ORDER BY id; ``` 上の例では、挿入処理と更新処理の両方がROLLBACKされます。 通常の制約違反で重複更新文が失敗しても、明示的トランザクション内で先に成功した変更は残る場合があります。 アプリケーションはエラーを確認して後続処理を決めるか、ROLLBACKで業務変更を取り消す必要があります。 TRANSACTIONのUPSERT文には、`INSERT`権限と`UPDATE`権限の両方が必要です。 実行結果が挿入処理であっても、文に更新処理が含まれるため両方の権限を付与する必要があります。 次は権限の形式だけを示す例です。 実際の所有者・テーブル・既存アプリケーションアカウントに合わせ、別の管理作業として適用してください。 ```text GRANT INSERT ON owner.table_name TO app_user; GRANT UPDATE ON owner.table_name TO app_user; ``` `SELECT`権限は、TRANSACTIONのUPSERT文の実行自体には不要です。 ただし、アプリケーションが結果確認のために`SELECT`を実行する場合は、別途`SELECT`権限が必要です。 ## サポートする型と制約 `SET`句で更新できる列の型は、通常のTRANSACTION `UPDATE`と同じ公開型のサポート範囲に従います。 | 分類 | 型 | | --- | --- | | 整数 | `SHORT`, `INT16`, `USHORT`, `UINT16`, `INT`, `INTEGER`, `INT32`, `UINTEGER`, `UINT32`, `LONG`, `INT64`, `ULONG`, `UINT64` | | 浮動小数点 | `FLOAT`, `DOUBLE` | | 固定小数点 | `DECIMAL`, `NUMERIC`, `DEC`, `FIXED`, `NUMBER` | | 文字列/LOB | `VARCHAR`, `TEXT`, `CLOB`, `BINARY`, `BLOB` | | その他 | `DATETIME`, `IPV4`, `IPV6`, `JSON` | 上の表は、TRANSACTIONで使用するスカラー型をまとめたものです。 数値ARRAYのサポート範囲は、[データ型リファレンス](/ja/dbms/reference/sql/types/)を参照してください。 競合判定キーとなるキー・インデックスの型は、TRANSACTION PRIMARY KEYとUNIQUE INDEXの型ポリシーに従います。 この機能はキー型のサポート範囲を拡張しません。 次の構文はサポートしていません。 ```text -- 未サポートの構文を示す説明用のブロックです。 -- INSERT SELECTとON DUPLICATE KEY UPDATEの組み合わせは未サポートです。 INSERT INTO ch8_up_device_state(device_id, status, alarm_count, updated_at) SELECT device_id, status, alarm_count, updated_at FROM staging_device_state ON DUPLICATE KEY UPDATE SET status = 'UPDATED'; -- MySQLのVALUES(col)関数は未サポートです。 INSERT INTO ch8_up_device_state VALUES (1, 'ALARM', 1, TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET status = VALUES(status); -- EXCLUDED別名は未サポートです。 INSERT INTO ch8_up_device_state VALUES (1, 'ALARM', 1, TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS')) ON DUPLICATE KEY UPDATE SET status = EXCLUDED.status; -- conflict target構文は未サポートです。 INSERT INTO ch8_up_device_state VALUES (1, 'ALARM', 1, TO_DATE('2026-07-10 09:00:00', 'YYYY-MM-DD HH24:MI:SS')) ON CONFLICT (device_id) DO UPDATE SET status = 'ALARM'; ``` 対象テーブルの制限は次のとおりです。 - このページは、TRANSACTIONのPRIMARY KEY・UNIQUE競合時の動作だけを説明します。 同じSQL形式はLOOKUPとVOLATILEのPRIMARY KEY競合にも対応します。 共通構文の正本は[DMLリファレンス](/ja/dbms/reference/sql/syntax/dml-syntax/#on-duplicate-key-update)です。 - LOGとTAG DATA行ではサポートしていません。TAG METADATAのタグ名競合処理は、 [DMLリファレンス](/ja/dbms/reference/sql/syntax/dml-syntax/#on-duplicate-key-update)を参照してください。 - TRANSACTIONテーブルでも、PRIMARY KEYまたはUNIQUE INDEXがなければ使用できません。 - JSONパスのUNIQUE INDEXは競合判定キーに使用しません。 ## 競合とエラー処理 複数のUNIQUE INDEXが同じ既存行を指す場合、その行を一度だけUPDATEします。 一方、異なる既存行と競合すると、更新すべき行を決定できず文が失敗します。 次は、2つの業務キーがそれぞれ異なる行と競合するサンプルです。 ```sql CREATE TRANSACTION TABLE ch8_up_user_contact ( id INTEGER PRIMARY KEY, email VARCHAR(120), phone VARCHAR(40), note VARCHAR(80) ); CREATE UNIQUE INDEX ch8_up_uidx_user_contact_email ON ch8_up_user_contact(email); CREATE UNIQUE INDEX ch8_up_uidx_user_contact_phone ON ch8_up_user_contact(phone); INSERT INTO ch8_up_user_contact VALUES (1, 'a@example.com', '010-0000-0001', 'user-a'); INSERT INTO ch8_up_user_contact VALUES (2, 'b@example.com', '010-0000-0002', 'user-b'); ``` 次のINSERTだけを意図的に失敗させる任意の実習です。 ```sql -- emailはid=1、phoneはid=2と競合します。 -- 異なる行と競合するため、更新処理を選択せず失敗します。 INSERT INTO ch8_up_user_contact VALUES (3, 'a@example.com', '010-0000-0002', 'ambiguous') ON DUPLICATE KEY UPDATE SET note = 'updated'; ``` `SET`の結果が別のUNIQUE制約や`NOT NULL`制約に違反した場合も、文は失敗して既存行が保持されます。 ## 再送と最新状態 カウンター増加のUPSERTは自動的な重複排除ではありません。 同じイベントを再実行すると、既存のカウンターが再び増加します。 COMMIT応答を失った場合は、業務キー・イベント処理記録で先に結果を確認してください。 また、「最新状態」は、入力順序とイベント発生順序が一致する場合にのみ単純な上書きで維持できます。 遅れて到着した過去のイベントが最新値を上書きしないよう、元の時刻の比較と収集ポリシーを別途定めてください。 複数テーブルをまとめて変更する処理では、[障害時のトランザクションのコミット範囲](../transaction/)も確認する必要があります。 ## 運用上の推奨事項 - 業務キーが明確なら、PRIMARY KEYまたはUNIQUE INDEXを先に定義します。 - カウンターの累積には、`SET count_col = count_col + 1`形式を使用します。 - ソース行の値をそのまま反映するには、`SET`なしのUPSERTを使用できます。この場合、列リストで省略した列は保持されます。 - 複数のUNIQUE INDEXを持つテーブルでは、異なる行と同時に競合する可能性がある入力を事前に整理します。 - MySQL互換SQLを移植する場合は、`VALUES(col)`、`EXCLUDED`、`ON CONFLICT`をMachbaseのサポート構文に変更します。 - JSONパスのUNIQUE INDEXをUPSERTキーにする設計は避けます。必要なら別の通常列にキー値を保存してUNIQUE INDEXを作成します。 ## 結果確認とクリーンアップ 通常の実習を終えたら、代表値と件数を再確認します。 次の想定値は、意図的なエラー以外の正常なSQLをそれぞれ一度実行した場合です。 ```sql SELECT id, email, display_name, login_count FROM ch8_up_account_profile ORDER BY id; SELECT device_name, last_state, event_count FROM ch8_up_latest_device_status; SELECT external_device_id, device_name, owner_name FROM ch8_up_customer_device; SELECT alias_name, tag_name, manually_checked FROM ch8_up_tag_alias_cache; SELECT alarm_code, hit_count FROM ch8_up_alarm_counter; SELECT id, status, count_value FROM ch8_up_tx_device_state ORDER BY id; SELECT id, note FROM ch8_up_user_contact ORDER BY id; ``` | サンプル | 確認する結果 | |---|---| | account_profile | id=1を保持、display_name=ops-renamed、login_count=2 | | latest_device_status | ALARM、event_count=2 | | customer_device | 外部キーの1行、名前compressor-a-renamed、所有line-2 | | tag_alias_cache | tag_name=comp_a.temperature、manually_checked=1を保持 | | alarm_counter | OVER_TEMPのhit_count=2 | | tx_device_state | ROLLBACK後は既存のid=1、NORMAL、count_value=10だけが存在 | | user_contact | id=1・2のuser-a・user-bをそのまま保持 | ```sql DROP TABLE ch8_up_user_contact; DROP TABLE ch8_up_tx_device_state; DROP TABLE ch8_up_device_json_state; DROP TABLE ch8_up_alarm_counter; DROP TABLE ch8_up_tag_alias_cache; DROP TABLE ch8_up_customer_device; DROP TABLE ch8_up_latest_device_status; DROP TABLE ch8_up_daily_device_summary; DROP TABLE ch8_up_account_profile; DROP TABLE ch8_up_asset_cache; DROP TABLE ch8_up_device_state; ``` DROPはこのページの実習オブジェクトだけを対象にします。 キーが複雑な場合ほど、新しい入力値と競合する既存行を並べて比較してください。 更新しようとした行が明確になれば、エラーの原因も特定しやすくなります。 --- title: "9. LOOKUPテーブルの活用" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/ language: ja kind: section --- # 9. LOOKUPテーブルの活用 LOOKUPテーブルは、永続保存した基準情報やマスターデータをサーバー起動時にメモリへロードし、 PRIMARY KEYをキーに高速参照するテーブルです。 メモリ常駐構造、JSON/SEQUENCE、JOIN、一般の述語に基づくDMLを説明します。 ## この章の構成 | 節 | 内容 | |----|------| | [概要と選択基準](./overview-use-criteria/) | LOOKUPテーブルの用途と適用条件 | | [テーブル構造とスキーマ](./table-structure-schema/) | 列構成、PK構造、スキーマ設計 | | [作成、変更、削除](./create-alter-drop/) | DDL: CREATE、ALTER、DROP | | [データ入力と変更](./data-input-mutation/) | INSERT、Append、再ロード、削除 | | [クエリと分析](./query-analysis/) | SELECT、JOIN、条件検索 | | [インデックスとパフォーマンス](./index-performance/) | 赤黒木インデックス、セカンダリインデックス、チューニング | | [運用とデータライフサイクル](./operations-lifecycle/) | バックアップ・復旧、データの永続性 | | [制約、エラー、トラブルシューティング](./constraints-errors-troubleshooting/) | 制限、エラー原因、対処 | | [活用パターンとシナリオ](./patterns-scenarios/) | コードテーブル、マスターデータ、しきい値管理 | | [PRIMARY KEYポリシー](./primary-key-policy/) | 自然キーと代理キー、PK不変の原則 | | [SEQUENCE列](./sequence-column/) | 自動増分番号の設定とNEXTVALの使用方法 | | [JSON列とJSONクエリ](./json-column-query/) | JSON列のサポート範囲、パス条件検索、PRIMARY KEYの制約 | | [一般述語のUPDATE/DELETE](./predicate-update-delete/) | 非PK・範囲・文字列・日付・JSONパス条件による変更 | --- title: "9.1 概要と選択基準" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/overview-use-criteria/ language: ja kind: page --- # 9.1 概要と選択基準 LOOKUPテーブルは、基準コード、機器マスター、しきい値、設定値など、比較的小規模で頻繁に参照されるデータを保存します。 データは永続保存されますが、SQL検索に使用する全行はメモリに常駐します。 そのため、繰り返し行うキーによる検索と更新に適しています。 ## LOOKUPテーブルの特性 LOOKUPテーブルは`CREATE LOOKUP TABLE`文で作成し、`PRIMARY KEY`が必須です。 ```sql CREATE LOOKUP TABLE ch9_overview ( sensor_id VARCHAR(64) PRIMARY KEY, site VARCHAR(32), unit VARCHAR(16), status VARCHAR(16) ); ``` LOOKUPテーブルの主な特性は次のとおりです。 | 項目 | 内容 | |------|------| | 主な用途 | コードテーブル、機器マスター、しきい値、参照データ | | 必須条件 | `PRIMARY KEY`が必要 | | 保存方式 | 永続保存し、サーバー起動時に全行をメモリへロード | | 検索パターン | PK検索に最適化。一般条件検索と他のテーブルとのJOINをサポート | | 変更パターン | INSERT、UPDATE、DELETE | | 追加機能 | SEQUENCE列、Appendの重複キーポリシー | ## 選択基準 次の条件に該当する場合は、LOOKUPテーブルを使用します。 - データ件数が比較的小さく、全体が頻繁に参照される。 - 全行と必要なセカンダリインデックスをサーバーメモリに保持できる。 - コード、名前、場所、単位、状態などのマスターデータを管理する。 - TAGまたはLOGの元データに説明情報をJOINする必要がある。 - しきい値や設定値など、運用中に変更される参照値を保存する。 - `PRIMARY KEY`で行を明確に識別できる。 TAGまたはLOGデータに場所や単位などの説明を付加するJOIN例は、 [クエリと分析](/ja/dbms/lookup-table-usage/query-analysis/)で説明します。 ## 他のテーブルを検討する場合 次の要件には、他のテーブルタイプを検討します。 | 要件 | 推奨テーブル | |----------|-------------| | 大量の時系列計測データの保存 | TAG | | 追加中心の元イベントの保存 | LOG | | 全行のメモリロードが困難な大規模リレーショナルデータ | TRANSACTION | | トランザクションとリレーショナルな業務処理が必要なデータ | TRANSACTION | | サーバーメモリだけで維持する最新状態キャッシュ | VOLATILE | LOOKUPテーブルは参照データに適していますが、永続保存されることを理由にディスク中心の大容量テーブルとして使用しないでください。 元データはLOGまたはTAGに保存し、LOOKUPにはメモリに常駐させて繰り返し検索するマスターデータを格納します。 リレーショナルデータがメモリ容量を超える場合や、複雑な業務処理が必要な場合はTRANSACTIONテーブルを使用します。 この節の実習テーブルは、次のように削除します。 ```sql DROP TABLE ch9_overview; ``` ## 設計手順 LOOKUPテーブルの設計では、次の順序で決定します。 1. 行を識別する`PRIMARY KEY`を決めます。 2. 自然キーか、SEQUENCEまたはAUTO_INCREMENTに基づく代理キーかを決めます。 3. 頻繁に検索・JOINする列にインデックスを追加します。 4. 想定行サイズ・行数と、セカンダリインデックスを含むメモリ使用量を検証します。 5. 運用中に更新する列と不変の列を区別します。 6. 大量変更の前に、対象範囲を確認するクエリを用意します。 スキーマとキーの設計は、[テーブル構造とスキーマ](/ja/dbms/lookup-table-usage/table-structure-schema/)と [PRIMARY KEYポリシー](/ja/dbms/lookup-table-usage/primary-key-policy/)で説明します。 --- title: "9.2 テーブル構造とスキーマ" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/table-structure-schema/ language: ja kind: page --- # 9.2 テーブル構造とスキーマ LOOKUPテーブルの構造とスキーマ設計を説明します。 ## LOOKUPテーブルの設計 LOOKUPテーブルは、コードテーブルとマスターデータを保存するタイプです。 PRIMARY KEYで各行を識別し、PRIMARY KEYまたは一般条件式によるUPDATE/DELETEをサポートし、ディスクに永続保存されます。 ### 永続保存とメモリ検索の構造 LOOKUPテーブルは、永続性とメモリ検索性能を提供する2層構造です。 1. 変更された行は、再起動後も保持できるよう永続ストレージに記録されます。 2. サーバー起動時に永続ストレージのLOOKUP行をすべて読み取り、各列の値を含むメモリ上の行として復元します。 3. 各メモリ行は、必須の`PRIMARY KEY`の赤黒木インデックスに登録されます。 4. SQLクエリは、復元されたメモリ行とインデックスを使用します。 概念上、1行は次のようなキーと値の項目として捉えられます。 ``` PRIMARY KEY その他の列の値 sensor_id = 'TEMP-01' ───────► { site, unit, status, ... } key value ``` このためLOOKUPは、SQLテーブルのインターフェース、一般条件検索、JOIN、セカンダリインデックスに対応しながら、 特に`PRIMARY KEY`検索に適しています。 永続ストレージがあっても、検索時に必要な行だけをディスクから読み出す構造ではありません。 全行と作成した赤黒木セカンダリインデックスがメモリを使用するため、スキーマ設計では、 行数だけでなく可変長列、JSON値、セカンダリインデックスのサイズも考慮してください。 - **[活用例](/ja/dbms/lookup-table-usage/patterns-scenarios/#use-cases-lookup)** - **[PRIMARY KEYの設計](/ja/dbms/lookup-table-usage/primary-key-policy/#design-primary-key)** - **[列とシーケンスの設計](/ja/dbms/lookup-table-usage/sequence-column/#design-column-lookup-sequence)** - **[JSON列とクエリ](/ja/dbms/lookup-table-usage/json-column-query/#condition-query-lookup-json)** - **[参照設計パターン](/ja/dbms/lookup-table-usage/patterns-scenarios/#patterns-reference-design)** - **[インデックス戦略](/ja/dbms/lookup-table-usage/index-performance/#index-strategy-lookup)** - **[PRIMARY KEYポリシー](/ja/dbms/lookup-table-usage/primary-key-policy/#policy-lookup-primary-key)** - **[一般条件式によるUPDATE・DELETE](/ja/dbms/lookup-table-usage/predicate-update-delete/)** - **[バックアップ・復旧のサポート範囲](/ja/dbms/lookup-table-usage/operations-lifecycle/#recovery-support-scope-backup-lookup)** - **[制約と注意事項](/ja/dbms/lookup-table-usage/constraints-errors-troubleshooting/#limitations-lookup)** --- title: "9.3 作成、変更、削除" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/create-alter-drop/ language: ja kind: page --- # 9.3 作成、変更、削除 LOOKUPテーブルの作成、変更、削除方法を説明します。 ## LOOKUPテーブルの作成と管理 参照テーブルの作成方法は次のとおりです。LOOKUPテーブルには必ず`PRIMARY KEY`を指定します。 ## LOOKUPテーブルの作成 ```sql CREATE LOOKUP TABLE ch9_ddl (id INTEGER PRIMARY KEY, name VARCHAR(20)); ``` 運用で使用するマスターデータには、意味の明確な列名を定義します。 ```sql CREATE LOOKUP TABLE ch9_ddl_equip ( equip_id LONG PRIMARY KEY, equip_name VARCHAR(128), location VARCHAR(64), status VARCHAR(16), updated_at DATETIME ); ``` `PRIMARY KEY`は行を一意に識別し、UPDATE、DELETE、JOINの基準になります。 複数列の組み合わせが業務キーの場合は、結合した文字列を別のキー列にするか、SEQUENCEによる代理キーを使用します。 ```sql CREATE LOOKUP TABLE ch9_ddl_price ( price_key VARCHAR(64) PRIMARY KEY, product_id VARCHAR(32), region VARCHAR(16), price DOUBLE ); ``` ## AUTO_INCREMENT PRIMARY KEY サーバーが数値PRIMARY KEYを生成する場合は、単一の`LONG`または`INT64`列に`AUTO_INCREMENT`を指定します。 ```sql CREATE LOOKUP TABLE ch9_ddl_registry ( equip_id LONG PRIMARY KEY AUTO_INCREMENT, equip_name VARCHAR(128), location VARCHAR(64) ); INSERT INTO ch9_ddl_registry(equip_name, location) VALUES ('compressor-01', 'SEOUL-A'); ``` PK列を省略するかNULLを指定すると、サーバーが値を生成します。 単一の`INSERT ... VALUES`では、`0..INT64_MAX`範囲のPK値を直接指定することもできます。 指定値が現在の次の自動値以上なら、次の自動値は`指定値 + 1`に進み、小さい値を指定しても戻りません。 データと次の自動値は、正常な再起動後も保持されます。 AUTO_INCREMENTを使用するLOOKUPテーブルでは、`INSERT ... SELECT`と`ON DUPLICATE KEY UPDATE`は使用できません。 SDKでINSERT結果のIDを取得する方法は、[ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## SEQUENCE列の使用 自動増分番号が必要なら、`LONG PROPERTY(SEQUENCE=1)`列を使用します。 入力時は`NEXTVAL()`関数で次の値を取得します。 ```sql CREATE LOOKUP TABLE ch9_ddl_alarm ( seq LONG PROPERTY(SEQUENCE=1) PRIMARY KEY, sensor_id VARCHAR(64), alarm_type VARCHAR(32), occurred_at DATETIME, message VARCHAR(256) ); INSERT INTO ch9_ddl_alarm VALUES (NEXTVAL(seq), 'TEMP-01', 'HIGH', NOW, '온도 초과'); ``` SEQUENCE列の詳細なポリシーは、[SEQUENCE列](/ja/dbms/lookup-table-usage/sequence-column/)で説明します。 `PROPERTY(SEQUENCE)`と`AUTO_INCREMENT`は別の機能であり、同じ列に併用しません。 ## 列の追加と削除 Standard Editionでは、LOOKUPテーブルに固定長の数値ARRAY列を追加・削除できます。 ```sql ALTER TABLE ch9_ddl_equip ADD COLUMN (limits DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); ALTER TABLE ch9_ddl_equip DROP COLUMN (limits); ``` DEFAULTがなければ、既存行の新しいARRAY列は列全体がNULLになります。 DEFAULTを指定すると、既存行にもその値を適用します。 ARRAY DEFAULTの要素数は、宣言した要素数と正確に一致する必要があります。 ARRAY列はPRIMARY KEYやインデックスキーには使用できません。 サポート型と制約は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ## インデックスの追加 頻繁に検索する列やJOIN条件に使用する列には、インデックスを追加します。 ```sql CREATE INDEX ch9_ddl_loc_idx ON ch9_ddl_equip(location); CREATE INDEX ch9_ddl_status_idx ON ch9_ddl_equip(status); ``` PRIMARY KEY列には標準のインデックスが作成されるため、同じ列に別のインデックスを重複作成しません。 インデックスが多いと入力と更新のコストが増えるため、検索条件が明確な列だけに追加します。 ## データ削除とテーブル削除 行を削除するには`DELETE`文を使用します。単一行の削除には、PK条件を使用する方法が最も明確です。 ```sql DELETE FROM ch9_ddl_equip WHERE equip_id = 1001; ``` 一括削除では一般条件式を使用できます。 本番データでは、先に同じ条件で対象件数を確認してください。 ```sql SELECT COUNT(*) FROM ch9_ddl_equip WHERE status = 'RETIRED'; DELETE FROM ch9_ddl_equip WHERE status = 'RETIRED'; ``` テーブル自体を削除するには、`DROP TABLE`を使用します。 ```sql DROP TABLE ch9_ddl_alarm; DROP TABLE ch9_ddl_registry; DROP TABLE ch9_ddl_price; DROP TABLE ch9_ddl_equip; DROP TABLE ch9_ddl; ``` `DROP TABLE`はテーブル定義とデータを両方削除します。 必要に応じて、削除前にバックアップまたはエクスポートを行ってください。 ## 注意事項 - LOOKUPテーブルには`PRIMARY KEY`が必須です。 - `PRIMARY KEY`列は1つだけ指定します。 - `PRIMARY KEY`値を変更する場合は、既存行を削除してから新しいキーで挿入します。 - マスターデータが大きくなり、検索・更新パターンが複雑になったら、TRANSACTIONテーブルを検討します。 --- title: "9.4 データ入力と変更" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/data-input-mutation/ language: ja kind: page --- # 9.4 データ入力と変更 LOOKUPテーブルの入力、更新、削除を、一連の実行可能な例で説明します。 ## サンプルテーブルの準備 次の例は、最後のクリーンアップ文まで順に実行できます。 ```sql CREATE LOOKUP TABLE ch9_mutation ( code VARCHAR(32) PRIMARY KEY, label VARCHAR(64), status VARCHAR(16), updated_at DATETIME ); INSERT INTO ch9_mutation VALUES ('TEMP', 'Temperature', 'ACTIVE', NOW); INSERT INTO ch9_mutation VALUES ('PRESS', 'Pressure', 'ACTIVE', NOW); ``` SEQUENCEキーが必要なら、[SEQUENCE](/ja/dbms/lookup-table-usage/sequence-column/)を参照してください。 ## UPDATE 単一行の変更はPRIMARY KEY条件で処理します。 ```sql UPDATE ch9_mutation SET status = 'INACTIVE', updated_at = NOW WHERE code = 'TEMP'; ``` 複数行を変更する場合は、先に同じ`WHERE`句で対象を検索します。 単一行の変更には、対象が明確でインデックスを使用できる`PRIMARY KEY`条件を推奨します。 PRIMARY KEY列自体はUPDATEできません。キーを変更する場合は、既存行を削除して新しいキーで再入力します。 この2文を1つのTRANSACTIONトランザクションにまとめることはできないため、途中の失敗と参照データの変更手順も設計してください。 ## 重複キーの処理 SQL INSERTのキー重複時に更新が必要なら、`ON DUPLICATE KEY UPDATE`を使用します。 ```sql INSERT INTO ch9_mutation VALUES ('TEMP', 'Temperature sensor', 'ACTIVE', NOW) ON DUPLICATE KEY UPDATE SET label = 'Temperature sensor', status = 'ACTIVE', updated_at = NOW; ``` Appendでデータを挿入するときにPRIMARY KEYが重複すると、`LOOKUP_APPEND_UPDATE_ON_DUPKEY`設定に応じて対象行を更新できます。 この設定はLOOKUPテーブルのAppend処理における重複キーポリシーのため、本番環境では現在の設定値を確認してから使用してください。 ```sql SELECT name, value FROM v$property WHERE name = 'LOOKUP_APPEND_UPDATE_ON_DUPKEY'; ``` ## TABLE_REFRESH 永続保存されたLOOKUPの内容を、実行中のメモリテーブルへ再反映する必要がある場合は、`TABLE_REFRESH`を実行します。 ```sql EXEC TABLE_REFRESH(ch9_mutation); ``` 通常のSQL DMLの直後に毎回実行するコマンドではありません。 対象は現在のデータベースのLOOKUPテーブルであり、READ ONLYデータベースでは実行できません。 名前の範囲・権限・エラー仕様は、[EXECプロシージャの正本](/ja/dbms/reference/sql/syntax/execute-procedure-syntax/#table-refresh)、 クラスター運用手順は[運用とライフサイクル](/ja/dbms/lookup-table-usage/operations-lifecycle/)を参照してください。 ## LOOKUPデータの削除 単一行の削除にはPRIMARY KEY条件を使用します。 ```sql DELETE FROM ch9_mutation WHERE code = 'PRESS'; ``` 一般条件式を使用すると、条件に一致するすべての行を削除します。 全行を削除する場合はWHERE句を省略します。 ```sql DELETE FROM ch9_mutation; DROP TABLE ch9_mutation; ``` ## 変更操作のチェックリスト - 単一行の変更にはPRIMARY KEY条件を使用します。 - 一般条件式で一括変更する前に、同じ条件で対象範囲を検索します。 - 全行の削除前に、バックアップまたは再入力できる元データを確認します。 - PRIMARY KEY値の変更は、DELETE後のINSERTで処理します。 - Appendの重複キー処理では、`LOOKUP_APPEND_UPDATE_ON_DUPKEY`設定を確認します。 - 永続LOOKUPを実行時メモリに再反映する必要がある場合だけ、`EXEC TABLE_REFRESH(table_name)`を使用します。 --- title: "9.5 クエリと分析" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/query-analysis/ language: ja kind: page --- # 9.5 クエリと分析 LOOKUPテーブルのキー検索、一般条件検索、TAGデータとのJOINを実行可能な例で説明します。 ## サンプルデータの準備 次のLOOKUPテーブルとTAGテーブルを準備します。 ```sql CREATE LOOKUP TABLE ch9_query_master ( sensor_id VARCHAR(32) PRIMARY KEY, site VARCHAR(32), unit VARCHAR(16), status VARCHAR(16) ); INSERT INTO ch9_query_master VALUES ('TEMP-01', 'SEOUL', 'C', 'ACTIVE'); INSERT INTO ch9_query_master VALUES ('TEMP-02', 'BUSAN', 'C', 'INACTIVE'); CREATE TAG TABLE ch9_query_data ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); INSERT INTO ch9_query_data VALUES ('TEMP-01', TO_DATE('2026-01-01 00:00:00'), 23.5); INSERT INTO ch9_query_data VALUES ('TEMP-02', TO_DATE('2026-01-01 00:00:00'), 19.0); ``` ## PRIMARY KEYによる検索 単一行の検索には`PRIMARY KEY`条件を使用します。 ```sql SELECT sensor_id, site, unit, status FROM ch9_query_master WHERE sensor_id = 'TEMP-01'; ``` ## 一般条件による検索 LOOKUPテーブルは、一般列の条件でも検索できます。頻繁に使用する条件列にはインデックスを追加します。 ```sql SELECT sensor_id, site, unit FROM ch9_query_master WHERE site = 'SEOUL' AND status = 'ACTIVE'; ``` 頻繁に使用する一般条件列には、インデックスを追加できます。 インデックスの設計と作成方法は、[インデックス](/ja/dbms/lookup-table-usage/index-performance/)を参照してください。 ## TAG・LOGテーブルとのJOIN LOOKUPテーブルは、TAGまたはLOGテーブルの元データに説明情報を付加する用途でよく使用します。 ```sql SELECT d.name, m.site, m.unit, d.time, d.value FROM ch9_query_data d JOIN ch9_query_master m ON d.name = m.sensor_id WHERE m.status = 'ACTIVE'; ``` ## 分析パターン LOOKUPテーブルは元データを保存するより、分析の基準を提供します。次のパターンに適しています。 | パターン | 説明 | |------|------| | コード変換 | 状態コード、アラームコード、機器タイプをラベルに変換 | | 基準値との比較 | センサー値をしきい値テーブルとJOINし、超過を判定 | | グループ基準の提供 | 場所、部門、ラインなどの集計基準を提供 | | 最新設定の反映 | 運用中に変更される設定値を検索時点で反映 | 同じ方法で、しきい値のLOOKUPテーブルとTAGの元データをJOINし、基準値を超えたか判定できます。 時間範囲が広いTAGまたはLOGテーブルでは、JOIN前に時間条件で検索範囲を制限します。 ```sql DROP TABLE ch9_query_data CASCADE; DROP TABLE ch9_query_master; ``` ## クエリ性能の基準 - 単一行検索とJOINの基準列には、`PRIMARY KEY`またはインデックス列を使用します。 - 条件に頻繁に使う一般列には、別のインデックスを検討します。 - 大量の元データとJOINする場合は、元テーブルの時間範囲を先に絞ります。 - LOOKUPにはマスターデータ、長期の元データはTAGまたはLOGに保存します。 --- title: "9.6 インデックスとパフォーマンス" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/index-performance/ language: ja kind: page --- # 9.6 インデックスとパフォーマンス LOOKUPテーブルのインデックス構造とパフォーマンスチューニングを説明します。 ## LOOKUPのインデックスチューニング LOOKUPのPRIMARY KEYには赤黒木インデックスが自動作成されます。 全行とインデックスは、SQL検索中にメモリに常駐します。 必要に応じて、非PK列にも赤黒木のセカンダリインデックスを追加できます。 ### LOOKUPテーブルのインデックス #### PKの自動赤黒木インデックス LOOKUPテーブルを作成すると、PRIMARY KEY列に赤黒木インデックスが自動作成されます。 インデックス項目は、そのキーの全列値を含むメモリ行を指します。 そのため、永続テーブルでもクエリの実行経路はメモリベースであり、小規模なマスターデータをキーで繰り返し検索するパターンに最適化されています。 ```sql CREATE LOOKUP TABLE ch9_index_device ( device_id VARCHAR(64) PRIMARY KEY, -- 赤黒木を自動作成 device_name VARCHAR(128), location VARCHAR(256), category VARCHAR(32) ); INSERT INTO ch9_index_device VALUES ('DEV-01', 'Boiler', 'Seoul', 'temperature'); INSERT INTO ch9_index_device VALUES ('DEV-02', 'Pump', 'Busan', 'pressure'); ``` ```sql -- PK検索: 赤黒木インデックスを使用 SELECT device_id, device_name, location FROM ch9_index_device WHERE device_id = 'DEV-01'; ``` 1行が返されます。イベントログと結合する場合も、LOOKUP側はPKで検索します。 ```sql CREATE LOG TABLE ch9_index_event (device_id VARCHAR(64), level SHORT); INSERT INTO ch9_index_event VALUES ('DEV-01', 3); INSERT INTO ch9_index_event VALUES ('DEV-02', 1); EXEC TABLE_FLUSH(ch9_index_event); SELECT e.device_id, e.level, d.location FROM ch9_index_event e, ch9_index_device d WHERE e.device_id = d.device_id ORDER BY e.device_id; ``` 2行が返されます。LOG側に時間範囲も指定すると、読み取る元データをさらに減らせます。 #### 非PK列のセカンダリインデックス 非PK列にも赤黒木セカンダリインデックスを作成できます。 セカンダリインデックスがない列でフィルタリングすると、テーブル全体を順次スキャンします。 ```sql -- 頻繁にフィルタリングする非PK列にセカンダリインデックスを作成 CREATE INDEX ch9_index_device_location ON ch9_index_device(location); SELECT device_id FROM ch9_index_device WHERE location = 'Seoul'; -- インデックスのない列は全体スキャンになる場合があります SELECT device_id FROM ch9_index_device WHERE category = 'temperature'; ``` 両方のクエリがDEV-01を返します。結果が同じでもアクセス経路が異なるため、 実際の比較は本番規模のデータで実行計画と併せて確認します。 セカンダリインデックスは検索を高速化しますが、更新コストとメモリ使用量が増えます。 頻繁に使用する条件列だけに作成してください。 #### LOOKUPテーブルの使用指針 PRIMARY KEYと赤黒木セカンダリインデックスの検索コストは、木のサイズに応じて増加します。 インデックスのない条件は、メモリにロードされた全行をスキャンします。 行数だけで使用限界を決めず、全行の実サイズ、可変長値、インデックス数、検索と更新の比率を同じワークロードで測定してください。 サーバー起動時には永続データをすべて読み取り、メモリ行とインデックスを構築するため、起動時間も確認します。 | 使用パターン | 適合性 | |----------|-------| | PKで機器情報を検索 | 適している(PK使用) | | 非PK列でリスト検索 | セカンダリインデックス作成時に適している | | 少数の基準コードテーブル | 適している | | 全行がサーバーメモリに収まらない大規模マスターデータ | TRANSACTIONテーブルを検討 | | リレーショナルトランザクションが必要なマスターデータ | TRANSACTIONテーブルを検討 | ### VOLATILEとの区別 VOLATILEは、再起動時にデータが消失する別のテーブルタイプです。 インデックス設計は[VOLATILEのインデックスとパフォーマンス](/ja/dbms/volatile-table-usage/index-performance/)を参照してください。 ### 大容量のマスターデータが必要な場合 LOOKUPテーブルのサイズとセカンダリインデックスの更新コストを考慮し、次のシナリオでは代替方法を検討します。 **シナリオ**: 機器のマスターデータを複数列でフィルタリングし、変更履歴も保持する場合 ```sql -- 代替方法: LOGテーブル + LSM/BITMAPインデックス CREATE LOG TABLE ch9_index_device_hist ( device_id VARCHAR(64), device_name VARCHAR(128), location VARCHAR(256), category VARCHAR(32), updated_at DATETIME ); -- 非PK列にインデックスを作成可能 CREATE INDEX ch9_index_hist_location ON ch9_index_device_hist (location); CREATE INDEX ch9_index_hist_category ON ch9_index_device_hist (category) INDEX_TYPE BITMAP; ``` ただし、LOGテーブルは追加専用のため、マスターデータの更新パターンに合わせて設計する必要があります。 実習で使用したオブジェクトは、次のように削除します。 ```sql DROP TABLE ch9_index_device_hist; DROP INDEX ch9_index_device_location; DROP TABLE ch9_index_event; DROP TABLE ch9_index_device; ``` ### 要点 - PRIMARY KEYインデックスは自動作成されます。 - 繰り返す非PK条件にだけセカンダリインデックスを作成します。 - 行・可変長値・インデックスのメモリ、起動時間、更新負荷を併せて測定します。 --- title: "9.7 運用とデータライフサイクル" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/operations-lifecycle/ language: ja kind: page --- # 9.7 運用とデータライフサイクル LOOKUPテーブルのバックアップ・復旧とデータの永続性を説明します。 LOOKUPテーブルは、ディスクに永続保存される参照データテーブルです。 運用中に値が変わる場合があるため、変更手順、バックアップ、復旧、クエリへの反映時点を併せて管理します。 永続保存と検索時のデータの場所は区別する必要があります。 サーバー起動時に永続保存されたLOOKUPの全行をメモリテーブルへ復元し、`PRIMARY KEY`とセカンダリインデックスを構築します。 稼働中のSQLクエリはこのメモリ構造を使用します。 ## データライフサイクル LOOKUPデータは、作成、入力、更新、参照、バックアップ、復旧の流れで管理します。 ``` テーブル作成 └── マスターデータの入力 └── TAG/LOG/TRANSACTIONクエリでJOINまたは参照 └── 運用中のUPDATE/DELETE └── バックアップ / 復旧 / マウント ``` マスターデータは元のイベントより小規模ですが、クエリ結果の解釈に直接影響します。 そのため、変更前後の値と適用時点を記録する運用手順を設けます。 ## マスターデータの変更手順 運用中にLOOKUPデータを変更する場合は、次の順序で進めます。 1. 変更対象行を検索します。 2. 影響範囲を確認します。 3. UPDATEまたはDELETEを実行します。 4. 必要に応じて`EXEC TABLE_REFRESH(table_name)`を実行します。 5. 代表的なクエリで反映を確認します。 `TABLE_REFRESH`は、通常のSQL DMLの直後に毎回実行するコマンドではありません。 永続LOOKUPの内容を実行時のメモリテーブルに再反映する必要があるときに使用します。 名前の範囲・権限・エラー仕様は、[EXECプロシージャの正本](/ja/dbms/reference/sql/syntax/execute-procedure-syntax/#table-refresh)を参照してください。 次は、この手順をそのまま実行する実習です。 ```sql CREATE LOOKUP TABLE ch9_ops_sensor ( sensor_id VARCHAR(32) PRIMARY KEY, site VARCHAR(16), status VARCHAR(16), updated_at DATETIME ); INSERT INTO ch9_ops_sensor VALUES ('TEMP-01', 'SEOUL', 'READY', NOW); INSERT INTO ch9_ops_sensor VALUES ('TEMP-02', 'SEOUL', 'READY', NOW); INSERT INTO ch9_ops_sensor VALUES ('TEMP-03', 'BUSAN', 'READY', NOW); -- 変更対象を検索します。 SELECT sensor_id, site, status FROM ch9_ops_sensor WHERE sensor_id = 'TEMP-01'; -- 変更します。 UPDATE ch9_ops_sensor SET status = 'INACTIVE', updated_at = NOW WHERE sensor_id = 'TEMP-01'; -- 必要ならメモリテーブルに再反映します。 EXEC TABLE_REFRESH(ch9_ops_sensor); -- 代表的なクエリで確認します。 SELECT sensor_id, status FROM ch9_ops_sensor ORDER BY sensor_id; ``` TEMP-01だけが`INACTIVE`になり、残りの2行は`READY`のままです。 一括変更では、必ず先に対象件数を確認します。 ```sql SELECT COUNT(*) FROM ch9_ops_sensor WHERE site = 'SEOUL' AND status = 'READY'; ``` TEMP-01は変更済みのためCOUNTは1です。変更前に数えなければ、対象が変わります。 ```sql DROP TABLE ch9_ops_sensor; ``` ## バックアップ・復旧のサポート範囲 LOOKUPはディスクに永続保存され、データベースのバックアップに含まれます。 リストア後は行をメモリテーブルとインデックスに再構築します。 共通のBACKUP・RESTORE・MOUNTコマンドとEditionの範囲は、 [バックアップ・リストア・マウント](/ja/dbms/operations-configuration-recovery/backup-restore-mount/)を正本とします。 復旧後に代表的なキーとJOIN結果を検証してください。 ## 運用点検項目 - マスターデータの変更履歴を、別のログや運用手順で残します。 - 大量のUPDATE/DELETE前に対象件数を確認します。 - 頻繁にJOINする列にはインデックスを検討します。 - 実際のデータ規模で、サーバー起動時間とLOOKUPの行・インデックスのメモリ使用量を点検します。 - Appendの重複キー処理を使用する場合は、`LOOKUP_APPEND_UPDATE_ON_DUPKEY`設定を確認します。 - バックアップからの復旧後は、代表的なJOINクエリで参照結果を確認します。 --- title: "9.8 制約、エラー、トラブルシューティング" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/constraints-errors-troubleshooting/ language: ja kind: page --- # 9.8 制約、エラー、トラブルシューティング LOOKUPテーブルの制約、発生し得るエラー、解決方法を説明します。 ## 制約の概要 | 項目 | 制約 | 代表的なエラー | |---|---|---| | PRIMARY KEY | 必須。1つだけ指定 | `ERR-02322`, `ERR-02171` | | PRIMARY KEY列 | `SET`の対象に指定不可 | `ERR-02176` | | 列の型 | `TEXT`・`CLOB`・`BLOB`・`BINARY`は使用不可 | `ERR-02173` | | JSON列 | 一般列として使用可能。PRIMARY KEYには使用不可 | — | | メモリ | VOLATILEと1つの上限を共有 | `ERR-01344` | | UPDATE | `WHERE`必須。省略時は実行されない | — | ## PRIMARY KEYのエラー LOOKUPはPRIMARY KEYなしでは作成できず、2つ以上指定することもできません。 次の2文は、それぞれ失敗します。 ```sql -- 失敗: PRIMARY KEYがありません。(ERR-02322) CREATE LOOKUP TABLE ch9_err_nopk (code VARCHAR(16), label VARCHAR(64)); -- 失敗: PRIMARY KEYが2つあります。(ERR-02171) CREATE LOOKUP TABLE ch9_err_twopk ( code VARCHAR(16) PRIMARY KEY, name VARCHAR(32) PRIMARY KEY ); ``` どちらの文もテーブルを作成しないため、削除するオブジェクトはありません。 複合キーが必要なら、区切り文字で組み合わせた単一のキー列を用意し、 [PRIMARY KEYポリシー](../primary-key-policy/)の設計基準に従ってください。 PRIMARY KEY列の値は変更できません。 ```sql CREATE LOOKUP TABLE ch9_err_pk (code VARCHAR(16) PRIMARY KEY, label VARCHAR(64)); INSERT INTO ch9_err_pk VALUES ('KR', '대한민국'); -- 失敗: PRIMARY KEY列はSETの対象外です。(ERR-02176) UPDATE ch9_err_pk SET code = 'KO' WHERE code = 'KR'; ``` キーを変更する場合は、既存行を削除し、新しいキーで再入力します。 ## 未サポートの列型 `TEXT`、`CLOB`、`BLOB`、`BINARY`はLOOKUP列に使用できません。 長い文字列は`VARCHAR`で宣言し、原文の保持が必要ならLOGテーブルに分離します。 ```sql -- 失敗: 未サポートの列型です。(ERR-02173) ALTER TABLE ch9_err_pk ADD COLUMN (memo TEXT); ``` JSONは一般列として使用できます。 使用範囲は[JSON列とクエリ](../json-column-query/)を参照してください。 ```sql DROP TABLE ch9_err_pk; ``` ## メモリ上限 LOOKUPはディスクに永続保存されますが、クエリの実行経路はメモリです。 サーバー起動時に全行とインデックスをメモリへロードするため、使用量が上限を超えると`ERR-01344`が発生します。 この上限は**VOLATILEテーブルと共有します。** 設定名は`VOLATILE_`で始まりますが、LOOKUPも同じ上限に含まれるため、両タイプを併用する環境では合計で判断する必要があります。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME = 'VOLATILE_TABLESPACE_MEMORY_MAX_SIZE'; SELECT * FROM V$STORAGE_DC_VOLATILE_TABLE; ``` 上限に近づいたら、保持範囲の縮小や未使用のセカンダリインデックスの削除を行います。 大規模なマスターデータでは、[インデックスとパフォーマンス](../index-performance/)の基準に従って他のテーブルタイプを検討してください。 ## 複数行の変更範囲 一般述語のUPDATE/DELETEは、複数行に適用される場合があります。 実行前に同じ述語で対象数を確認し、[一般述語のUPDATE/DELETE](../predicate-update-delete/)の仕様に従ってください。 ## LOOKUPのJSON PRIMARY KEYエラー JSON列は一般列として使用できますが、PRIMARY KEYには宣言できません。 識別子を別のスカラー列に格納し、[JSON列とクエリ](../json-column-query/)の型・パス規則に従ってください。 ## 制約と注意事項 - PRIMARY KEYのポリシーは、[PRIMARY KEYポリシー](../primary-key-policy/)を参照してください。 - メモリ規模とインデックスのコストは、[インデックスとパフォーマンス](../index-performance/)で測定します。 - 時系列の元データにはTAG、再起動後に消えてもよいキャッシュにはVOLATILEを選択します。 - Appendの使用条件は、[SDK Append対応表](/ja/dbms/development-tools-integration/sdk-support-scope/#append-table-type-matrix)に従います。 --- title: "9.9 活用パターンとシナリオ" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/patterns-scenarios/ language: ja kind: page --- # 9.9 活用パターンとシナリオ LOOKUPテーブルの活用パターンとシナリオを説明します。 ## 活用例 LOOKUPテーブルは、次のようなデータの保存に適しています。 ## 適したデータの種類 | 種類 | 例 | |------|------| | コードテーブル | 国コード、言語コード、状態コード | | マスターデータ | 設備一覧、製品分類、部門情報 | | リアルタイム更新の参照データ | 為替レートテーブル、しきい値設定 | | タグメタデータの代替 | センサー情報(小規模) | ## コードテーブル ```sql CREATE LOOKUP TABLE ch9_pattern_country ( code VARCHAR(4) PRIMARY KEY, name VARCHAR(64), region VARCHAR(32) ); INSERT INTO ch9_pattern_country VALUES ('KR', '대한민국', 'Asia'); INSERT INTO ch9_pattern_country VALUES ('US', '미국', 'America'); UPDATE ch9_pattern_country SET name = 'United States' WHERE code = 'US'; SELECT code, name FROM ch9_pattern_country ORDER BY code; ``` 2行が返され、US行のnameだけが`United States`に変わっています。 状態コードやアラームコードも同じ方法で管理し、元のイベントとJOINして使用します。 ```sql CREATE LOOKUP TABLE ch9_pattern_status ( code VARCHAR(16) PRIMARY KEY, label VARCHAR(64), color VARCHAR(16) ); INSERT INTO ch9_pattern_status VALUES ('RUN', '가동', 'green'); INSERT INTO ch9_pattern_status VALUES ('STOP', '정지', 'red'); CREATE LOG TABLE ch9_pattern_event ( event_time DATETIME, device_id VARCHAR(64), status VARCHAR(16) ); INSERT INTO ch9_pattern_event VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'DEV-01', 'RUN'); INSERT INTO ch9_pattern_event VALUES (TO_DATE('2026-01-01 10:05:00', 'YYYY-MM-DD HH24:MI:SS'), 'DEV-01', 'STOP'); EXEC TABLE_FLUSH(ch9_pattern_event); SELECT e.event_time, e.device_id, c.label FROM ch9_pattern_event e JOIN ch9_pattern_status c ON e.status = c.code ORDER BY e.event_time; ``` 2行がコードの代わりに`가동`(稼働)・`정지`(停止)のラベルで返されます。 コードにない状態がイベントに含まれるとINNER JOINでその行が除外されるため、コードテーブルの欠落も点検します。 ## 設備マスター ```sql CREATE LOOKUP TABLE ch9_pattern_equip ( equip_id VARCHAR(32) PRIMARY KEY, equip_name VARCHAR(128), location VARCHAR(64), dept VARCHAR(64), install_dt DATETIME ); INSERT INTO ch9_pattern_equip VALUES ('TEMP-01', 'Boiler', 'Seoul', 'Production', TO_DATE('2025-01-01', 'YYYY-MM-DD')); INSERT INTO ch9_pattern_equip VALUES ('TEMP-02', 'Chiller', 'Busan', 'Facility', TO_DATE('2025-01-01', 'YYYY-MM-DD')); ``` TAGテーブルのセンサーデータとJOINすると、場所や部門などのマスターデータも検索できます。 ```sql CREATE TAG TABLE ch9_pattern_sensor ( name VARCHAR(32) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); INSERT INTO ch9_pattern_sensor VALUES ('TEMP-01', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 90.0); INSERT INTO ch9_pattern_sensor VALUES ('TEMP-02', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 20.0); EXEC TABLE_FLUSH(ch9_pattern_sensor); SELECT d.name, m.location, m.dept, d.value FROM ch9_pattern_sensor d JOIN ch9_pattern_equip m ON d.name = m.equip_id WHERE m.dept = 'Production' ORDER BY d.name; ``` TEMP-01の1行だけが返されます。部門条件はLOOKUP側の列に適用されるため、 条件を変更すると、読み取るTAGの元データが同じでも結果集合が変わります。 ## しきい値設定 ```sql CREATE LOOKUP TABLE ch9_pattern_threshold ( sensor_name VARCHAR(64) PRIMARY KEY, low_limit DOUBLE, high_limit DOUBLE, alert_level SHORT ); INSERT INTO ch9_pattern_threshold VALUES ('TEMP-01', 0.0, 100.0, 1); INSERT INTO ch9_pattern_threshold VALUES ('TEMP-02', 0.0, 100.0, 1); -- リアルタイムのしきい値変更 UPDATE ch9_pattern_threshold SET high_limit = 85.0 WHERE sensor_name = 'TEMP-01'; ``` しきい値テーブルは、TAGデータと結合してアラーム条件を判定するために使用します。 ```sql SELECT s.name, s.value, t.high_limit FROM ch9_pattern_sensor s JOIN ch9_pattern_threshold t ON s.name = t.sensor_name WHERE s.value > t.high_limit ORDER BY s.name; ``` TEMP-01だけが超過と判定されます。値90は変更前の上限100では正常でした。 同じ元データでもしきい値の変更時点によって判定が変わることを、併せて記録してください。 ## SEQUENCEによる履歴番号 小規模な管理履歴や運用イベントに連番が必要なら、SEQUENCE列を使用できます。 ```sql CREATE LOOKUP TABLE ch9_pattern_note ( seq LONG PROPERTY(SEQUENCE=1) PRIMARY KEY, target_id VARCHAR(64), note VARCHAR(512), created_at DATETIME ); INSERT INTO ch9_pattern_note VALUES (NEXTVAL(seq), 'TEMP-01', 'threshold changed', NOW); INSERT INTO ch9_pattern_note VALUES (NEXTVAL(seq), 'TEMP-02', 'inspection done', NOW); SELECT seq, target_id FROM ch9_pattern_note ORDER BY seq; ``` seqは1と2です。大量の元履歴データは、LOOKUPよりLOGテーブルに保存してください。 このページの実習オブジェクトは、次のように削除します。 ```sql DROP TABLE ch9_pattern_note; DROP TABLE ch9_pattern_threshold; DROP TABLE ch9_pattern_sensor; DROP TABLE ch9_pattern_equip; DROP TABLE ch9_pattern_event; DROP TABLE ch9_pattern_status; DROP TABLE ch9_pattern_country; ``` ## 適さない場合 - 明示的トランザクションと一般的なリレーショナルDMLが必要なデータ → TRANSACTIONテーブルを推奨 - UPDATEが不要な追加専用の履歴 → LOGテーブルを推奨 - センサー計測値 → TAGテーブルを推奨 - 再起動後に消えてもよい最新状態キャッシュ → VOLATILEテーブルを推奨 --- title: "9.10 PRIMARY KEYポリシー" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/primary-key-policy/ language: ja kind: page --- # 9.10 PRIMARY KEYポリシー LOOKUPテーブルのPRIMARY KEY設計原則とポリシーを説明します。 SDKがSELECT結果からPKを判定する方法は、 [PRIMARY KEYメタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-primary-key-metadata)を参照してください。 ## PRIMARY KEYの設計 LOOKUPテーブルには`PRIMARY KEY`が必須です。 PRIMARY KEYは行を一意に識別し、重複入力を制御します。 UPDATEとDELETEの`WHERE`句には一般条件式を使用できますが、PRIMARY KEY列自体はUPDATEできません。 ### 基本構文 ```text CREATE LOOKUP TABLE table_name ( pk_col type PRIMARY KEY, col2 type, ... ); ``` ### 単一列のPRIMARY KEY ```sql CREATE LOOKUP TABLE ch9_pk_country_code ( code VARCHAR(4) PRIMARY KEY, name VARCHAR(64), region VARCHAR(32) ); ``` ### 複合キーが必要な場合 ```sql CREATE LOOKUP TABLE ch9_pk_price ( price_key VARCHAR(64) PRIMARY KEY, product_id VARCHAR(32), region VARCHAR(16), price DOUBLE ); -- 挿入 INSERT INTO ch9_pk_price VALUES ('PROD-01:KR', 'PROD-01', 'KR', 99.0); INSERT INTO ch9_pk_price VALUES ('PROD-01:US', 'PROD-01', 'US', 79.0); -- 組み合わせキーによるUPDATE UPDATE ch9_pk_price SET price = 89.0 WHERE price_key = 'PROD-01:KR'; ``` LOOKUPテーブルにはPRIMARY KEY列を1つだけ指定できます。 複数列の組み合わせが業務キーの場合は、組み合わせた文字列または代理キーを別のPRIMARY KEY列に格納します。 ### PRIMARY KEYの型の選択 | 型 | 利点 | 欠点 | |------|------|------| | `VARCHAR(n)` | 可読性が高く、意味のあるキー | 文字列の比較コスト | | `INTEGER` / `LONG` | 比較が高速で保存効率がよい | 意味を持たず、別のマッピングが必要 | ### 注意事項 - PRIMARY KEY値は重複できません。 - PRIMARY KEY値は変更できません(変更時はDELETE + INSERT)。 - PRIMARY KEY列にはインデックスが自動作成されます。 - PRIMARY KEY列は1つだけ指定します。 ## PRIMARY KEYポリシー PRIMARY KEY設計で考慮するポリシーと推奨方法を説明します。 ### 自然キーと代理キー #### 自然キー(Natural Key) 業務上の意味を持つ値を、そのままPRIMARY KEYに使用します。 ```sql -- 国コード: 標準化された自然キー CREATE LOOKUP TABLE ch9_pk_country ( iso_code VARCHAR(4) PRIMARY KEY, -- ISO 3166-1 alpha-2 name VARCHAR(64) ); ``` **利点**: 意味を理解しやすく、別の検索が不要 **欠点**: キー変更時に参照整合性の問題が発生 #### 代理キー(Surrogate Key) SEQUENCE列やUUIDなど、業務上の意味を持たない値をPRIMARY KEYに使用します。 ```sql -- 設備マスター: 代理キー CREATE LOOKUP TABLE ch9_pk_equip ( equip_id LONG PROPERTY(SEQUENCE=1) PRIMARY KEY, code VARCHAR(32), -- 業務キー name VARCHAR(128) ); CREATE INDEX ch9_pk_equip_idx ON ch9_pk_equip(code); ``` **利点**: 不変で、結合が効率的 **欠点**: コードとIDの変換が必要 ### PRIMARY KEY不変の原則 PRIMARY KEY値はUPDATEできません。変更が必要ならDELETE + INSERTを使用します。 ```sql -- 誤ったパターン(PK変更はDELETE + INSERTで実行) -- UPDATEではPKを変更できません -- 正しいパターン DELETE FROM ch9_pk_country WHERE iso_code = 'OLD'; INSERT INTO ch9_pk_country VALUES ('NEW', '새 국가명'); ``` LOOKUPテーブルのDMLは個々の文単位で実行します。 `BEGIN`/`COMMIT`でまとめるTRANSACTIONトランザクションに、LOOKUPのDMLを含めることはできません。 したがって、2文の間の検索や挿入失敗に備える必要があります。 既存値を保持し、参照キーの切り替え順序を決めてから変更してください。 変更全体のアトミック性が必要なら、TRANSACTIONテーブルを検討します。 このページの実習テーブルは、次のように削除します。 ```sql DROP INDEX ch9_pk_equip_idx; DROP TABLE ch9_pk_equip; DROP TABLE ch9_pk_country; DROP TABLE ch9_pk_price; DROP TABLE ch9_pk_country_code; ``` --- title: "9.11 SEQUENCE列" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/sequence-column/ language: ja kind: page --- # 9.11 SEQUENCE列 LOOKUPテーブルのSEQUENCE列の設定と活用を説明します。 ## LOOKUPのSEQUENCE列の定義 SEQUENCE列は、`NEXTVAL`で入力番号を生成するために使用します。 LOOKUPテーブルは[PRIMARY KEYが必須](../primary-key-policy/)のため、 SEQUENCE列自体をPRIMARY KEYにするか、他の列をPRIMARY KEYにするかも決めます。 この番号を、イベント発生時刻の順序と同じものとして解釈しないでください。 ## SEQUENCE列が必要な理由 同時刻に発生したアラームや管理履歴を、別々の行として識別する場合に使用できます。 LOOKUPは全行をメモリに保持するため、この例は小規模な管理履歴を対象とします。 長期間蓄積する大量イベントには、LOGテーブルを検討してください。 ## SEQUENCE列の宣言 SEQUENCEは`LONG`または`INT64`型の列に指定できます。 PROPERTY句の`SEQUENCE`パラメーターで開始値を設定します。この属性はLOOKUPテーブルだけで使用できます。 ```sql CREATE LOOKUP TABLE ch9_sequence ( seq LONG PROPERTY(SEQUENCE=1) PRIMARY KEY, sensor_id VARCHAR(40), alarm_type VARCHAR(20), occurred_at DATETIME, message VARCHAR(200) ); ``` - `SEQUENCE=1`: seq列が1から自動増分します。 - 開始値は1以上4,294,967,295未満の整数だけを指定できます。 - 上の例のようにSEQUENCE列をPRIMARY KEYにすると、番号の一意性も保証されます。 ## SEQUENCE値の挿入: NEXTVAL() サーバーはSEQUENCE列ごとに次に使用する番号をカウンターで保持し、`NEXTVAL()`はその値を取得して挿入します。 毎回テーブルの最大値を再計算することはありません。 ```sql -- NEXTVAL()で自動増分値を入力 INSERT INTO ch9_sequence (seq, sensor_id, alarm_type, occurred_at, message) VALUES (NEXTVAL(seq), 'TEMP-01', 'HIGH', NOW, '온도 초과'); INSERT INTO ch9_sequence (seq, sensor_id, alarm_type, occurred_at, message) VALUES (NEXTVAL(seq), 'PRESS-02', 'LOW', NOW, '압력 저하'); -- 検索 SELECT * FROM ch9_sequence ORDER BY seq; -- seq=1、seq=2の順にソート ``` ## 一般列と同様の直接値指定 SEQUENCE列に値を直接入力することもできます。 入力値が現在のカウンターより大きければ、カウンターは`入力値 + 1`に進みます。 現在のカウンターより小さい値を入力しても、カウンターは減少しません。 ```sql -- 値を直接指定(nextvalは不要) INSERT INTO ch9_sequence (seq, sensor_id, alarm_type, occurred_at, message) VALUES (100, 'FLOW-03', 'NORMAL', NOW, '정상 복구'); -- 以後のNEXTVAL()呼び出しは101になります INSERT INTO ch9_sequence (seq, sensor_id, alarm_type, occurred_at, message) VALUES (NEXTVAL(seq), 'TEMP-01', 'NORMAL', NOW, '온도 정상'); -- seq = 101 ``` ## 活用パターン ```sql -- 最新アラームN件を検索 SELECT * FROM ch9_sequence ORDER BY seq DESC LIMIT 10; -- 特定のseq以降のアラームを検索 SELECT * FROM ch9_sequence WHERE seq > 500 ORDER BY seq; -- アラーム確認処理(PKによるUPDATE) UPDATE ch9_sequence SET alarm_type = 'ACKNOWLEDGED' WHERE seq = 101; ``` 実習テーブルは、次のように削除します。 ```sql DROP TABLE ch9_sequence; ``` ## 注意事項 - SEQUENCE列は`LONG`、`INT64`型をサポートします。 - 開始値は正数(`SEQUENCE=1`以上)のみ許可され、4,294,967,295未満である必要があります。 - カウンターはサーバーに保存され、増加方向だけに進みます。最大のseq行をDELETEしても番号は再使用されないため、欠番が生じる場合があります。 - SEQUENCE列をPRIMARY KEYにしない場合、`NEXTVAL()`を使わずに重複値を直接入力できます。 番号の一意性が必要なら、この列をPRIMARY KEYに指定してください。 --- title: "9.12 JSON列とJSONクエリ" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/json-column-query/ language: ja kind: page --- # 9.12 JSON列とJSONクエリ LOOKUPテーブルのJSON列のサポート範囲と、JSON条件によるクエリを説明します。 ## LOOKUPのJSON条件検索 LOOKUPテーブルは、`JSON`列を一般列としてサポートします。 JSON列は、可変的な属性値を参照データと一緒に保存する場合に使用できます。 ```sql CREATE LOOKUP TABLE ch9_json ( sensor_id VARCHAR(80) PRIMARY KEY, location VARCHAR(200), config JSON ); INSERT INTO ch9_json VALUES ( 'TEMP-01', 'factory1', '{"unit":"celsius","level":3,"threshold":{"high":90.0}}' ); SELECT sensor_id, config FROM ch9_json WHERE config->'$.unit' = 'celsius'; ``` ## 型別のJSON条件 数値を数値として比較する場合は、型別のJSON抽出関数を使用します。 ```sql SELECT sensor_id FROM ch9_json WHERE JSON_EXTRACT_INTEGER(config, '$.level') >= 3 AND JSON_EXTRACT_DOUBLE(config, '$.threshold.high') > 80.0; ``` JSON構造自体も確認できます。 ```sql SELECT sensor_id FROM ch9_json WHERE JSON_IS_VALID(config) = 1 AND JSON_TYPEOF(config, '$.threshold') = 'Object'; ``` ## PRIMARY KEYの制約 LOOKUPテーブルはJSON列を保存できますが、JSON列を`PRIMARY KEY`には使用できません。 行識別子には、`INTEGER`、`LONG`、`VARCHAR`などの安定した一般型を使用します。 ```sql -- 失敗: JSON列はPRIMARY KEYに使用できません。 CREATE LOOKUP TABLE ch9_json_bad ( config JSON PRIMARY KEY, note VARCHAR(80) ); ``` ```sql -- 推奨: 別の識別子をPRIMARY KEYに使用します。 CREATE LOOKUP TABLE ch9_json_ok ( sensor_id VARCHAR(80) PRIMARY KEY, config JSON, note VARCHAR(80) ); ``` ## 設計基準 | 状況 | 推奨方法 | |------|----------| | 結合・検索で頻繁に使用する値 | 別の列 | | 機器ごとに異なる可変属性 | JSON列 | | 数値条件検索 | 一般の数値列に分離 | | PRIMARY KEY | 安定した識別子列を使用 | | 高頻度のパス検索 | 別の列に抽出 | JSONパスごとの専用インデックスはサポートしていません。 高頻度の検索条件は別の列に分離し、その列にインデックスを適用する設計を先に検討してください。 ```sql CREATE LOOKUP TABLE ch9_json_fast ( sensor_id VARCHAR(80) PRIMARY KEY, unit VARCHAR(16), level INTEGER, config JSON ); CREATE INDEX ch9_json_unit_idx ON ch9_json_fast(unit); ``` ## UPDATE・DELETEの条件 ```sql UPDATE ch9_json SET location = 'factory2' WHERE config->'$.unit' = 'celsius'; DELETE FROM ch9_json WHERE JSON_EXTRACT_INTEGER(config, '$.level') < 2; ``` 対象範囲が広くなる場合があるため、UPDATE/DELETE前に同じ条件で件数を確認します。 このページの実習オブジェクトは、次のように削除します。 `ch9_json_bad`は作成に失敗する例なので、削除対象ではありません。 ```sql DROP TABLE ch9_json_fast; DROP TABLE ch9_json_ok; DROP TABLE ch9_json; ``` ## 注意事項 - LOOKUPテーブルは、JSON列を一般列としてサポートします。 - JSON列はPRIMARY KEYには使用できません。 - JSONパスごとの専用インデックスはサポートしていません。 - 頻繁に検索する値は、LOOKUPの一般列に分離します。 - JSONパスインデックスが必要なら、TRANSACTIONまたはTAGテーブルを検討します。 --- title: "9.13 一般述語のUPDATE/DELETE" url: https://docs.machbase.com/ja/dbms/lookup-table-usage/predicate-update-delete/ language: ja kind: page --- # 9.13 一般述語のUPDATE/DELETE LOOKUPテーブルは、主キーだけでなく一般条件式で複数行を更新・削除できます。 変更前に同じ条件で対象行数を確認してください。 このページの実習は、次の1つのテーブルで進め、最後に削除します。 ```sql CREATE LOOKUP TABLE ch9_predicate ( equip_id VARCHAR(32) PRIMARY KEY, site VARCHAR(16), status VARCHAR(16), score INTEGER ); INSERT INTO ch9_predicate VALUES ('EQ-01', 'SEOUL', 'READY', 10); INSERT INTO ch9_predicate VALUES ('EQ-02', 'SEOUL', 'READY', 20); INSERT INTO ch9_predicate VALUES ('EQ-03', 'SEOUL', 'RETIRED', 30); INSERT INTO ch9_predicate VALUES ('EQ-04', 'BUSAN', 'READY', 40); ``` ## UPDATE 条件に一致するすべての行を更新します。 `SET`式は現在の行値を参照できますが、主キー列自体は変更できません。 LOOKUP UPDATEには`WHERE`条件が必要です。 全行を更新する場合でも、サポートされる条件式を明示してください。 `WHERE`なしで全件削除できるDELETEとは区別してください。 ```sql -- 変更前に影響範囲を数えます。 SELECT COUNT(*) FROM ch9_predicate WHERE site = 'SEOUL' AND status = 'READY'; UPDATE ch9_predicate SET status = 'ACTIVE', score = score + 10 WHERE site = 'SEOUL' AND status = 'READY'; SELECT equip_id, site, status, score FROM ch9_predicate ORDER BY equip_id; ``` COUNTは2で、EQ-01とEQ-02だけが`ACTIVE`に変わり、scoreは20・30になります。 同じSEOULでもstatusが異なるEQ-03、同じREADYでもsiteが異なるEQ-04は変わりません。 ## DELETE 条件に一致するすべての行を削除します。 `WHERE`を省略すると、テーブルの全行が削除されます。 ```sql SELECT COUNT(*) FROM ch9_predicate WHERE status = 'RETIRED'; DELETE FROM ch9_predicate WHERE status = 'RETIRED'; SELECT equip_id, status FROM ch9_predicate ORDER BY equip_id; ``` COUNTは1で、EQ-03が削除されて3行が残ります。 ## 条件の設計指針 1. 単一行の変更には主キー条件を使用します。 2. 一括変更前に、同じ条件の`SELECT COUNT(*)`で影響範囲を確認します。 3. 頻繁にフィルタリングするJSON値は、一般列に分離してインデックスを適用する方法を検討します。 4. 主キーを変更する場合は、既存行を削除して新しいキーで挿入します。 サポートされる演算子とJSON条件の正確な範囲は、SQLリファレンスで確認してください。 - [LOOKUPの述語UPDATE](/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-update-syntax/) - [LOOKUPの述語DELETE](/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-delete-syntax/) ## 権限とパフォーマンス UPDATEとDELETEには、それぞれ対象テーブルの`UPDATE`、`DELETE`権限が必要です。 アプリケーションが変更前後の値を直接検索する場合だけ、`SELECT`も付与します。 権限SQLの正本は[権限管理](/ja/dbms/security-access-control/privileges/)です。 主キーの等価条件は単一行を直接検索し、一般条件式は条件を評価して変更対象を収集します。 繰り返す単一行の変更には、プリペアドステートメントとバインドを使用します。 大量変更は、同じ条件の行数と実行時間を検証環境で測定してください。 ```sql DROP TABLE ch9_predicate; ``` --- title: "10. VOLATILEテーブルの活用" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/ language: ja kind: section --- # 10. VOLATILEテーブルの活用 VOLATILEテーブルは、サーバープロセス内で共有されるメモリテーブルです。 再起動時のデータ消失、UPSERT、再作成可能なキャッシュパターンを説明します。 ## この章の構成 | 節 | 内容 | |----|------| | [概要と選択基準](./overview-use-criteria/) | VOLATILEテーブルの特性と適用判断基準 | | [テーブル構造とスキーマ](./table-structure-schema/) | PRIMARY KEY設計、列の型、スキーマ構成 | | [作成、変更、削除](./create-alter-drop/) | CREATE VOLATILE TABLE、DROP、永続性の違い | | [データ入力と変更](./data-input-mutation/) | INSERT、ON DUPLICATE KEY UPDATE、DELETE | | [クエリと分析](./query-analysis/) | SELECT、条件検索、LIKE | | [インデックスとパフォーマンス](./index-performance/) | 赤黒木インデックス、PKインデックス | | [運用とデータライフサイクル](./operations-lifecycle/) | 運用手順とデータ管理 | | [制約、エラー、トラブルシューティング](./constraints-errors-troubleshooting/) | 機能制約とエラー対応 | --- title: "10.1 概要と選択基準" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/overview-use-criteria/ language: ja kind: page --- # 10.1 概要と選択基準 VOLATILEテーブルは、データをメモリに保存する一時テーブルです。 サーバーを再起動するとデータが消失するため、再作成可能な最新状態、一時集計、セッション間の共有キャッシュに使用します。 ## VOLATILEテーブルの特性 VOLATILEテーブルは`CREATE VOLATILE TABLE`文で作成します。 ```sql CREATE VOLATILE TABLE ch10_overview ( sensor_id VARCHAR(64) PRIMARY KEY, value DOUBLE, updated_at DATETIME ); ``` VOLATILEテーブルの主な特性は次のとおりです。 | 項目 | 内容 | |------|------| | 主な用途 | 最新状態のキャッシュ、一時集計、中間結果 | | 保存場所 | メモリ | | 再起動後のデータ | 消失 | | 共有範囲 | サーバー全体で共有 | | キー | PRIMARY KEYは任意 | | 主な機能 | UPDATE、DELETE、`ON DUPLICATE KEY UPDATE`、赤黒木インデックス | | バックアップ | 未サポート | ## 選択基準 次の条件に該当する場合は、VOLATILEテーブルを使用します。 - サーバー再起動後にデータが失われても問題がない。 - 元データからいつでも再計算または再構築できる。 - 最新状態、直近の集計、一時処理結果を高速に検索する必要がある。 - 複数のセッションで同じ一時状態を共有する必要がある。 - ディスクの永続性より、メモリによる応答時間を重視する。 最新のセンサー状態を維持する例は次のとおりです。 ```sql INSERT INTO ch10_overview VALUES ('TEMP-01', 23.5, NOW) ON DUPLICATE KEY UPDATE SET value = 23.5, updated_at = NOW; SELECT * FROM ch10_overview WHERE sensor_id = 'TEMP-01'; -- 次の節で同じ名前を使うため、削除します。 DROP TABLE ch10_overview; ``` ### 活用パターン | パターン | key | 再作成元 | 推奨する期限管理方法 | |------|-----|-------------|----------------| | 機器の最新状態 | 機器ID | TAGまたはLOG | 同じkeyを更新 | | 短周期の集計 | 対象と時間bucket | TAGまたはLOG | bucketの置き換えまたは再構築 | | 処理の進行状態 | ジョブID | ジョブシステム | 完了後にkeyを削除 | | 一時クエリキャッシュ | リクエストまたはオブジェクトID | 永続テーブル | 全体を再構築 | 最新状態の更新は[データ入力と変更](../data-input-mutation/)、 一時集計は[クエリと分析](../query-analysis/)を参照してください。 ## 他のテーブルを検討する場合 次の要件には、他のテーブルタイプを使用します。 | 要件 | 推奨テーブル | |----------|-------------| | 再起動後も必ず保持する元データ | TAGまたはLOG | | 基準コードや機器マスターなどの永続的な参照データ | LOOKUP | | トランザクションとリレーショナルな更新が必要な業務データ | TRANSACTION | | 長期分析対象の時系列データ | TAG | VOLATILEテーブルだけに保存したデータは、サーバー終了時に復旧できません。 重要なデータはTAG、LOG、LOOKUP、TRANSACTIONから適切な永続テーブルを選んで保存し、 VOLATILEテーブルはキャッシュや中間結果に使用します。 ## 設計手順 VOLATILEテーブルの設計では、次の順序で決定します。 1. データを再作成できることを確認します。 2. PRIMARY KEYが必要かを決めます。 3. 想定行数とメモリ使用量を見積もります。 4. 再起動後の初期ロード手順を用意します。 5. 保持が必要な結果は、アプリケーションの明示的な書き込みで永続テーブルに保存します。 VOLATILEを永続化する専用のflushコマンドはありません。 スキーマとPRIMARY KEYの設計は[テーブル構造とスキーマ](/ja/dbms/volatile-table-usage/table-structure-schema/)、 再起動への対応は[再起動とデータ消失](/ja/dbms/volatile-table-usage/operations-lifecycle/)で説明します。 --- title: "10.2 テーブル構造とスキーマ" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/table-structure-schema/ language: ja kind: page --- # 10.2 テーブル構造とスキーマ VOLATILEテーブルのPRIMARY KEY設計とスキーマ構成を説明します。 ## PRIMARY KEYの設計 VOLATILEテーブルはPRIMARY KEYなしでも作成できます。 ただし、PKによる検索や`ON DUPLICATE KEY UPDATE`を使用するにはPRIMARY KEYが必要です。 ### 単一のPRIMARY KEY ```sql CREATE VOLATILE TABLE ch10_schema_state ( device_id VARCHAR(32) PRIMARY KEY, state VARCHAR(16), updated_at DATETIME ); ``` ### 複合キーが必要な場合 複数列の組み合わせで行を一意に識別する必要がある場合は、組み合わせたキーを別のPRIMARY KEY列に格納します。 ```sql CREATE VOLATILE TABLE ch10_schema_hourly ( key_id VARCHAR(96) PRIMARY KEY, sensor_id VARCHAR(64), hour_ts DATETIME, avg_value DOUBLE, sample_cnt INTEGER ); -- 組み合わせキーの挿入 INSERT INTO ch10_schema_hourly VALUES ('TEMP-01:2026010110', 'TEMP-01', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 23.5, 60); INSERT INTO ch10_schema_hourly VALUES ('TEMP-01:2026010111', 'TEMP-01', TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 24.1, 60); INSERT INTO ch10_schema_hourly VALUES ('TEMP-02:2026010110', 'TEMP-02', TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 21.0, 60); -- 組み合わせキーの検索 SELECT sensor_id, avg_value FROM ch10_schema_hourly WHERE key_id = 'TEMP-01:2026010110'; ``` ### ON DUPLICATE KEY UPDATEとの併用 ```sql -- PRIMARY KEY重複時にUPDATEを実行 INSERT INTO ch10_schema_state VALUES ('DEV-01', 'ONLINE', NOW) ON DUPLICATE KEY UPDATE SET state = 'ONLINE', updated_at = NOW; ``` ### 注意事項 - PRIMARY KEYなしでも作成できますが、PKに基づく操作(UPSERT、PK検索など)は使用できません。 - 同じPRIMARY KEYを持つ行を複数保存することはできません。`ON DUPLICATE KEY UPDATE`は、 重複行を追加する代わりに既存行を更新します。 - PRIMARY KEY列は1つだけ指定します。 ## VOLATILEテーブルの設計 VOLATILEテーブルはデータをメモリだけに保持し、サーバー再起動時にデータが消失します。 テーブル定義は残るため、設計では「何を失ってもよいか」と「どのように再充填するか」を決めます。 複数セッションで共有し、再起動後に復旧する必要がない状態やキャッシュに使用します。 スキーマを決めるときは、次の項目も検討してください。 - [活用例](../overview-use-criteria/#use-cases-volatile) - [永続性の違いとDDL](../create-alter-drop/#differences-persistence-ddl) - [メモリのライフサイクル](../operations-lifecycle/#lifecycle-memory) - [赤黒木インデックス](../index-performance/#index-strategy-red-black) - [ON DUPLICATE KEY UPDATE](../data-input-mutation/#on-duplicate-key-update) - [再起動とデータ再構築](../operations-lifecycle/#data-loss) このページの実習テーブルは、次のように削除します。 ```sql DROP TABLE ch10_schema_hourly; DROP TABLE ch10_schema_state; ``` --- title: "10.3 作成、変更、削除" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/create-alter-drop/ language: ja kind: page --- # 10.3 作成、変更、削除 VOLATILEテーブルの作成・削除と、他のテーブルタイプとの永続性の違いを説明します。 ## VOLATILEテーブルの作成と管理 VOLATILEテーブルの作成・削除方法は次のとおりです。 ### 作成 ```sql create volatile table vtable (id1 integer, name varchar(20)); ``` ### 削除 ```sql drop table vtable; ``` ## 永続性の違いとDDL VOLATILEテーブルは、他のテーブルタイプと異なりメモリにのみ存在します。 ### 永続性の比較 | 項目 | VOLATILE | LOOKUP | TRANSACTION | TAG | LOG | |------|----------|--------|-----|-----|-----| | 保存場所 | メモリ | ディスク | ディスク | ディスク | ディスク | | サーバー再起動後のデータ保持 | X | O | O | O | O | | テーブル構造(DDL)の保持 | O | O | O | O | O | ### DDLの特性 VOLATILEで消失するのはデータであり、テーブル定義は他のテーブルタイプと同様に永続保存されます。 再起動後に必要なのは、再作成ではなく初期ロードです。 ```sql -- テーブル定義は一度だけ作成します。 CREATE VOLATILE TABLE ch10_ddl ( sensor_id VARCHAR(64) PRIMARY KEY, value DOUBLE, updated_at DATETIME ); ``` ### 作成構文 基本構文は`CREATE VOLATILE TABLE テーブル名 (列定義, ...)`です。 キーによる更新や削除が必要な場合は、1つの列に`PRIMARY KEY`を指定します。 - `PRIMARY KEY`は任意です。 - PRIMARY KEY列は1つだけ指定します。 ### AUTO_INCREMENT PRIMARY KEY サーバーが数値のPRIMARY KEYを生成する場合は、単一の`LONG`または`INT64`列に`AUTO_INCREMENT`を指定します。 ```sql CREATE VOLATILE TABLE ch10_ddl_seq ( request_id LONG PRIMARY KEY AUTO_INCREMENT, payload VARCHAR(256) ); INSERT INTO ch10_ddl_seq(payload) VALUES('refresh'); ``` PK列を省略するかNULLを指定すると、サーバーが値を生成します。 単一の`INSERT ... VALUES`では、`0..INT64_MAX`範囲のPK値を直接指定することもできます。 指定値が現在の次の自動値以上なら、次の自動値は`指定値 + 1`に進みます。小さい値を指定しても戻りません。 AUTO_INCREMENTを使用するVOLATILEテーブルでは、`INSERT ... SELECT`と`ON DUPLICATE KEY UPDATE`は使用できません。 VOLATILEテーブルはサーバー再起動時にデータが消えるため、次の自動値も1から再開します。 テーブル定義は保持されるため、再作成は不要です。 SDKでINSERT結果のIDを取得する方法は、[ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ### 列の追加と削除 Standard Editionでは、VOLATILEテーブルに固定長の数値ARRAY列を追加・削除できます。 ```sql ALTER TABLE ch10_ddl ADD COLUMN (thresholds DOUBLE[2] DEFAULT [10.0, 20.0]); ALTER TABLE ch10_ddl DROP COLUMN (thresholds); ``` VOLATILEは既存のスカラー`ADD COLUMN`と同様に、ALTER前から存在する行をDEFAULTで書き直しません。 ARRAY DEFAULTを指定しても、既存行の新しい列は列全体がNULLになります。 この動作は、LOG、LOOKUP、TRANSACTION、TAG METADATAのバックフィル規則とは異なります。 ARRAYのサポート要素型、要素数、DEFAULT規則は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ### 削除 ```sql DROP TABLE ch10_ddl; DROP TABLE ch10_ddl_seq; ``` ### 注意事項 - VOLATILEテーブルのDDL(構造定義)はデータベースに保存され、サーバー再起動後も残ります。 - データは再起動後に自動復元されないため、初期ロードスクリプト(起動時のmachsql実行など)を構成する必要があります。 --- title: "10.4 データ入力と変更" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/data-input-mutation/ language: ja kind: page --- # 10.4 データ入力と変更 VOLATILEテーブルの`INSERT`、重複キー更新、`DELETE`を、実行可能な例で説明します。 ## データ入力と更新 次の例は、最後のクリーンアップ文まで順に実行できます。 最新状態のように同じキーの値を継続的に更新する場合は、`PRIMARY KEY`を定義し、`ON DUPLICATE KEY UPDATE`を使用します。 ```sql CREATE VOLATILE TABLE ch10_mutation ( id INTEGER PRIMARY KEY, direction VARCHAR(10), refcnt INTEGER ); INSERT INTO ch10_mutation VALUES (1, 'west', 0); INSERT INTO ch10_mutation VALUES (2, 'east', 0); INSERT INTO ch10_mutation VALUES (1, 'south', 0) ON DUPLICATE KEY UPDATE; INSERT INTO ch10_mutation VALUES (1, 'south', 0) ON DUPLICATE KEY UPDATE SET refcnt = 1; SELECT * FROM ch10_mutation ORDER BY id; ``` 重複キーがなければ新しい行を挿入します。重複キーがある場合、`SET`句のない構文は入力値で行全体を更新し、 `SET`句のある構文は指定した列だけを更新します。`PRIMARY KEY`自体は更新対象に指定できません。 大量取り込みAPIの初期化・バインド・エラー処理は、言語とドライバーによって異なります。 不完全なコード断片をコピーせず、[SDKと連携](/ja/dbms/development-tools-integration/)の該当ドライバーの例を使用してください。 ## 条件付き更新 既存行の一部の列だけを変更する場合は`UPDATE`を使用します。 `INSERT ... ON DUPLICATE KEY UPDATE`が「なければ挿入し、あれば更新する」のに対し、 `UPDATE`は対象行が存在する場合だけ値を変更します。 VOLATILEテーブルの`UPDATE`には`WHERE`が必要です。 条件は削除と同様に`PRIMARY KEY = 値`の形式のみサポートし、他の列の条件や複合条件は使用できません。 `WHERE`を省略した全件更新もサポートしていません。 ```sql UPDATE ch10_mutation SET refcnt = refcnt + 1 WHERE id = 2; SELECT * FROM ch10_mutation ORDER BY id; ``` `SET`句に`PRIMARY KEY`列は指定できません。 キーを変更する場合は、既存行を削除して新しいキーで再入力します。 ## データの削除 条件付き削除は`PRIMARY KEY = 値`の形式のみサポートします。 他の列の条件や複合条件は使用できません。 ```sql DELETE FROM ch10_mutation WHERE id = 2; SELECT * FROM ch10_mutation ORDER BY id; DROP TABLE ch10_mutation; ``` テーブル定義を保持したまま全行を削除するには、`DELETE FROM テーブル名`のようにWHEREを省略します。 スキーマも初期化する場合は、DROP後に再作成します。 サーバーを再起動するとデータだけが消え、テーブル定義は残るため、再作成ではなく再ロードのスクリプトを別途管理します。 --- title: "10.5 クエリと分析" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/query-analysis/ language: ja kind: page --- # 10.5 クエリと分析 VOLATILEテーブルのキー検索、一般条件検索、一時集計を実行可能な例で説明します。 ## サンプルデータの準備 VOLATILEテーブルは、他のテーブルタイプと同様に`SELECT`文で検索します。 次の例は、最後のクリーンアップ文まで順に実行できます。 ```sql CREATE VOLATILE TABLE ch10_query ( device_id VARCHAR(64) PRIMARY KEY, status VARCHAR(16), value DOUBLE, updated_at DATETIME ); INSERT INTO ch10_query VALUES ('DEV-01', 'RUNNING', 42.5, NOW); INSERT INTO ch10_query VALUES ('DEV-02', 'STOPPED', 0, NOW); ``` ## PRIMARY KEYによる検索 キー条件は、最新状態キャッシュの単一行検索に適しています。 ```sql SELECT device_id, status, value, updated_at FROM ch10_query WHERE device_id = 'DEV-01'; ``` ## 一般条件による検索 `PRIMARY KEY`以外の列で繰り返し検索する場合は、セカンダリインデックスを検討します。 ```sql CREATE INDEX ch10_query_status_idx ON ch10_query(status); SELECT device_id, value, updated_at FROM ch10_query WHERE status = 'RUNNING'; ``` インデックスもメモリを使用するため、実際の検索に必要な列だけに作成します。 ## 一時集計の検索 短周期の集計結果を保存すると、ダッシュボードやアラーム判定の繰り返し計算を減らせます。 ```sql CREATE VOLATILE TABLE ch10_query_summary ( summary_key VARCHAR(96) PRIMARY KEY, sensor_id VARCHAR(64), bucket_time DATETIME, avg_value DOUBLE, max_value DOUBLE, sample_cnt LONG ); INSERT INTO ch10_query_summary VALUES ('TEMP-01:2026-01-01T00:00', 'TEMP-01', TO_DATE('2026-01-01 00:00:00'), 21.5, 23.0, 60); SELECT sensor_id, bucket_time, avg_value, max_value FROM ch10_query_summary WHERE sensor_id = 'TEMP-01' ORDER BY bucket_time DESC LIMIT 10; DROP TABLE ch10_query_summary; DROP TABLE ch10_query; ``` 集計結果を長期保持する必要がある場合は、LOGまたはTRANSACTIONテーブルに定期的にコピーします。 ## クエリの注意事項 - サーバー再起動後はデータが空になるため、初期ロードの実施を先に確認します。 - キー検索が中心なら`PRIMARY KEY`を指定します。 - 範囲検索やソートで頻繁に使用する列には、セカンダリインデックスを検討します。 - 重要な元データは永続テーブルに保存し、VOLATILEはキャッシュとして使用します。 --- title: "10.6 インデックスとパフォーマンス" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/index-performance/ language: ja kind: page --- # 10.6 インデックスとパフォーマンス VOLATILEテーブルのインデックス作成と選択基準を説明します。 ## サポートするインデックス `PRIMARY KEY`を宣言すると、キー検索用のインデックスが作成されます。 一般列には`REDBLACK`インデックスを追加できます。 `BITMAP`と`KEYWORD`インデックスは、VOLATILEテーブルではサポートしていません。 次の例は、作成からクリーンアップまで順に実行できます。 ```sql CREATE VOLATILE TABLE ch10_index ( id INTEGER PRIMARY KEY, name VARCHAR(20), status VARCHAR(16) ); CREATE INDEX ch10_index_name_idx ON ch10_index(name) INDEX_TYPE REDBLACK; INSERT INTO ch10_index VALUES (1, 'west device', 'ACTIVE'); INSERT INTO ch10_index VALUES (2, 'east device', 'INACTIVE'); SELECT id, name FROM ch10_index WHERE name = 'west device'; DROP INDEX ch10_index_name_idx; DROP TABLE ch10_index; ``` ## 設計基準 - キーによる単一行の検索と更新には`PRIMARY KEY`を使用します。 - 一般列の等価・範囲条件を繰り返し使用する場合だけ、セカンダリインデックスを追加します。 - データだけでなくインデックスもメモリを使用するため、不要なインデックスは削除します。 - 実際のクエリ条件と行数を基準に、作成前後の応答時間とメモリを比較します。 構文の詳細は[インデックス構文](/ja/dbms/reference/sql/syntax/index-syntax/)を参照してください。 --- title: "10.7 運用とデータライフサイクル" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/operations-lifecycle/ language: ja kind: page --- # 10.7 運用とデータライフサイクル VOLATILEテーブルの作成・ロード・使用・消失・再構築の手順を説明します。 ## データライフサイクル 1. サーバー起動後にテーブル作成SQLを実行します。 2. 必要に応じて永続的な元データから初期データをロードします。 3. アプリケーションが検索と更新を開始します。 4. 保持が必要な結果を永続テーブルに記録します。 5. サーバーが終了するとデータが消失します。テーブル定義は残ります。 ## セッション間の共有 VOLATILEテーブルはサーバー全体で共有されます。 あるセッションが入力した行を別のセッションから検索でき、接続を終了しただけではデータは消失しません。 ## 永続データとの境界 VOLATILEには、元データから再作成できる最新状態や中間結果だけを格納します。 監査記録、元のイベント、復旧できない結果は、TAG、LOG、LOOKUPまたはTRANSACTIONテーブルに保存します。 コピーSQLは、コピー元とコピー先の列、重複処理、実行周期を含む独立したジョブとして管理します。 ## 再起動の手順 - テーブルの存在を確認します。再起動だけでは定義は消失しないため、通常は再作成しません。 - 永続的な元データがある場合は、定義した基準時点のデータだけをロードします。 - 想定行数と最新時刻を確認します。 - 検証後に、収集クライアントとアプリケーションの書き込みを再開します。 - 再構築に失敗した場合は、空のキャッシュでサービスが安全に動作するか確認します。 ## 運用チェックリスト - 初期ロードSQLをバージョン管理します。初回構築用の作成SQLも保存します。 - 本番アカウントと実際の接続情報で、スクリプトを事前検証します。 - 行数とメモリ上限を監視します。 - 保持が必要なデータがVOLATILEだけに残っていないか確認します。 - 再起動訓練でロードと検証の順序を確認します。 ## メモリ確認とキャッシュの再構築 ```sql SELECT * FROM V$STORAGE_DC_VOLATILE_TABLE; SELECT * FROM V$SYSMEM; SELECT * FROM V$SESMEM; SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME = 'VOLATILE_TABLESPACE_MEMORY_MAX_SIZE'; ``` 特定の内部列名に依存せず、導入バージョンのビュー定義を確認してください。 キャッシュの再作成では行数とサンプル値を記録し、利用処理を切り替えてから、テーブル作成・初期ロード・検証の順に進めます。 失敗時には空のキャッシュでも安全に動作する必要があります。 --- title: "10.8 制約、エラー、トラブルシューティング" url: https://docs.machbase.com/ja/dbms/volatile-table-usage/constraints-errors-troubleshooting/ language: ja kind: page --- # 10.8 制約、エラー、トラブルシューティング VOLATILEテーブルの制約、発生し得るエラー、解決方法を説明します。 多くの問題は、メモリ上限、PRIMARY KEY設計、未サポートの列型、再起動後のデータ消失に起因します。 ## 制約 VOLATILEテーブルでは、次の制約を考慮してください。 | 項目 | 制約 | |------|------| | 保存場所 | メモリ | | 再起動後のデータ | 消失 | | バックアップ・マウント | 未サポート | | JSON列 | 未サポート | | PRIMARY KEY | 任意。1つだけ指定 | | UPDATE/DELETE | `PRIMARY KEY = 値`条件のみサポート | | メモリ上限 | Volatile/Lookupテーブル全体のメモリ上限の影響を受ける | ```sql -- 失敗例: VOLATILEテーブルではJSON列を使用できません。 CREATE VOLATILE TABLE ch10_err_json ( session_id VARCHAR(64) PRIMARY KEY, payload JSON ); ``` 可変的な属性が必要なら、頻繁に検索する値を通常の列に分離してください。 永続的なJSON列が必要な場合は、TRANSACTIONまたはTAGテーブルを検討します。 ## メモリ不足 VOLATILEテーブルのデータとインデックスはメモリを使用します。 行数の増加や多数のインデックスによって、メモリ上限に達する場合があります。 診断は次の順序で行います。次の実習テーブルは、このページの最後で削除します。 ```sql -- 診断例の実習テーブルです。 CREATE VOLATILE TABLE ch10_diag ( device_id VARCHAR(64) PRIMARY KEY, value DOUBLE ); INSERT INTO ch10_diag VALUES ('DEV-01', 10.0); -- 1. 対象テーブルの行数を確認します。 SELECT COUNT(*) FROM ch10_diag; ``` ```sql -- 2. VOLATILEテーブル全体のメモリ使用量を確認します。 SELECT * FROM V$STORAGE_DC_VOLATILE_TABLE; ``` 必要に応じて、設定の`VOLATILE_TABLESPACE_MEMORY_MAX_SIZE`を確認します。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME = 'VOLATILE_TABLESPACE_MEMORY_MAX_SIZE'; ``` 対処方法は次のとおりです。 - 不要な行を削除します。 - キャッシュの保持範囲を縮小します。 - 使用していないインデックスを削除します。 - 重要なデータを永続テーブルに移してから、VOLATILEテーブルを再構築します。 - 運用ポリシーに合わせてメモリ上限の調整を検討します。 ## PRIMARY KEY関連のエラー `ON DUPLICATE KEY UPDATE`、[PKによるUPDATE](../data-input-mutation/#volatile-primary-key-update)、 PKによるDELETEを使用するにはPRIMARY KEYが必要です。 ```sql CREATE VOLATILE TABLE ch10_err_device ( device_id VARCHAR(64) PRIMARY KEY, status VARCHAR(16), updated_at DATETIME ); ``` PRIMARY KEYの値は重複できません。重複入力を更新として処理する場合は、`ON DUPLICATE KEY UPDATE`を使用します。 ```sql INSERT INTO ch10_err_device VALUES ('DEV-01', 'ONLINE', NOW) ON DUPLICATE KEY UPDATE SET status = 'ONLINE', updated_at = NOW; ``` PRIMARY KEY列自体はUPDATEできません。キーを変更する場合は、既存行を削除して新しいキーで挿入します。 ## 再起動後のデータ消失 サーバーの正常終了、異常終了、再起動時に、VOLATILEテーブルのデータは消失します。 これはエラーではなく、テーブルタイプの特性です。 問題が発生したら、次の項目を確認してください。 1. サーバーの再起動履歴を確認します。 2. VOLATILEテーブルの作成スクリプトが実行されたか確認します。 3. 初期ロードクエリが正常に実行されたか確認します。 4. 元のTAG/LOG/TRANSACTIONテーブルからキャッシュを再構築します。 ```sql SELECT COUNT(*) FROM ch10_diag; ``` 結果が0の場合は、初期ロード手順を再実行します。 このページの実習テーブルは、次のように削除します。 ```sql DROP TABLE ch10_diag; DROP TABLE ch10_err_device; ``` ## トラブルシューティングのチェックリスト - テーブルに保存したデータを再作成できるか確認します。 - PRIMARY KEYが必要な操作か確認します。 - `COUNT(*)`と`V$STORAGE_DC_VOLATILE_TABLE`で規模とメモリ使用量を確認します。 - 再起動後は初期ロードSQLを再実行します。テーブルの再作成は不要です。 - 永続保持が必要なら、VOLATILEではなくTAG、LOG、LOOKUP、TRANSACTIONテーブルを使用します。 --- title: "11. 開発とアプリケーション連携" url: https://docs.machbase.com/ja/dbms/development-tools-integration/ language: ja kind: section --- # 11. 開発とアプリケーション連携 アプリケーションの要件に合う連携方式を選び、SDK別のインストール・APIと共通の運用原則を確認します。 言語別の実装は各SDKページ、複数SDKに共通する判断基準は選択・概念・サポート範囲のページを参照します。 ## 読む順序 1. [連携方式の選択](selection-integration-method/)で言語と入力方式に合うインターフェースを選びます。 2. [共通の連携概念](concepts-common/)で認証、時間値、バインディング、トランザクション、再試行を確認します。 3. [SDK機能のサポート範囲](sdk-support-scope/)で必要な機能の実際のサポート状況を比較します。 4. 該当言語のSDKページでインストール、接続、実行コードを確認します。 5. [データの入力とエクスポート](data-input-load-export/)で作業別の手順を適用します。 SQLのROWIDの意味は[ROWID](../reference/sql/rowid/)を参照してください。 Machbase DBMS 8.7.0のARRAYの部分入力は [Sparse ARRAYと選択列Append API](data-input-load-export/array-append/)を参照してください。 ## SDK別リファレンス | 環境 | ドキュメント | |---|---| | C/C++ネイティブまたはODBC | [Machbase SQLCLIとODBC](cli-odbc/) | | Java・Spring | [JDBC](jdbc/) | | Python | [Python](python/) | | Node.js・TypeScript | [Node.js / TypeScript](node-js-typescript/) | | C#・VB.NET | [.NET Connector](net-connector/) | | Goネイティブ・`database/sql` | [Go](go/) | ## 共通の接続情報 | 項目 | デフォルト値 | 説明 | |---|---|---| | HOST | `127.0.0.1` | Machbaseサーバーのホスト名またはIP | | PORT | `5656` | Machbaseサーバーポート(`machbase.conf`の`PORT_NO`) | | USER | `SYS` | ユーザーID | | PASSWORD | `MANAGER` | ユーザーパスワード | 本番環境では専用ユーザーと必要最小限の権限を使用します。アカウントと認証設定は [アカウント、権限、アクセス制御](../security-access-control/)を参照してください。 ## 既存のサポート範囲リンク NULL・PRIMARY KEYメタデータ、ROWID、Append、AUTH KEYのSDK別サポート状況は [SDK機能のサポート範囲](sdk-support-scope/)で確認してください。 --- title: "11.1 連携方式の選択" url: https://docs.machbase.com/ja/dbms/development-tools-integration/selection-integration-method/ language: ja kind: section --- # 11.1 連携方式の選択 プロジェクトの言語、入力特性、デプロイ環境に合う連携方式を選択します。 ## 選択基準 | 要件 | 優先して検討する方式 | |----------|------------------| | C/C++ネイティブのコレクター | SQLCLI | | ODBCマネージャー・DSNベースのアプリケーション | ODBC | | Java・Spring | JDBC | | Pythonによる分析・自動化 | `machbaseapi` | | C#・VB.NET | .NET Connector | | Goのコレクター・サービス | v2の`database/sql`。旧v1ではネイティブ`machgo`も使用可能 | | Node.js・TypeScriptバックエンド | `@machbase/ts-client` | | R分析環境 | Machbase ODBCドライバーとRODBC | | 大きなファイルの一括入力・エクスポート | machloader、csvimport、csvexport | | 継続的なTAG・LOGの大量入力 | 選択したSDKのAppend API | ブラウザーから5656ポートに直接接続しません。バックエンドでクエリを実行し、必要な結果のみを渡します。 ## 決定手順 1. アプリケーションの言語で保守可能な公式ドライバーを選びます。 2. 5656ポートへの接続、OSとランタイムの互換性を確認します。 3. SQL、プリペアドステートメント、Append、トランザクションの必要な機能を決めます。 4. [SDK機能のサポート表](../sdk-support-scope/)で実際のサポート状況を確認します。 5. サンプルデータでタイムスタンプ、NULL、数値、文字列の往復を検証します。 6. 目標の行サイズ・同時接続数・バッチサイズで負荷テストします。 Appendのサポートだけでドライバーを決定しません。フラッシュ遅延、サーバーのエラー処理応答、再接続、 失敗行の処理まで実際のSDKで確認します。TRANSACTION DMLには明示的トランザクションのサポート範囲を 確認し、TAG・LOGのAppendを同じロールバック単位とは考えないでください。 ## トピック別の詳細ドキュメント | 内容 | 詳細ドキュメント | |------|------| | SDKのインストール・接続・API・完全なコード | 本章のSDK別ページ | | 共通の認証・バインディング・トランザクション・再試行 | [共通の連携概念](../concepts-common/) | | SDK別の機能サポート状況 | [SDK機能のサポート範囲](../sdk-support-scope/) | | SQL・設定・コマンドラインの詳細 | [第16章 リファレンス](/ja/dbms/reference/) | | 入力・エクスポート方式の選択 | [データの入力とエクスポート](../data-input-load-export/) | 連携方式を選んだら、該当SDKページのインストールと接続例を実行します。 機能のサポート状況は、ドキュメントに記載されたバージョンと実際の配布成果物を合わせて確認します。 --- title: "11.2 共通の連携概念" url: https://docs.machbase.com/ja/dbms/development-tools-integration/concepts-common/ language: ja kind: section --- # 11.2 共通の連携概念 ドライバーや言語に関係なく適用される、接続、バインディング、トランザクション、大量入力、エラー処理の 原則を説明します。SDK別の関数名と完全なコードは、本章のSDK別ページを参照してください。 ## 接続文字列と認証 接続にはホスト、ネイティブポート、ユーザー、認証情報を使用します。デフォルトポートは`5656`ですが、 デプロイ環境の`machbase.conf`設定を確認してください。 | 項目 | 確認事項 | |------|-----------| | ホスト・ポート | アプリケーションの実行場所からTCP接続できるか | | ユーザー | 対象データベースとテーブルに必要な最小限の権限 | | パスワード | 環境変数またはシークレット管理システムで注入 | | データベース | SDKが初期データベースの選択をサポートするか | | タイムアウト | 接続・コマンド・読み取り制限をワークロードに合わせて設定 | | タイムゾーン | SDKとサーバーがサポートするオプション名と適用範囲 | 例の`SYS`/`MANAGER`はローカル検証用です。本番アプリケーションには専用アカウントを作成し、 ソース、コマンド履歴、ログにパスワードを記録しません。 AUTH KEYは、パスワードの代わりに秘密鍵でチャレンジに署名する方式です。鍵形式、ファイル権限、 SDK別オプションは[AUTH KEY認証](/ja/dbms/security-access-control/authentication-auth-key/)と 該当ドライバーのドキュメントを合わせて確認します。 接続プールを使用する場合は、返却した接続の現在のデータベース、セッション設定、開いた文が 次のリクエストに影響しないよう、初期化動作を検証します。 ## タイムゾーンと時間値 Machbaseの`DATETIME`はナノ秒精度をサポートします。アプリケーションでは時間値の意味と表現を 分けて管理します。 - 収集時刻の基準タイムゾーン(UTCまたは業務地域)を明示します。 - 文字列をバインドする際は、形式とタイムゾーンをともに固定します。 - エポック値を渡す際は、SDKが要求する単位が秒、ミリ秒、マイクロ秒、ナノ秒のどれかを確認します。 - 検索文字列のタイムゾーンは、接続オプションや`TO_CHAR()`など実際の使用経路で往復テストします。 - 業務規則で`NOW`と`SYSDATE`を混用せず、必要な意味をSQLリファレンスで確認します。 文字列の往復検証では、同じ接続で入力値、検索値、タイムゾーン変更後の検索値を比較します。 関数の詳細は[SQL関数](/ja/dbms/reference/sql/functions/functions-full/)を参照してください。 ## プリペアドステートメント プリペアドステートメント(prepared statement)はSQLの構造と値を分離し、同じSQLを繰り返し 実行する際に使用します。 ```text INSERT INTO sensor_data VALUES (?, ?, ?) SELECT value FROM sensor_data WHERE name = ? AND time >= ? ``` 文を準備した接続と現在のデータベースが変わっていないか確認し、使用後に閉じます。 文キャッシュを提供するSDKでは、キャッシュ範囲、項目の削除ポリシー、データベース切り替え時の 初期化動作を確認します。 CTE、LIMITなど構文の位置によってはパラメータープレースホルダーが許可されない場合があります。 構文エラーが発生したら、値を文字列として連結する前に [Named Bind Parameter](/ja/dbms/reference/sql/syntax/named-bind-parameter-syntax/)と 該当SDKのプレースホルダーのサポート範囲を確認します。 ## パラメーターバインディング | 値の種類 | 推奨方式 | |---------|-----------| | 整数・実数 | 言語の固定幅型とSQL型の範囲を合わせる | | 文字列 | エンコーディングと最大長を確認 | | DATETIME | SDKの時間オブジェクトまたは明示されたエポック単位を使用 | | NULL | 言語別のNULL表現とSQL型をともに指定 | | DECIMAL | 文字列変換よりSDKの正確な固定小数点型を優先 | | バイナリ・IP | SDKが要求するバイト配列または専用型を使用 | 位置指定のプレースホルダー`?`は出現順に値をバインドします。名前付きプレースホルダー`:name`は 対応するサーバーとSDKでのみ使用し、同名の繰り返し処理規則を確認します。識別子やSQLキーワードは 値パラメーターとしてバインドできないため、許可リストで検証してからSQLを組み立てます。 ## DMLの影響行数 `INSERT`、`UPDATE`、`DELETE`の後はSDKが返す影響行数を確認します。成功応答だけで業務対象が 実際に変更されたと考えないでください。 - 単一行の変更では期待値が1か確認します。 - 0件の場合、条件に一致する行がないか、すでに同じ変更が反映されているか確認します。 - 権限不足や非サポートのDMLでは、影響行数とは別にエラーコードと例外を確認します。 - 一括変更では、実行前に同じ条件の`COUNT(*)`で範囲を確認します。 - AppendではSQLの影響行数の代わりに、close・サーバー処理応答の成功件数と失敗件数を確認します。 ## トランザクション 明示的な`BEGIN`、`COMMIT`、`ROLLBACK`はTRANSACTIONテーブルのリレーショナルDMLで使用します。 LOG・TAGのAppendを同じロールバック単位とは考えないでください。 1. 使用するSDKがトランザクションAPIを提供するか確認します。 2. 提供しない場合は、サポートされるSQL制御文を同じ接続で実行します。 3. エラー時にロールバックして接続を再利用できるか確認します。 4. 接続プールへの返却前に未完了のトランザクションが残らないようにします。 5. 複数のテーブルタイプを混在させる作業では、各文のコミット範囲を事前に検証します。 完全なSQL例は [TRANSACTIONテーブルのトランザクション](/ja/dbms/rdb-table-usage/transaction/)を参照してください。 ## Append APIとバッチ 入力方式の選択と結果確認項目は[データの入力とエクスポート](../data-input-load-export/)、 クライアント・テーブルタイプ別のAppendの利用条件は [SDK Appendサポート表](../sdk-support-scope/#append-table-type-matrix)で扱います。 Append接続は通常のクエリ接続と分け、フラッシュ・クローズと失敗行を確認します。 ## エラー処理と再試行 エラーは、接続、認証・権限、SQL・スキーマ、データ、リソース不足に分類します。 - 接続切断と一時的なタイムアウトだけを、回数を制限し待機時間を設けて再試行します。 - 認証失敗、権限不足、構文エラー、型エラーは、修正前に自動再試行しません。 - 再試行前に文・カーソル・Appendハンドルと接続を解放します。 - INSERTの再試行では業務キーや重複処理ポリシーで冪等性を確保します。 - サーバーのエラーコードとメッセージは記録し、認証情報と機密の生データは除去します。 - 接続プール内でエラーになった接続は、有効性検査後に返却するか破棄します。 運用エラーの分類と診断手順は[トラブルシューティング](/ja/dbms/troubleshooting/)を参照してください。 --- title: "11.3 SDK機能のサポート範囲" url: https://docs.machbase.com/ja/dbms/development-tools-integration/sdk-support-scope/ language: ja kind: section --- # 11.3 SDK機能のサポート範囲 アプリケーションの要件に合うSDKを選択できるように、機能別のサポート状況とAPIエントリーポイントを 比較します。インストール、接続、関数、実行コードは各SDKページを参照してください。 初めてSDKを選ぶ場合は[連携方式の選択](../selection-integration-method/)を先に読み、 このページで必要な機能と正確なAPI経路を照合します。 Goの表にある「ネイティブ」は、確認基準がv1.8.4の旧`machgo` APIを指します。 [Go SDK](../go/)はv2の`database/sql` APIを説明しており、v2では旧`machgo`は提供されません。 v1の確認済み機能や最小バージョンをv2へそのまま適用せず、以下のARRAY・選択列Appendなどの v2固有の確認基準と区別してください。 ## NULL許容性のメタデータ MachbaseはSELECT結果列のNULL許容性を`NO_NULLS`、`NULLABLE`、`UNKNOWN`で区別します。 アプリケーションは`NULLABLE`と`UNKNOWN`の両方をNULL処理の対象とします。 | SDK | 取得方法 | |---|---| | JDBC | `ResultSetMetaData.isNullable()` | | Python | `cursor.description[i][6]` | | Goネイティブ | `api.Column.Nullability` | | Go `database/sql` | `Rows.ColumnTypeNullable()` | | Node.js | `ColumnMeta.nullable` | | .NET | `GetSchemaTable()`の`AllowDBNull` | | SQLCLI・ODBC | ディスクリプターのnullable属性 | 式、集計、VIEW、JOINの結果は`UNKNOWN`になる場合があります。直接の列のスキーマ制約と 検索結果メタデータを同一と考えないでください。 ## PRIMARY KEYメタデータ | SDK | 結果列 | テーブルカタログ | |---|:---:|:---:| | JDBC | O | `DatabaseMetaData.getPrimaryKeys()` | | Python | O | カタログSQL | | Goネイティブ | O | カタログSQL | | Go `database/sql` | 標準APIなし | カタログSQL | | Node.js | O | カタログSQL | | .NET | O | カタログSQL | | ODBC | 別の結果APIなし | `SQLPrimaryKeys()` | 式・集計・外部JOINのNULL補完側は、元の列のPK属性をそのまま伝達しない場合があります。 ## INSERT結果のROWID Machbase 8.7.0 Standard Editionでは、成功した単一の`INSERT ... VALUES`が対応SDKにROWIDを 提供できます。 | SDK・ツール | 確認方法 | 値がない場合 | |---|---|---| | machsql | `SHOW LAST ROWID` | `NULL` | | Machbase SQLCLI | `SQLGetGeneratedRowID()` | `SQL_NO_DATA` | | 標準ODBC | 専用の標準APIなし | - | | JDBC | `Statement.getGeneratedKeys()` | 空の`ResultSet` | | Python | `cursor.lastrowid` | `None` | | .NET | `MachCommand.RowId` | `null` | | Go `database/sql` | `Result.LastInsertId()` | エラー | | Goネイティブ | 非サポート | - | | Node.js | 実行結果の`rowId` | `undefined` | バッチ、`executemany()`、Append、loader、`INSERT ... SELECT`、UPSERTは単一のROWIDを返しません。 SQLの意味とテーブルごとの制約は[ROWID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## Append APIとテーブルタイプ | API経路 | LOG | TAG | LOOKUP | VOLATILE | TRANSACTION | 基準 | |---|:---:|:---:|:---:|:---:|:---:|---| | SQLCLI `SQLAppend*`拡張 | O | O | O | O | O | TRANSACTIONはStandard | | JDBC `MachStatement.executeAppend*` | O | O | O | O | O | NFX cce422dのソース・テスト | | Python 2.4 `append*` | O | O | O | O | O | NFX cce422dのソース・テスト | | .NET `MachAppendWriter` | O | O | O | O | O | NFX cce422dのプロバイダー | | Go v1.8.4ネイティブ`Appender` | O | O | X | X | O | TRANSACTIONはStandard | | Go `database/sql`標準API | X | X | X | X | X | `sql.Conn.Raw()`拡張はネイティブ仕様 | | Nodeソースの`appendBatch()` | O | △ | △ | △ | O | NFX cce422dのソースビルド | | Nodeソースの`appendOpen()` | O | O | △ | △ | △ | 汎用native/fallback、テーブル別の検証が必要 | 標準クエリ接続とAppendハンドルのライフサイクルを区別し、close・flushの結果を確認します。 `O`は該当ソース・テストで確認した範囲、`△`は汎用経路だけがあり、テーブル別の回帰検証がさらに 必要な範囲です。Append拡張は標準ODBCや`database/sql`の機能ではありません。 ### ARRAYと選択列Append Machbase DBMS 8.7.0のARRAYのサポート範囲は次のとおりです。 | SDK | 密なARRAYの検索・入力 | スパースARRAY | 選択列Append | |---|:---:|:---:|:---:| | SQLCLI・C++ | O | O | O | | Machbase ODBC拡張 | O | O | O | | JDBC | O | O | O | | Python | O | O | O | | Node.js | O | O | O | | .NET full/legacyプロバイダー | O | O | O | | Go | v2 mainソース | v2 mainソース | v2 mainソース | Machbase DBMS 8.7.0サーバーとARRAY機能を含むSDKビルドを合わせて使用します。ARRAYのSQL要素位置と Machbase専用SDKの位置は0始まりのインデックスです。既存の全行スカラーAppend APIは維持されます。 Node.jsのprepared代替経路も`SparseArray`をサポートします。Goは [`neo-client` PR #17](https://github.com/machbase/neo-client/pull/17)以降のv2 mainソースを 使用する必要があり、公開v2リリースが指定されるまでは公開モジュールのバージョンだけでサポートを 判断しません。入力方式とAPIの詳細は [Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 ## AUTH KEY | SDK・ツール | サポート | |---|:---:| | machsql、Machbase SQLCLI、ODBC、JDBC | O | | Goネイティブ、Go `database/sql` | O(neo-client v1.5.0+) | | Python、Node.js、.NET | X | 鍵の生成・登録・交換は[AUTH KEY認証](/ja/dbms/security-access-control/authentication-auth-key/)、 接続オプションは対応SDKページを参照してください。 ## トランザクション、prepare、bind | SDK | トランザクションAPI | サーバー側prepare | 名前付きbind API | |---|:---:|:---:|:---:| | JDBC | O | O | △(Machbase拡張) | | Python | X | O | O | | Goネイティブ | △ | O | O | | Go `database/sql` | O | O | O | | .NET | X | X | △ | | Node.js | X | O | O | | SQLCLI | △ | O | O | | ODBC | △ | O | 位置指定bind | プリペアドステートメントとパラメーターバインディングはトランザクションのサポートとは別です。 プレースホルダーの構文は [Named Bind Parameter](/ja/dbms/reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 Machbase 8.7.0 Standard EditionのTAGデータUPDATEは、各SDKの既存の位置指定・名前付きAPIで NAMEとBASETIMEの条件値をバインドできます。NFX #4127の回帰テストはC/C++ SQLCLI、 Go `database/sql`、JDBC、Node.js、Python、.NETの経路を検証します。ODBCは個別のSDK回帰 マトリクスには含まれず、`?`または名前付きSQLのプレースホルダーを標準`SQLBindParameter()`の 位置番号でバインドします。TAG UPDATEの条件仕様は [TAGデータUPDATEのバインド](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/#tag-data-update-predicate-bind)を 参照してください。 トランザクション列の`△`は、専用オブジェクトの代わりに同じ接続でトランザクションSQLを直接実行する 経路です。名前付きbind列の`△`は、標準の名前付きバインディングAPIではなく、ドライバー拡張、または クライアントが値をSQLリテラルに変換する経路を表します。 ## 最小確認バージョンと出所 | SDK | 本ドキュメントの確認基準 | |---|---| | SQLCLI・JDBC・Python | NFX `cce422d2972`、Pythonパッケージ2.4 | | Node.js | NFX `cce422d2972`のソースビルド(`package.json` 1.0.1) | | .NET | Uni 8.0.55、limited 3.1.3、full 3.2.2 | | Go | 公開済みneo-client v1.8.4、AUTH KEYはv1.5.0+、データベース選択はv1.8.3+ | NFX cce422dのNode機能の一部は、公開npm 1.0.1の配布後に追加されました。レジストリパッケージの バージョン文字列だけで同じ機能を想定せず、配布成果物のコミット出所を確認するか、NFXソースビルドを 使用します。 ARRAYと選択列Appendの確認基準は、NFX `655d1333870313c4951698b89c9a3c9ada11d630`とマージコミット `f756986c4836982723e2aa7727ec05b7e05e9707`です。サーバーはMachbase DBMS 8.7.0、クライアントは 該当変更以降の検証済みSDK成果物を基準に判断します。 ## SDKリファレンス | SDK | 詳細ドキュメント | |---|---| | Machbase SQLCLI・ODBC | [SQLCLIとODBC](../cli-odbc/) | | JDBC | [JDBC](../jdbc/) | | Python | [Python](../python/) | | Node.js / TypeScript | [Node.js / TypeScript](../node-js-typescript/) | | .NET Connector | [.NET Connector](../net-connector/) | | Go | [Go](../go/) | --- title: "11.4 Machbase SQLCLIとODBC" url: https://docs.machbase.com/ja/dbms/development-tools-integration/cli-odbc/ language: ja kind: section --- # 11.4 Machbase SQLCLIとODBC Machbase SQLCLIはC/C++アプリケーションで使用する呼び出しレベルインターフェース(Call-Level Interface)です。ODBCドライバーは標準ODBCアプリケーションで使用します。両者は環境・接続・文の ハンドルを使用する実行フローを共有し、SQLCLIには高速Append用の拡張関数が追加されています。 ## 選択基準 | 要件 | インターフェース | |----------|------------| | MachbaseインストールパッケージとともにC/C++アプリケーションを開発 | SQLCLI | | 汎用ODBCツールまたはドライバーマネージャーを使用 | ODBC | | Append拡張APIによる大量入力 | SQLCLI | | 標準SQLの実行と結果の取得 | SQLCLIまたはODBC | ## ヘッダーとライブラリ インストールディレクトリで次のファイルを確認します。 ```bash test -f "$MACHBASE_HOME/include/machbase_sqlcli.h" test -f "$MACHBASE_HOME/lib/libmachbasecli_dll.so" ``` Linuxでの動的リンクの例です。 ```bash gcc cli_quickstart.c -I"$MACHBASE_HOME/include" -L"$MACHBASE_HOME/lib" -lmachbasecli_dll -o cli_quickstart LD_LIBRARY_PATH="$MACHBASE_HOME/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" MACHBASE_PASSWORD='your-password' ./cli_quickstart ``` 本番ビルドは、インストールパッケージの`install/machbase_env.mk`とプラットフォーム別の リンカー設定に基づいて構成します。 ## 接続文字列 SQLCLIの基本的な接続文字列は次のキーを使用します。 ```text SERVER=127.0.0.1;PORT_NO=5656;UID=APP_USER;PWD=secret;CONNTYPE=1 ``` ODBCデータソースを使用する場合はDSN、アカウント、パスワードを指定します。 ```text DSN=MACHBASE;UID=APP_USER;PWD=secret ``` マルチデータベースの初期値をサポートするドライバーでは`DATABASE`または`DBNAME`を使用できます。 実際に配布されたドライバーのサポート状況を確認し、接続後に`SELECT CURRENT_DATABASE()`で 選択結果を検証します。 ## クイックスタート 次のプログラムは5656ポートに接続してシステムテーブルのクエリを実行し、全ハンドルを解放します。 パスワードは環境変数で渡します。 ```c #include #include #include int main(void) { SQLHENV env = SQL_NULL_HENV; SQLHDBC dbc = SQL_NULL_HDBC; SQLHSTMT stmt = SQL_NULL_HSTMT; char conn[512]; const char *password = getenv("MACHBASE_PASSWORD"); if (password == NULL) { fputs("MACHBASE_PASSWORD is required\n", stderr); return 2; } snprintf(conn, sizeof(conn), "SERVER=127.0.0.1;PORT_NO=5656;" "UID=SYS;PWD=%s;CONNTYPE=1", password); if (SQLAllocEnv(&env) != SQL_SUCCESS) { return 3; } if (SQLAllocConnect(env, &dbc) != SQL_SUCCESS) { SQLFreeEnv(env); return 4; } if (SQLDriverConnect( dbc, NULL, (SQLCHAR *)conn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT) != SQL_SUCCESS) { SQLFreeConnect(dbc); SQLFreeEnv(env); return 5; } if (SQLAllocStmt(dbc, &stmt) != SQL_SUCCESS) { SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); return 6; } if (SQLExecDirect( stmt, (SQLCHAR *)"SELECT COUNT(*) FROM V$TABLES", SQL_NTS) != SQL_SUCCESS) { SQLFreeStmt(stmt, SQL_DROP); SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); return 7; } puts("query succeeded"); SQLFreeStmt(stmt, SQL_DROP); SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); return 0; } ``` 失敗原因を出力する必要があるアプリケーションは、`SQLGetDiagRec()`または既存コードの `SQLError()`でSQLSTATE、ネイティブエラーコード、メッセージを読み取ります。 ## 標準的な実行フロー 1. 環境ハンドルと接続ハンドルを割り当てます。 2. `SQLDriverConnect()`または`SQLConnect()`で接続します。 3. 文ハンドルを割り当てます。 4. `SQLPrepare()`と`SQLExecute()`、または`SQLExecDirect()`でSQLを実行します。 5. SELECT結果は`SQLBindCol()`と`SQLFetch()`で読み取ります。 6. 文、接続、環境の順にリソースを解放します。 入力値は文字列として連結せず、`SQLBindParameter()`でバインドします。NULL許容性は `SQLDescribeCol()`の最後の引数、または`SQLColAttribute(..., SQL_DESC_NULLABLE, ...)`で確認します。 ## Named Bind Parameter サーバーとドライバーが名前付きパラメーターをサポートする場合、`:name`プレースホルダーを使用し、 `SQLBindParameterByName()`でバインドできます。同じ名前が複数回現れると1つの値が全位置に適用されます。 共通の制約と例は [Named Bind Parameter](/ja/dbms/reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 サポートを確認できない環境では、標準の`?`プレースホルダーと`SQLBindParameter()`を使用します。 ## INSERT結果のROWID Standard Editionで単一の`INSERT ... VALUES`が成功した後、生成されたROWIDが必要な場合は 次の方法を使用します。 - SQLCLI拡張: `SQLGetGeneratedRowID()` - 標準ODBC: 生成ROWID専用の標準APIなし バッチ、Append、`INSERT ... SELECT`、UPSERTで同じ戻り値を想定しないでください。詳細な範囲は [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## Append拡張API 高速入力は通常の文と分けたAppendフローを使用します。 | 段階 | 主な関数 | |------|-----------| | オープン | `SQLAppendOpen()`、選択列は`SQLAppendOpenColumns()`/`W()` | | 1行の入力 | `SQLAppendDataV2()`または対応バージョンのAppend関数 | | バッチ入力 | `SQLAppendBatch()` | | サーバーへの反映 | `SQLAppendFlush()` | | エラーコールバック | `SQLAppendSetErrorCallback()` | | クローズ | `SQLAppendClose()` | Append行の列順序と型は、対象テーブルのスキーマと完全に一致する必要があります。文字列、バイナリ、 IP、DATETIME、NULLの表現は、インストール済み`machbase_sqlcli.h`の`SQL_APPEND_PARAM`定義に 基づいて記述します。エラーコールバックでは失敗行とサーバーエラーを記録しますが、パスワードや機密の 生データはログに残しません。 有効なAppendハンドルがある接続は通常のクエリと共有せず、close結果の成功・失敗件数を確認します。 ## マルチスレッドとリソース管理 - スレッドごとに接続と文を分けます。 - 1つの文またはAppendハンドルを複数スレッドで同時に使用しません。 - すべてのエラー経路でもハンドルを逆順に解放するよう、後処理関数を用意します。 - 再試行前に、前の接続とAppendの状態が完全に閉じているか確認します。 - 大量入力では成功件数と失敗件数の両方を記録します。 ## API詳細の確認 関数プロトタイプ、定数、構造体は、インストール済みの `$MACHBASE_HOME/include/machbase_sqlcli.h`が該当ライブラリと一致する基準です。 サンプルを別バージョンのヘッダーと混用せず、コンパイル・リンク・5656接続のテストを デプロイパイプラインに含めます。 ## DECIMAL Append `SQLAppendDataV2()`と`SQLAppendBatch()`で`DECIMAL`または`NUMERIC`値を入力する際は、 32バイトの不透明型`SQL_APPEND_NUMERIC`と公開生成関数を使用します。 アプリケーションで内部バイトを直接作成・変更しません。 | 入力 | 関数 | |---|---| | UTF-8の数値文字列 | `SQLAppendNumericFromString()` | | 符号付き・符号なし整数 | `SQLAppendNumericFromInt64()`、`SQLAppendNumericFromUInt64()` | | `SQL_NUMERIC_STRUCT` | `SQLAppendNumericFromSQLNumeric()` | | NULL | `SQLAppendNumericSetNull()` | 正確な値を保持するには、文字列または`SQL_NUMERIC_STRUCT`を優先します。型配列には `SQL_APPEND_TYPE_NUMERIC`または`SQL_APPEND_TYPE_DECIMAL`を指定し、対象列の精度とスケールに 基づいてオーバーフローと丸めを確認してください。 ## ARRAYと選択列Append Machbase DBMS 8.7.0は、`SQL_MACHBASE_ARRAY_DESC`による型付きARRAYの検索・バインドと、 `SQL_MACHBASE_SPARSE_ARRAY_DESC`によるスパース入力をサポートします。通常のOpenでもARRAY列に スパースディスクリプターを渡せます。 ```c SQLAppendOpen(statement, (SQLCHAR *)"ARRAY_APPEND_FULL_EXAMPLE", 0); row[0].mLong = 1; row[1].mVar.mData = &sparse; row[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; SQLAppendDataV3(statement, row, 2); SQLAppendClose(statement, &success, &failure); ``` 上記コードは`ID LONG, A INT32[4]`テーブルの入力順序に従います。接続・ディスクリプター・バッファの 準備とエラー処理を含む[通常Openの全体例](../data-input-load-export/array-append/#c-full-open)を 先に確認してください。旧式の`SQLAppendData(void *[])`にディスクリプターを渡す方式とは異なります。 一部の列または固定ARRAY要素だけを選択する場合は、`SQLAppendOpenColumns()`または `SQLAppendOpenColumnsW()`を使用します。 ```c SQLCHAR *targets[] = { (SQLCHAR *)"ID", (SQLCHAR *)"CHANNELS[0]", (SQLCHAR *)"CHANNELS[3]", NULL }; SQLAppendOpenColumns(statement, (SQLCHAR *)"SENSOR_ARRAY", targets, 0); ``` ARRAY要素の対象とスパースディスクリプターの位置は0始まりのインデックスです。列名リストの最後の要素は `NULL`である必要があります。`SQLAppendBatch()`はARRAYをサポートしません。 ディスクリプター定義、配列全体のNULLと要素NULLの処理、直接ODBCハンドルの制約は [Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 --- title: "11.5 JDBC" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/ language: ja kind: section --- # 11.5 JDBC Machbase JDBCドライバーはJava 8を基準にJDBC 4.2の主要APIを提供します。標準JDBC APIで サーバーに接続し、PreparedStatement、型指定の検索とバインディング、データベースメタデータ、 ローカルトランザクション、接続プールを使用できます。 | 項目 | 値 | |------|----| | Javaバイトコード基準 | Java 8 | | ドライバーが報告するJDBCバージョン | 4.2 | | ドライバーバージョン | 3.0.0 | | JDBC URL | `jdbc:machbase:///[database]` | | `Driver.jdbcCompliant()` | `false` | `jdbcCompliant()`の`false`はJDBC 4.2 APIのサポート状況ではなく、SQL-92 Entry Level全体への 準拠状況を示します。アプリケーションでは必要な任意機能を`DatabaseMetaData`の機能メソッドで確認します。 ## マルチデータベース URLパスまたは`database`接続プロパティで初期データベースを指定できます。 ```java String url = "jdbc:machbase://127.0.0.1:5656/factory_a"; Connection conn = DriverManager.getConnection(url, "APP_A", password); System.out.println(conn.getCatalog()); conn.setCatalog("FACTORY_A"); ``` `getCatalog()`と`setCatalog()`はサーバーの現在のデータベースと同期します。URLパスと設定プロパティを 両方指定する場合は同じ値にする必要があります。JDBCメタデータではカタログはデータベース、スキーマは 所有者です。プールされた接続の返却時に初期カタログへ復元されるか確認し、プリペアドステートメントと Appendハンドルは作成時のデータベースに固定される点を考慮します。 ## ドライバーのインストール ### JARファイルの使用 Machbaseインストールディレクトリの`machbase.jar`をクラスパスに追加します。 ```bash ls -l "$MACHBASE_HOME/lib/machbase.jar" javac -classpath ".:$MACHBASE_HOME/lib/machbase.jar" MyApp.java java -classpath ".:$MACHBASE_HOME/lib/machbase.jar" MyApp ``` JARには`META-INF/services/java.sql.Driver`が含まれています。JDBC 4.0以降の環境では `Class.forName("com.machbase.jdbc.MachDriver")`を呼び出さなくてもドライバーが自動登録されます。 既存アプリケーションの明示的な呼び出しも引き続き使用できます。 ### Maven ```xml com.machbase machjdbc {{< jdbc_version >}} ``` ### Gradle ```groovy dependencies { implementation 'com.machbase:machjdbc:{{< jdbc_version >}}' } ``` 配布成果物のバージョンは[Maven Central](https://mvnrepository.com/artifact/com.machbase/machjdbc)で 確認します。ドライバーが実行時メタデータで返す`3.0.0`と配布成果物のバージョンは、別のバージョン体系です。 ## サーバーへの接続 ユーザー名とパスワードはソースコードに記録せず、環境変数やシークレット管理システムで渡します。 ```java import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; String url = "jdbc:machbase://127.0.0.1:5656/machbasedb"; Properties properties = new Properties(); properties.setProperty("user", "SYS"); properties.setProperty("password", System.getenv("MACHBASE_PASSWORD")); try (Connection connection = DriverManager.getConnection(url, properties)) { // SQLを実行します。 } ``` ### 接続オプション 接続オプションは`Properties`またはURLクエリ文字列で指定します。`randomHost`は`Properties`で 指定するか、複数ホストURLの`^`区切り文字を使用します。 | オプション | 説明 | |------|------| | `user`, `password` | パスワード認証情報 | | `TIMEZONE` | セッションのタイムゾーン。`+0900`形式を使用します。 | | `randomHost` | ホスト一覧から最初の接続先をランダムに選択します。 | | `maxStatements` | プールされた接続の最大キャッシュStatement数 | | `CONNECTION_TIMEOUT` | ソケット接続のタイムアウト(秒)。`0`は無制限です。 | | `SOCKET_TIMEOUT` | ソケット読み取りのタイムアウト(秒)。`0`は無制限です。 | | `characterEncoding` | クライアントの文字エンコーディング | | `AUTH_MODE` | `PASSWORD`または`CHALLENGE` | | `AUTH_SIG_SCHEME` | `ECDSA`、`RSA_PKCS1_V15`、`RSA_PSS` | | `AUTH_KEY_FILE` | PEM秘密鍵ファイルのパス | ```java String url = "jdbc:machbase://127.0.0.1:5656/machbasedb?TIMEZONE=+0900"; ``` ### 複数ホストへの接続 Machbase 8.7.0 JDBCドライバーは、1つのURLに複数ホストを指定できます。 | 選択方式 | 指定方法 | 動作 | |-----------|-----------|------| | 順次選択 | ホストを`,`で区切る | URLの記載順に接続を試みます。 | | ランダム開始 | ホストを`^`で区切る | ホスト一覧から最初の接続先をランダムに選びます。 | | ランダム開始 | `Properties`で`randomHost=true`を指定 | `,`で区切った一覧から最初の接続先をランダムに選びます。 | 次のURLは`db1`への接続に失敗すると、`db2`への接続を試みます。 ```java String url = "jdbc:machbase://db1.example.com:5656,db2.example.com:5656/" + "machbasedb?CONNECTION_TIMEOUT=5"; ``` `^`区切り文字を使用すると、最初の接続先をランダムに選択します。 ```java String url = "jdbc:machbase://db1.example.com:5656^db2.example.com:5656/" + "machbasedb?CONNECTION_TIMEOUT=5"; ``` `randomHost`設定プロパティを使用する場合は、`,`でホストを区切ります。 ```java Properties properties = new Properties(); properties.setProperty("randomHost", "true"); String url = "jdbc:machbase://db1.example.com:5656,db2.example.com:5656/" + "machbasedb?CONNECTION_TIMEOUT=5"; ``` - 1つのURLで`,`と`^`の区切り文字は併用できません。 - 接続拒否、接続タイムアウト、ソケットエラーなど接続段階のI/Oエラーが発生すると、次のホストへの 接続を試みます。すべてのホストが失敗すると`DriverManager.getConnection()`は`SQLException`を返します。 - `CONNECTION_TIMEOUT`はホストごとの接続試行に適用されます。そのため全体の接続待機時間は ホスト数と各ホストの応答時間によって長くなる場合があります。 - `SOCKET_TIMEOUT`は接続済みソケットの読み取り待機時間を制限し、ホストの選択順序は変更しません。 複数ホストの切り替えは、新規接続または再接続時のソケット接続に適用されます。切断後に自動再接続が 成功しても、以前のStatement、PreparedStatement、ResultSetは再利用しません。実行中のSQLの成功や 安全な再実行は保証されないため、有効なトランザクションで接続エラーが発生した場合は接続を破棄し、 業務の冪等性ポリシーに従ってトランザクション全体を再実行します。 ## AUTH KEY認証 公開鍵によるチャレンジ認証では、パスワードの代わりにローカルの秘密鍵でサーバーチャレンジに署名します。 ```java Properties properties = new Properties(); properties.setProperty("user", "app_user"); properties.setProperty("AUTH_MODE", "CHALLENGE"); properties.setProperty("AUTH_SIG_SCHEME", "ECDSA"); properties.setProperty( "AUTH_KEY_FILE", "/opt/machbase/keys/app_user_ecdsa.pem"); Connection connection = DriverManager.getConnection( "jdbc:machbase://127.0.0.1:5656/machbasedb", properties); ``` - `AUTH_MODE=CHALLENGE`では認証に`password`を使用しません。 - `AUTH_KEY_FILE`は必須です。 - `AUTH_SIG_SCHEME`を省略すると、鍵の種類に合うデフォルト署名方式を選択します。 - POSIX環境では秘密鍵ファイルの権限を`600`に制限します。 ## クイックスタート 次の例はLOGテーブルに値を入力し、再検索します。 ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; public class JdbcQuickStart { public static void main(String[] args) throws Exception { Properties properties = new Properties(); properties.setProperty("user", "SYS"); properties.setProperty( "password", System.getenv("MACHBASE_PASSWORD")); try (Connection connection = DriverManager.getConnection( "jdbc:machbase://127.0.0.1:5656/machbasedb", properties); Statement statement = connection.createStatement()) { statement.execute( "CREATE LOG TABLE jdbc_sensor " + "(ts DATETIME, name VARCHAR(40), value DOUBLE)"); try (PreparedStatement insert = connection.prepareStatement( "INSERT INTO jdbc_sensor VALUES (?, ?, ?)")) { insert.setLong(1, System.currentTimeMillis() * 1_000_000L); insert.setString(2, "sensor-1"); insert.setDouble(3, 25.3); insert.executeUpdate(); } try (ResultSet result = statement.executeQuery( "SELECT name, value FROM jdbc_sensor")) { while (result.next()) { System.out.printf("%s %.1f%n", result.getString("NAME"), result.getDouble("VALUE")); } } } } } ``` DATETIMEにエポックナノ秒値を渡す場合は`long`を使用します。例のテーブルがすでに存在する場合は、 `CREATE LOG TABLE`を省略するか別名を使用します。 ## INSERT結果のROWID Standard Editionで単一の`INSERT ... VALUES`が成功すると、JDBC標準の生成キーAPIで入力行の ROWIDを確認できます。 ```java String sql = "INSERT INTO jdbc_sensor VALUES (?, ?, ?)"; try (PreparedStatement insert = connection.prepareStatement( sql, Statement.RETURN_GENERATED_KEYS)) { insert.setLong(1, System.currentTimeMillis() * 1_000_000L); insert.setString(2, "sensor-2"); insert.setDouble(3, 26.1); insert.executeUpdate(); try (ResultSet keys = insert.getGeneratedKeys()) { if (keys.next()) { java.sql.RowId rowId = keys.getRowId("ROWID"); } } } ``` 結果は1つの`ROWID`列と最大1行で構成されます。返すROWIDがない場合は空の`ResultSet`です。 サポート状況は`DatabaseMetaData.supportsGetGeneratedKeys()`で確認します。 バッチ、Append、`INSERT ... SELECT`、UPSERTの違いは [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## バージョンの確認 ```java import java.sql.DatabaseMetaData; DatabaseMetaData metadata = connection.getMetaData(); System.out.println(metadata.getDriverName()); System.out.println(metadata.getDriverVersion()); System.out.println(metadata.getJDBCMajorVersion()); // 4 System.out.println(metadata.getJDBCMinorVersion()); // 2 ``` ## 関連ドキュメント | ドキュメント | 内容 | |------|------| | [PreparedStatementと型](./prepared-types/) | パラメーターメタデータ、名前付きbind、SQLType、NULL、型変換 | | [ResultSet、Statement、LOB](./resultset-lob/) | 型指定の検索、ストリーム、LOB、タイムアウト、リソース管理 | | [トランザクションと接続プール](./transaction-pooling/) | Standardのローカルトランザクション、DataSource、接続プール | | [DatabaseMetaData](./database-metadata/) | テーブル、列、キー、インデックス、機能の検索 | | [Append API](./append-api/) | `MachStatement`による高速入力 | | [移行とトラブルシューティング](./migration-troubleshooting/) | 旧ドライバーからの移行、非サポート機能、エラー処理 | --- title: "11.5.1 PreparedStatementと型" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/prepared-types/ language: ja kind: page --- # 11.5.1 PreparedStatementと型 PreparedStatementはSQLをサーバーでprepareし、パラメーターだけを変えて繰り返し実行します。 Machbase JDBCは標準の位置指定パラメーターと名前付き拡張パラメーターを提供します。 ## ParameterMetaData `PreparedStatement.getParameterMetaData()`で実行前にパラメーターの数と型を確認できます。 INSERT、UPDATE、SELECTで同じように使用します。 ```java import java.sql.ParameterMetaData; import java.sql.PreparedStatement; try (PreparedStatement statement = connection.prepareStatement( "INSERT INTO sensor_tx " + "(id, value, created_at) VALUES (?, ?, ?)")) { ParameterMetaData metadata = statement.getParameterMetaData(); for (int index = 1; index <= metadata.getParameterCount(); index++) { System.out.printf( "%d: type=%s precision=%d scale=%d nullable=%d%n", index, metadata.getParameterTypeName(index), metadata.getPrecision(index), metadata.getScale(index), metadata.isNullable(index)); } } ``` パラメーターのインデックスは1から始まります。0またはパラメーター数を超えるインデックスは `SQLException`になります。precisionは型に応じて解釈します。数値型では保存バイト数ではなく、 JDBCの10進桁数を表します。DATETIMEは`java.sql.Types.TIMESTAMP`にマッピングされますが、 データベースの型名は`DATETIME`です。 ## Named Bind Parameter `:name`プレースホルダーと`MachPreparedStatement.setObject(String, Object)`はMachbase拡張です。 同じ名前が複数回現れると、その名前のすべての位置に値が適用されます。 ```java import com.machbase.jdbc.MachPreparedStatement; try (MachPreparedStatement statement = (MachPreparedStatement) connection.prepareStatement( "SELECT id FROM sensor_tx " + "WHERE id = :id OR parent_id = :id")) { statement.setObject("id", Integer.valueOf(10)); try (ResultSet result = statement.executeQuery()) { while (result.next()) { System.out.println(result.getInt("ID")); } } } ``` - 名前の先頭のコロンは指定・省略のどちらも可能です。 - 名前は大文字と小文字を区別します。 - 1つの文で名前付きsetterと数値インデックスsetterを混用しません。 - SQLにない名前、または名前付き・位置指定の混用はSQLState `07009`になります。 - 名前付きbindをサポートしない旧サーバーではSQLState `0A000`になります。 移植性が必要なアプリケーションは、JDBC標準の`?`と数値インデックスsetterを使用します。 共通の名前構文は[Named Bind Parameter](/ja/dbms/reference/sql/syntax/named-bind-parameter-syntax/)を 参照してください。 ## Prepared SELECTの再実行 同じPreparedStatementでSELECTを繰り返し実行できます。前のResultSetを閉じて値を再バインドすると、 次の実行で新しいResultSetを返します。 ```java try (PreparedStatement statement = connection.prepareStatement( "SELECT id, name FROM sensor_tx WHERE id = ?")) { ResultSetMetaData metadata = statement.getMetaData(); System.out.println(metadata.getColumnCount()); for (int id = 1; id <= 2; id++) { statement.setInt(1, id); try (ResultSet result = statement.executeQuery()) { while (result.next()) { System.out.println(result.getString("NAME")); } } } } ``` Machbase JDBCは1つのStatementで複数の結果を同時に開く機能をサポートしません。各実行のResultSetを 読み取って閉じてから、次の実行を開始します。prepare段階の`ResultSetMetaData`は、Statementが 開いている間は再取得できます。 ## JDBC 4.2 SQLTypeのバインディング Java 8の`JDBCType`でパラメーターのSQL型を指定できます。 ```java import java.math.BigDecimal; import java.sql.JDBCType; import java.sql.Timestamp; try (PreparedStatement statement = connection.prepareStatement( "INSERT INTO sensor_tx " + "(id, name, value, created_at, payload) " + "VALUES (?, ?, ?, ?, ?)")) { statement.setObject(1, Integer.valueOf(1), JDBCType.INTEGER); statement.setObject(2, "sensor-1", JDBCType.VARCHAR); statement.setObject( 3, new BigDecimal("12.3400"), JDBCType.DECIMAL, 4); statement.setObject( 4, Timestamp.valueOf("2026-07-26 10:00:00"), JDBCType.TIMESTAMP); statement.setObject(5, new byte[] {1, 2, 3}, JDBCType.BINARY); statement.executeUpdate(); } ``` 不明なベンダー`SQLType`は`SQLFeatureNotSupportedException`になります。 DECIMALとNUMERICは`BigDecimal`を使用し、指定スケールに合わせてバインドします。 ### SQL NULL `setNull()`または`setObject(index, null, JDBCType)`を使用すると、対象型に合うSQL NULLが 渡されます。次の型も型付きNULLをサポートします。 - `REAL`、`BIT`、`TINYINT`、`BOOLEAN` - `VARBINARY`、`LONGVARBINARY`、`BLOB`、`CLOB` - `LONGVARCHAR` 符号なしパラメーターのNULLは、ParameterMetaDataに基づいてネイティブのNULL値に変換されます。 符号なし型の最大データ値より1大きい通信上のNULLセンチネルは実データとして保存できず、 その値を渡すとSQLState `22003`になります。 | Machbaseの型 | Javaの型 | データ範囲 | |---------------|-----------|-------------| | `USHORT` | `Integer` | 0~65534 | | `UINTEGER` | `Long` | 0~4294967294 | | `ULONG` | `BigInteger` | 0~18446744073709551614 | NULLを入力する場合はセンチネル値を直接渡さず、`setNull()`を使用します。 ## Boolean `setBoolean()`と`setObject(index, value, JDBCType.BOOLEAN)`は、`true`を1、`false`を0として 渡します。文字列は大文字・小文字を問わず`true`と`false`のみ許可され、それ以外はSQLState `22018`に なります。 ## IPv4とIPv6 IPアドレス列には`MachPreparedStatement`の拡張setterを使用できます。 ```java MachPreparedStatement statement = (MachPreparedStatement) connection.prepareStatement( "INSERT INTO net_log(ts, src_ip, dst_ip) VALUES (?, ?, ?)"); statement.setLong(1, System.currentTimeMillis() * 1_000_000L); statement.setIpv4(2, "192.168.1.100"); statement.setIpv6(3, "::1"); statement.executeUpdate(); ``` ## NULL許容性のメタデータ `ParameterMetaData.isNullable()`は`parameterNoNulls`、`parameterNullable`、 `parameterNullableUnknown`のいずれかを返します。`parameterNullableUnknown`をNOT NULLと 解釈しないでください。SQL別の判定規則は [NULL許容性メタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-nullable-metadata)を 参照してください。 --- title: "11.5.2 ResultSet、Statement、LOB" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/resultset-lob/ language: ja kind: page --- # 11.5.2 ResultSet、Statement、LOB Machbase JDBCのResultSetは前方のみの読み取り専用カーソルです。 Connection、Statement、ResultSetはtry-with-resourcesで閉じます。 ```java statement.getResultSetType(); // ResultSet.TYPE_FORWARD_ONLY statement.getResultSetConcurrency(); // ResultSet.CONCUR_READ_ONLY ``` スクロール可能または更新可能なResultSetはサポートしません。`next()`の前、最終行の後、close後の getter呼び出しや、範囲外の列インデックスは`SQLException`になります。 ## 型指定の検索 `getObject(index, Class)`と`getObject(label, Class)`をサポートします。 ```java import java.math.BigDecimal; import java.sql.Timestamp; try (ResultSet result = statement.executeQuery( "SELECT id, value, created_at FROM sensor_tx")) { while (result.next()) { Integer id = result.getObject("ID", Integer.class); BigDecimal value = result.getObject("VALUE", BigDecimal.class); Timestamp createdAt = result.getObject("CREATED_AT", Timestamp.class); } } ``` | Javaの型 | 一般的なMachbaseの型 | |-----------|-------------------------| | `String` | CHAR、VARCHAR、TEXT、IPV4、IPV6、JSON | | `Short`, `Integer`, `Long` | 整数型 | | `Float`, `Double` | 実数型 | | `BigDecimal` | DECIMAL、NUMERIC | | `Boolean` | BOOLEAN | | `Timestamp`, `Date`, `Time` | DATETIME | | `byte[]` | BINARY | | `Blob`, `Clob` | BLOB、CLOB | SQL NULLはオブジェクトgetterでJavaの`null`を返します。プリミティブgetterは0または`false`を返すため、 直後の`wasNull()`でSQL NULLかを確認します。非サポートの変換や対象クラスのnull指定は `SQLException`になります。 Machbase SQLでは空文字列リテラル`''`はSQLの`NULL`です。そのため、該当結果列の `ResultSetMetaData.isNullable()`は`columnNullable`、`getObject()`は`null`を返します。 `''''`は単一引用符1文字であり、NULLではない文字列です。 符号なし型のデフォルトのオブジェクトマッピングは次のとおりです。 | Machbaseの型 | `getObject()`の戻り値の型 | |---------------|-------------------------| | `USHORT` | `Integer` | | `UINTEGER` | `Long` | | `ULONG` | `BigInteger` | `SHORT`は`Integer`、32ビットの`FLOAT`は`Float`オブジェクトとして返します。 BOOLEAN文字列は`true`と`false`のみ許可します。 ## 文字・バイナリストリーム `setAsciiStream()`、`setBinaryStream()`、`setCharacterStream()`は、長さを`int`、`long`で 指定するオーバーロードと、長さを指定しないオーバーロードを提供します。`setNCharacterStream()`と `setNString()`は専用のNCHAR保存型ではなく、VARCHAR経路の別名です。 ResultSetでは次のgetterをインデックスまたは列名で使用できます。 - `getAsciiStream()`、`getBinaryStream()` - `getCharacterStream()`、`getNCharacterStream()` - `getNString()` 長さ指定の入力が宣言した長さより短い場合、長さが負の場合、`Integer.MAX_VALUE`を超える場合は `SQLException`になります。現在のストリームはクライアントメモリに全体を実体化するため、 一定のメモリだけで処理する大容量ストリーミングには使用しません。 ## BLOBとCLOB LOGテーブルのBLOB/CLOB列は標準の`Blob`と`Clob`オブジェクトで検索・バインドできます。 ```java import java.io.ByteArrayInputStream; import java.io.StringReader; import java.sql.Blob; import java.sql.Clob; try (PreparedStatement insert = connection.prepareStatement( "INSERT INTO event_log (payload, message) VALUES (?, ?)")) { insert.setBlob(1, new ByteArrayInputStream(payload)); insert.setClob(2, new StringReader(message)); insert.executeUpdate(); } try (ResultSet result = statement.executeQuery( "SELECT payload, message FROM event_log")) { while (result.next()) { Blob payloadObject = result.getBlob("PAYLOAD"); Clob messageObject = result.getClob("MESSAGE"); byte[] payloadBytes = payloadObject.getBytes( 1, (int) payloadObject.length()); String messageText = messageObject.getSubString( 1, (int) messageObject.length()); payloadObject.free(); messageObject.free(); } } ``` `Connection.createBlob()`と`createClob()`で変更可能なオブジェクトを作成し、`setBytes()`、 `setString()`、`setBinaryStream()`、`setCharacterStream()`、`truncate()`を使用できます。 使用後は`free()`を呼び出します。 LOBの位置はJDBC標準に従い1から始まります。部分ストリームの要求範囲全体が実際の値の範囲内に ある必要があり、末尾を超える場合は短く切り詰めて返さず、SQLState `22003`になります。 負の長さやJava配列で表現できない長さは`HY090`です。`free()`後のオブジェクト再使用は `SQLException`になります。 LOBは値全体をクライアントメモリに実体化します。数百MiB以上の値を一定のメモリで処理する ストリーミングLOB実装ではありません。 ## ResultSetメタデータ `ResultSetMetaData.isNullable()`でSELECT結果列のNULL許容性を確認します。 ```java ResultSetMetaData metadata = result.getMetaData(); int nullable = metadata.isNullable(columnIndex); ``` `columnNullableUnknown`はNOT NULLを意味しません。テーブル列の制約は `DatabaseMetaData.getColumns()`、PRIMARY KEYは`DatabaseMetaData.getPrimaryKeys()`で別途確認します。 ## 行数とフェッチ設定 JDBC 4.2のlarge update APIは更新件数を`long`で返します。 ```java long count = statement.executeLargeUpdate( "DELETE FROM sensor_tx WHERE id < 100"); long[] counts = statement.executeLargeBatch(); ``` `setLargeMaxRows()`と`getLargeMaxRows()`も使用できます。`setMaxRows()`または `setLargeMaxRows()`はResultSetで取得する最大行数を制限しますが、Statementの`fetchSize`値は 変更しません。 ## Statementのライフサイクル - `closeOnCompletion()`を設定すると、最後のResultSetが閉じる際にStatementも閉じます。 - 1つのStatementの前のResultSetは、再実行前に閉じます。 - コミットはResultSetを閉じますが、StatementとPreparedStatementは再利用できます。 - 1つのResultSetの`next()`とgetterを複数スレッドで同時に呼び出しません。 ## キャンセルとクエリタイムアウト `Statement.cancel()`は現在実行中の文を別セッションからキャンセルします。実行中の文がなければ 何もせず、PreparedStatementのバインドとメタデータは維持されます。 `setQueryTimeout(seconds)`が期限切れになると、`SQLTimeoutException`とSQLState `HYT00`が 発生します。同じStatementは例外処理後に次のクエリで再利用できます。 前の実行のタイムアウト処理が、次の実行をキャンセルすることはありません。 独立したクエリを並列実行するには、同じConnectionを複数ワーカーで共有せず、接続プールから ワーカーごとに論理Connectionを借り出します。実行中のフェッチを終了する場合は、別スレッドから `close()`、`cancel()`、`Connection.abort()`を呼び出せます。 --- title: "11.5.3 トランザクションと接続プール" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/transaction-pooling/ language: ja kind: page --- # 11.5.3 トランザクションと接続プール Machbase JDBCはStandard EditionのTRANSACTIONテーブルで標準JDBCのローカルトランザクションを サポートします。Cluster EditionにはTRANSACTIONテーブルがないため、このページのトランザクション 機能は適用しません。 ## TRANSACTIONテーブルの作成 ```sql CREATE TRANSACTION TABLE sensor_tx ( id INTEGER PRIMARY KEY, parent_id INTEGER, name VARCHAR(64), value DECIMAL(20, 4), created_at DATETIME, payload BINARY ); ``` ## コミットとロールバック `setAutoCommit(false)`、`commit()`、`rollback()`を使用します。 アプリケーションからSQLの`BEGIN`を直接送る必要はありません。 ```java import java.sql.PreparedStatement; import java.sql.SQLException; connection.setAutoCommit(false); try (PreparedStatement statement = connection.prepareStatement( "INSERT INTO sensor_tx (id, value) VALUES (?, ?)")) { statement.setInt(1, 1); statement.setBigDecimal(2, new BigDecimal("10.5000")); statement.executeUpdate(); connection.commit(); } catch (SQLException exception) { try { connection.rollback(); } catch (SQLException rollbackException) { exception.addSuppressed(rollbackException); } throw exception; } ``` `setAutoCommit(false)`は直ちに`BEGIN`を送りません。手動モードで最初のStatementを実行する際に トランザクションを開始します。コミットまたはロールバック後もauto-commitは`false`のままで、 次のStatementが新しいトランザクションを開始します。 - `setAutoCommit(true)`へ切り替える際、有効なトランザクションがあれば先にコミットします。 - auto-commitが`true`のときに`commit()`または`rollback()`を呼ぶと、SQLState `25000`になります。 - Connectionを閉じる際、未完了のトランザクションはロールバックされます。 - コミットとロールバックは開いたResultSetを閉じますが、Statementは再利用できます。 ## 分離レベルとカーソル サポートする分離レベルは`Connection.TRANSACTION_SERIALIZABLE`です。他の分離レベルを要求すると `SQLFeatureNotSupportedException`になります。 サポートするカーソル保持設定は`ResultSet.CLOSE_CURSORS_AT_COMMIT`です。 コミット前に必要なResultSetを読み取るか、コミット後にクエリを再実行します。 ## テーブルタイプ別の動作 | 操作 | 手動トランザクションでの動作 | |------|--------------------------| | TRANSACTIONテーブルのDML/SELECT | トランザクションに参加します。 | | LOG/TAGテーブルのSELECT | 実行できます。 | | TRANSACTION変更前の最初のLOG DML | 互換経路でauto-commitとして再実行される場合があります。 | | 独立したTAG DML | トランザクションに参加し、ロールバックできます。 | | TRANSACTION変更後のLOG/TAG DMLまたはDDL | エラーになります。 | 互換経路でauto-commit再実行されたLOG DMLは、後続のロールバック対象ではありません。 ロールバックが必要なデータにはTRANSACTIONテーブルを使用します。複数のTRANSACTIONテーブルの 通常のコミットとロールバックはサポートしますが、バックエンドのコミット中に障害が起きた場合の 全体の原子性は保証しません。重要なアトミック操作は1つのTRANSACTIONテーブルの範囲で設計します。 ## DataSource `MachDataSource`は、アプリケーションサーバーやフレームワークに接続プロパティを注入する際に使用します。 ```java import com.machbase.jdbc.MachDataSource; import java.sql.Connection; MachDataSource dataSource = new MachDataSource(); dataSource.setUrl("jdbc:machbase://127.0.0.1:5656/machbasedb"); dataSource.setUser("SYS"); dataSource.setPassword(System.getenv("MACHBASE_PASSWORD")); dataSource.setLoginTimeout(10); try (Connection connection = dataSource.getConnection()) { // SQLを実行します。 } ``` DataSourceはURL、ユーザー、password、ログインタイムアウト、ログwriter、JDBCの`Wrapper`仕様を サポートします。 ## ConnectionPoolDataSource `MachConnectionPoolDataSource`は物理接続を直接公開せず、論理Connectionを返します。 ```java import com.machbase.jdbc.MachConnectionPoolDataSource; import java.sql.Connection; import javax.sql.PooledConnection; MachConnectionPoolDataSource source = new MachConnectionPoolDataSource(); source.setUrl("jdbc:machbase://127.0.0.1:5656/machbasedb"); source.setUser("SYS"); source.setPassword(System.getenv("MACHBASE_PASSWORD")); PooledConnection pooled = source.getPooledConnection(); try { try (Connection logical = pooled.getConnection()) { // 論理接続を使用します。 } } finally { pooled.close(); } ``` 1つのPooledConnectionでは論理ハンドルを1つだけ有効にします。論理Connectionを閉じると、 次の状態を初期化してから`connectionClosed`イベントが1回発生します。 - 未完了トランザクションのロールバック - auto-commitの復元 - URLで決まる初期カタログの復元 - ネットワークタイムアウトの復元 クローズを開始した論理ハンドルの呼び出しが終わる前に、次の貸し出しは行いません。 閉じたConnection、Statement、DatabaseMetaDataは次に接続を借りたリクエストで再利用できず、 SQLState `08003`になります。Statement poolingはサポートしません。 SQLStateクラス`08`の致命的な接続エラーでは物理接続を破棄し、`connectionErrorOccurred`を発生させます。 重複キーなどクラス`23`のエラーは接続破損ではないため、接続エラーイベントを発生させません。 ## HikariCP ```java import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:machbase://127.0.0.1:5656/machbasedb"); config.setUsername("SYS"); config.setPassword(System.getenv("MACHBASE_PASSWORD")); config.setMaximumPoolSize(10); config.setMinimumIdle(2); config.setConnectionTimeout(30_000); config.setIdleTimeout(600_000); config.setMaxLifetime(1_800_000); config.addDataSourceProperty("TIMEZONE", "+0900"); try (HikariDataSource dataSource = new HikariDataSource(config); Connection connection = dataSource.getConnection()) { // SQLを実行します。 } ``` 論理Connectionはtry-with-resourcesで速やかに返却し、返却済みのハンドルを保持しません。 ## ネットワークタイムアウト `setNetworkTimeout(executor, milliseconds)`はソケット読み取りタイムアウトをミリ秒単位で設定し、 `0`は無制限です。負の値、null executor、またはタスクを拒否するexecutorは`SQLException`になります。 実際にネットワークタイムアウトが発生するとSQLStateクラス`08`の例外が発生し、物理接続は無効になります。 その接続で作成したStatementとResultSetは再利用せず、新しい接続を借り出します。 有効なトランザクションのI/O失敗は自動再実行しません。 --- title: "11.5.4 DatabaseMetaData" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/database-metadata/ language: ja kind: page --- # 11.5.4 DatabaseMetaData `Connection.getMetaData()`はドライバー、サーバー、スキーマオブジェクト、JDBC機能の情報を返します。 結果列はJDBC標準の名前と順序を使用するため、数値の位置より列名で読み取ることを推奨します。 ```java import java.sql.DatabaseMetaData; DatabaseMetaData metadata = connection.getMetaData(); System.out.println(metadata.getDriverName()); System.out.println(metadata.getDriverVersion()); System.out.println(metadata.getDatabaseProductName()); System.out.println(metadata.getDatabaseProductVersion()); ``` ## テーブルとVIEW ```java try (ResultSet tables = metadata.getTables( null, null, "%", new String[] {"TABLE", "VIEW"})) { while (tables.next()) { System.out.printf("%s %s%n", tables.getString("TABLE_NAME"), tables.getString("TABLE_TYPE")); } } ``` `getTables()`はTABLEとVIEWを区別します。Machbaseの詳細なテーブルタイプは`REMARKS`で確認します。 アプリケーションは特定の位置番号に依存せず、標準列名を使用します。 ## 列 ```java try (ResultSet columns = metadata.getColumns( null, null, "SENSOR_TX", "%")) { while (columns.next()) { System.out.printf( "%s %s size=%d nullable=%s%n", columns.getString("COLUMN_NAME"), columns.getString("TYPE_NAME"), columns.getInt("COLUMN_SIZE"), columns.getString("IS_NULLABLE")); } } ``` `NULLABLE`は数値定数、`IS_NULLABLE`は`YES`、`NO`、または空文字列で返ります。 LOOKUPとVOLATILEテーブルのPRIMARY KEYは、明示的なNOT NULL句がなくても`columnNoNulls`と `NO`で返ります。 VARCHAR、DATETIME、BINARY、BLOB、CLOBなど数値属性が適用されない列の`DECIMAL_DIGITS`と `NUM_PREC_RADIX`はSQL NULLです。`getInt()`の0だけを見ず、`getObject()`または`wasNull()`で NULLかどうかを確認します。 ## PRIMARY KEYとインデックス ```java try (ResultSet keys = metadata.getPrimaryKeys( null, null, "SENSOR_TX")) { while (keys.next()) { System.out.printf("%s position=%d%n", keys.getString("COLUMN_NAME"), keys.getShort("KEY_SEQ")); } } try (ResultSet indexes = metadata.getIndexInfo( null, null, "SENSOR_TX", false, false)) { while (indexes.next()) { System.out.printf("%s %s%n", indexes.getString("INDEX_NAME"), indexes.getString("COLUMN_NAME")); } } ``` PRIMARY KEYかどうかを`ResultSetMetaData.isNullable()`の値から推測しません。 `getPrimaryKeys()`と`getIndexInfo()`を使用します。 SELECT結果の直接の列がPKかどうかは、Machbase JDBC拡張の `MachResultSetMetaData.isPrimaryKey(column)`で確認できます。 ```java import com.machbase.jdbc.MachResultSetMetaData; try (ResultSet result = statement.executeQuery( "SELECT ID, ID + 1 AS ID_EXPR FROM SENSOR_TX")) { MachResultSetMetaData resultMetadata = (MachResultSetMetaData) result.getMetaData(); System.out.println(resultMetadata.isPrimaryKey(1)); // trueまたはfalse System.out.println(resultMetadata.isPrimaryKey(2)); // 式: false } ``` `getPrimaryKeys()`はテーブルカタログのPKを検索し、`isPrimaryKey()`は現在のSELECT結果の 列メタデータを取得します。旧バージョンのサーバーまたはSDKに接続した場合、結果列のPKフラグが `false`として返る場合があります。 ## スキーマと型情報 次のメソッドはJDBC標準形式のResultSetを返します。 - `getSchemas()`、`getCatalogs()`、`getTableTypes()` - `getTypeInfo()` - `getTables()`、`getColumns()` - `getPrimaryKeys()`、`getIndexInfo()` 非サポートの任意メタデータ検索は、nullや非標準のResultSetではなく、標準列を持つ空のResultSetを 返す場合があります。機能を使用する前に機能メソッドを確認します。 ```java if (metadata.supportsSavepoints()) { // 対応環境でのみセーブポイントを使用します。 } ``` ## カタログ `Connection.getCatalog()`と`setCatalog()`は、ドライバーが公開する現在のカタログ値を管理します。 メタデータメソッドのカタログ引数は、この値と一致する要求をフィルターするために使用します。 ```java String initialCatalog = connection.getCatalog(); connection.setCatalog(initialCatalog); ``` 接続プールに論理Connectionを返却すると、カタログはURLで決まる初期値に復元されます。 前の接続貸し出し期間で取得したDatabaseMetaDataオブジェクトは、次の貸し出し期間で再利用しません。 ## サポート範囲の確認 Machbase JDBCは実際のサポート範囲を機能情報に反映します。たとえばトランザクションの分離レベル、 ResultSetの種類、セーブポイント、生成キー、複数結果の同時オープンのサポートを次のように確認します。 ```java System.out.println(metadata.supportsTransactions()); System.out.println(metadata.supportsTransactionIsolationLevel( Connection.TRANSACTION_SERIALIZABLE)); System.out.println(metadata.supportsResultSetType( ResultSet.TYPE_FORWARD_ONLY)); System.out.println(metadata.supportsSavepoints()); System.out.println(metadata.supportsGetGeneratedKeys()); System.out.println(metadata.supportsMultipleOpenResults()); ``` `Driver.jdbcCompliant()`が`false`であることと、個々のJDBC APIのサポート状況は別です。 アプリケーションは必要な機能を直接確認します。 Standard EditionでROWID対応サーバーに接続すると、`supportsGetGeneratedKeys()`は`true`、 `getRowIdLifetime()`は`ROWID_VALID_OTHER`を返します。非対応サーバーまたはCluster Editionでは、 それぞれ`false`と`ROWID_UNSUPPORTED`を返します。使用例は [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 --- title: "11.5.5 Append API" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/append-api/ language: ja kind: page --- # 11.5.5 Append API Machbase Append APIは複数行を連続して入力する大量入力APIです。JDBCでは`MachStatement`の 拡張メソッドを使用します。このページはLOG入力の例を中心に説明します。他のテーブルタイプの サポート範囲は[SDKサポート表](../../sdk-support-scope/#append-table-type-matrix)も確認してください。 ## API | メソッド | 説明 | |--------|------| | `executeAppendOpen(tableName, errorCheckCount)` | Appendセッションを開始し、列メタデータを返します。 | | `executeAppendOpen(tableName, inputColumns, errorCheckCount)` | Machbase DBMS 8.7.0で選択列またはARRAY要素を対象にAppendセッションを開始します。 | | `executeAppendData(metadata, data)` | 1行を送信します。 | | `executeAppendDataByTime(metadata, time, data)` | ナノ秒の時刻を指定して1行を送信します。 | | `executeAppendFlush()` | 保留中の応答を同期します。 | | `executeAppendClose()` | Appendセッションを終了します。 | | `executeSetAppendErrorCallback(callback)` | 行エラーのコールバックを登録します。 | | `getAppendSuccessCount()` | 成功した行数を返します。 | | `getAppendFailureCount()` | 失敗した行数を返します。 | 公開メソッド`executeAppendData()`は成功すると`1`を返し、無効な内部結果には`SQLException`を スローします。最終的な成功・失敗件数とコールバックも確認します。 ## 入力例 ```sql CREATE LOG TABLE sensor_data ( time DATETIME, name VARCHAR(40), value DOUBLE ); ``` ```java import com.machbase.jdbc.MachStatement; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; try (MachStatement statement = (MachStatement) connection.createStatement()) { ResultSet appendResult = statement.executeAppendOpen("sensor_data", 100); ResultSetMetaData metadata = appendResult.getMetaData(); statement.executeSetAppendErrorCallback( (errorNumber, errorMessage, rowMessage) -> System.err.printf( "Append error [%05d]: %s%n%s%n", errorNumber, errorMessage, rowMessage)); long baseTime = System.currentTimeMillis() * 1_000_000L; for (int index = 0; index < 10_000; index++) { ArrayList row = new ArrayList<>(); row.add(baseTime + index); row.add("sensor-" + (index % 10)); row.add(20.0 + index * 0.001); int result = statement.executeAppendData(metadata, row); if (result != 1 && result != 2) { throw new SQLException( "Append failed at row " + index); } } statement.executeAppendFlush(); statement.executeAppendClose(); appendResult.close(); System.out.printf("success=%d failure=%d%n", statement.getAppendSuccessCount(), statement.getAppendFailureCount()); } ``` ## ARRAYと選択列 スパースARRAY入力に列選択は必須ではありません。通常の `executeAppendOpen(tableName, errorCheckCount)`で開き、返されたメタデータに合わせて `MachSparseArray`を行のARRAY値として渡します。 ```java ResultSet opened = statement.executeAppendOpen("ARRAY_APPEND_FULL_EXAMPLE", 0); ``` 接続・入力・Close・検索を含む[通常Openの例](../../data-input-load-export/array-append/#jdbc-full-open)を 先に確認してください。`ID`とARRAY列を宣言順で渡し、自動の`_arrival_time`は行に追加しません。 Machbase DBMS 8.7.0では、`executeAppendOpen()`のオーバーロードに列名や `ARRAY_COLUMN[position]`を渡せます。 ```java ResultSet appendResult = statement.executeAppendOpen( "sensor_array", new String[] {"ID", "CHANNELS[0]", "CHANNELS[3]"}, 0); ``` 行ごとに異なるARRAY位置を入力する場合は、`MachConnection.createSparseArrayOf()`で `MachSparseArray`を作成します。mapキーは0から始まり、空のmapは全要素がNULLのARRAYです。 Javaの`null`は配列全体のNULLです。 ```java Map entries = new HashMap(); entries.put(Integer.valueOf(1), Integer.valueOf(200)); entries.put(Integer.valueOf(3), Integer.valueOf(400)); MachSparseArray sparse = connection.createSparseArrayOf( "INT32", 4, entries); ``` 密なARRAYの検索とprepared入力には、`java.sql.Array`、`Connection.createArrayOf()`、 `PreparedStatement.setArray()`を使用します。全体例と対象の衝突規則は [Sparse ARRAYと選択列Append API](../../data-input-load-export/array-append/)を参照してください。 SQLのARRAY要素対象と`MachSparseArray`の位置は0始まりです。JDBC標準のパラメーター番号と `java.sql.Array.getArray(index, count)`のスライスインデックスは従来どおり1始まりのため、 混同しないでください。 ## DATETIME AppendのDATETIME値はエポックナノ秒単位の`long`で渡します。 ```java long epochNanoseconds = System.currentTimeMillis() * 1_000_000L; ``` `executeAppendDataByTime()`は別の時刻値を受け取るテーブル入力経路で使用します。 入力列の順序とJavaの型は、`executeAppendOpen()`が返したResultSetMetaDataに合わせます。 ## フラッシュとクローズ 1. `executeAppendOpen()`でセッションを開始します。 2. `executeAppendData()`を繰り返し呼び出します。 3. 途中の確認が必要な場合は`executeAppendFlush()`を呼び出します。 4. 全入力を送った後、`executeAppendClose()`を呼び出します。 5. 成功・失敗件数とコールバックの結果を確認します。 例外時にもAppendセッションとStatementが閉じるよう、try-with-resourcesと`finally`を使用します。 コールバックでは失敗行を別途保存またはログ記録し、無条件の再試行で重複入力を作らないよう業務キーを 使用します。 ## サイズと使用範囲 ordered appendはプロトコルのパケット上限を共有するため、1行全体のエンコード後サイズを64KiB未満に 保ちます。BLOB/CLOBなど大きな値を入力する場合は、行サイズとクライアントのメモリ使用量を合わせて 確認します。 TRANSACTIONテーブルのAppendバッチはSQLトランザクションに含まれず、独立して反映されます。 ロールバックが必要な複数のDMLには[JDBCトランザクション](../transaction-pooling/)を使用します。 --- title: "11.5.6 移行とトラブルシューティング" url: https://docs.machbase.com/ja/dbms/development-tools-integration/jdbc/migration-troubleshooting/ language: ja kind: page --- # 11.5.6 移行とトラブルシューティング 最新のMachbase JDBCはJava 8/JDBC 4.2を基準として、バージョン報告、メタデータ、型変換、 トランザクション、リソースのライフサイクルを標準JDBC仕様に合わせています。 以前の動作に依存するアプリケーションは、次の違いを確認してください。 ## 旧ドライバーからの移行 | 領域 | 現在の動作 | アプリケーションの確認事項 | |------|-----------|------------------------| | Java/JDBC基準 | Java 8バイトコード、JDBC 4.2を報告 | 実行JDKはJava 8以降を使用します。 | | ドライバーバージョン | ドライバーとメタデータは3.0.0を報告 | バージョン判定ロジックを更新します。 | | 自動検出 | JDBCサービスプロバイダーを提供 | 明示的な`Class.forName()`は任意です。 | | ParameterMetaData | JDBCのprecision、DB型名、Javaクラスを返す | precisionの型別の意味を確認し、保存バイト数とは解釈しません。 | | トランザクション | 遅延`BEGIN`、実際のcommit/rollback | StandardのTRANSACTION操作を明示的に完了します。 | | カーソル保持設定 | `CLOSE_CURSORS_AT_COMMIT` | コミット後にResultSetを再検索します。 | | DatabaseMetaData | 標準結果構造とサポート機能を返す | ドライバー固有の列番号ではなく標準列名を使用します。 | | 型API | 型指定`getObject()`、`JDBCType`、Boolean、符号なし型、LOB | メタデータのJavaクラスで検索・バインドします。 | | エラー | 不正な状態で標準`SQLException`を返す | SQLStateでエラーを分岐します。 | | タイムアウト | クエリ・ネットワークのタイムアウトをサポート | ネットワークタイムアウト後は接続を破棄します。 | | 接続プール | 論理接続の貸し出し期間と状態初期化 | 閉じたハンドルやメタデータを再利用しません。 | | 生成キー | Standardの単一INSERTのROWIDを返す | `getGeneratedKeys()`の`ROWID`を読み取ります。 | 名前付きbindは対応サーバーで使用します。旧サーバーが名前付きbindをサポートしない場合は SQLState `0A000`になるため、位置指定パラメーター`?`に切り替えます。 ## 非サポート機能 次のJDBC任意機能はサポートしません。 - セーブポイント - XAと分散トランザクション - ストアドプロシージャとCallableStatementの成功経路 - スクロール可能または更新可能なResultSet - Statement pooling - 複数結果の同時オープン - Struct、Ref、SQLXML、UDT型マッピング - 専用NClobストレージとファクトリー - Machbase専用RowSetプロバイダー - JDBC 4.3のシャーディングとリクエスト境界API Machbase DBMS 8.7.0とARRAY対応JDBCビルドでは、`java.sql.Array`、`createArrayOf()`、 `setArray()`を使用できます。旧ドライバーのARRAY非サポートの説明は適用せず、 [ARRAYと選択列Append](../append-api/#arrayと選択列)のバージョンとインデックス基準を確認します。 非サポート機能は通常、`SQLFeatureNotSupportedException`とSQLState `0A000`を返します。 機能を呼び出す前にDatabaseMetaDataの機能情報を確認します。 ## `No suitable driver` **症状** `DriverManager.getConnection()`で`No suitable driver`が発生します。 **確認と解決** 1. 実行クラスパスに`machbase.jar`があるか確認します。 2. JARに`META-INF/services/java.sql.Driver`があるか確認します。 3. URLが`jdbc:machbase://:/machbasedb`形式か確認します。 4. 複数バージョンのMachbase JDBC JARが同時に含まれていないか確認します。 ## SQLState `0A000` 選択した機能またはサーバーがそのAPIをサポートしていません。セーブポイント、スクロール可能なカーソル、 XAには代替フローを使用します。生成キーはStandard EditionとROWID対応のサーバー・JDBCの組み合わせで 使用し、`DatabaseMetaData.supportsGetGeneratedKeys()`で確認します。 名前付きbindで発生した場合は、位置指定パラメーター`?`を使用します。 ## コミット後にResultSetが閉じる 正常な動作です。Machbaseのトランザクションのカーソル保持設定は`CLOSE_CURSORS_AT_COMMIT`です。 コミット前に結果を読み取るか、コミット後にクエリを再実行します。 StatementとPreparedStatementは再利用できます。 ## LOG DMLがロールバックされない 手動トランザクションでTRANSACTIONテーブルを変更する前に実行した最初のLOG DMLは、互換経路で auto-commitとして再実行される場合があります。この入力は後続のロールバック対象ではありません。 ロールバックが必要なデータにはTRANSACTIONテーブルを使用します。 ## 複数のTRANSACTIONテーブルをまとめてコミット 通常のコミットとロールバックはサポートしますが、バックエンドのコミット中に障害が発生した場合、 複数のTRANSACTIONテーブルの全体の原子性は保証しません。 重要なアトミック操作は1つのTRANSACTIONテーブルの範囲で設計します。 ## ネットワークタイムアウトまたは接続エラー ソケット読み取りタイムアウトやSQLStateクラス`08`の接続エラーが発生した場合、その物理接続は 再利用しません。接続プールから新しい接続を借り、有効なトランザクションは業務の冪等性ポリシーに 従って最初から再実行します。例外だけでコミットの成否を推測しません。 ## クローズしたプールオブジェクトの再利用 論理Connectionを閉じた後、そのConnectionから取得したStatement、ResultSet、DatabaseMetaDataを 次の貸し出し期間で再利用するとSQLState `08003`になります。 各貸し出し期間のオブジェクトはtry-with-resourcesの範囲内だけで使用します。 --- title: "11.6 Python" url: https://docs.machbase.com/ja/dbms/development-tools-integration/python/ language: ja kind: section --- # 11.6 Python ## 概要 パッケージ2.4を基準とします。PyPIのパッケージ名は`machbaseapi`(小文字)です。 純粋なPython実装のため、ネイティブバイナリ(`.so/.dll/.dylib`)は不要です。 既存の`machbase`の使用フローは維持されます。 - インストールするパッケージ名: `machbaseapi` - 従来どおり`import machbaseAPI`を使用 - DB-API形式の`connect()`、`cursor()`をサポート - 2.4から`cursor(prepared=True)`でサーバーの文を複数の呼び出しで再利用 - `append*`には`on_ack`コールバックを追加でき、ACKを観測可能 - `append()`、`appendByTime()`、`appendData()`、`appendDataByTime()`は型リストを省略しても動作し、サーバーメタデータから型を自動推論 - 2.3からAppend行の末尾の一部の列を省略すると、AppendのNULLビットにより`NULL`として保存 - TAGテーブルは`value`列までが必須で、後続の追加列とメタデータ列は省略時に`NULL`として保存可能 - 接続プールオプション(`pool_name`、`pool_size`、`pool_reset_session`)は非サポート ## マルチデータベース `connect(database=...)`で初期データベースを指定できます。現在のカタログのgetter/setterはないため、 接続後に`SELECT CURRENT_DATABASE()`で確認し、SQLの`USE`で変更します。 ```python conn = connect( host='127.0.0.1', port=5656, user='APP_A', password='secret', database='FACTORY_A', ) cur = conn.cursor() cur.execute('SELECT CURRENT_DATABASE()') print(cur.fetchone()) cur.execute('USE FACTORY_B') ``` 既存互換の`machbase.open()`にはデータベース引数がありません。マルチデータベース操作には最新の `connect()`を使用してください。接続プールと文のバインディング規則の詳細は [マルチデータベース運用ガイド](/ja/dbms/operations-configuration-recovery/multi-database/#94-python)を 参照してください。 ## インストール ### 要件 - `pip`を使用できるPython 3.6以降 - 接続可能なMachbaseサーバーとアカウント情報(デフォルトアカウント`SYS/MANAGER`、ポート`5656`) - 2.4にはネイティブライブラリの依存関係なし ### PyPIからインストール ```bash pip3 install machbaseapi ``` `pip3`がPATHにない場合は`python3 -m pip install machbaseapi`を使用します。 ### インストールパッケージからオフラインでインストール インターネットに接続できない環境では、Machbaseインストールパッケージに含まれるwheelをインストールします。 ```bash python3 -m pip install \ $MACHBASE_HOME/3rd-party/python3-module/machbaseapi-2.4-py3-none-any.whl ``` 同じディレクトリのソース配布ファイル`machbaseapi-2.4.tar.gz`も使用できます。 インストール前にPython 3.6以降であることを確認します。 ### モジュールの確認 ```bash python3 - <<'PY' from machbaseAPI import machbase, connect print('machbaseクラスのインポート:', bool(machbase)) print('connect関数の存在:', callable(connect)) print('module import:', __import__('machbaseAPI')) PY ``` このコマンドが成功すれば、パッケージを正常にインポートできます。 ## クイックスタート 次のDB-API例はサンプルLOGテーブルを作成して入力・検索し、テーブルと接続を片付けます。 パスワードは環境変数で渡します。 ```python import os from machbaseAPI import connect conn = connect( host=os.getenv('MACH_HOST', '127.0.0.1'), port=int(os.getenv('MACH_PORT', '5656')), user=os.getenv('MACH_USER', 'SYS'), password=os.environ['MACHBASE_PASSWORD'], ) cur = conn.cursor() try: cur.execute( 'CREATE LOG TABLE py_sample ' '(ts DATETIME, device VARCHAR(40), value DOUBLE)' ) cur.execute( "INSERT INTO py_sample VALUES (" "TO_DATE('2026-01-01','YYYY-MM-DD'), 'sensor-1', 20.5)" ) cur.execute('SELECT device, value FROM py_sample') print(cur.fetchall()) finally: cur.execute('DROP TABLE py_sample') cur.close() conn.close() ``` ## 結果の処理 DB-APIカーソルは`execute()`、`fetchone()`、`fetchall()`を提供します。作業後にカーソルと接続を閉じ、 サンプルオブジェクトが本番データベースに残らないよう削除します。 ### INSERT結果のROWID Standard EditionでDB-APIカーソルを使って単一の`INSERT ... VALUES`を実行した後、 `cursor.lastrowid`で入力行のROWIDを確認できます。 ```python cursor.execute( "INSERT INTO orders(item) VALUES(%s)", ("pump",), ) row_id = cursor.lastrowid ``` 値は任意精度のPython `int`で、符号なし64ビットROWIDを正の値として保持します。 ROWIDのない実行では`None`です。`executemany()`、Append、`INSERT ... SELECT`、UPSERTは ROWIDを返しません。実行失敗後も前の値を再利用しないでください。詳細な条件は [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ### DB-API結果のNULL許容性メタデータ DB-APIカーソルでは`cursor.description[i][6]`の`null_ok`値で、SELECT結果列のNULL許容性を 確認します。 ```python cursor.execute(sql) for column in cursor.description: name = column[0] null_ok = column[6] print(name, null_ok) ``` | `null_ok` | 意味 | |-----------|------| | `False` | NULLにならない | | `True` | NULLになり得る | | `None` | 判定不能 | `None`は`NOT NULL`を意味しないため、NULLが発生し得るものとして処理します。 SQL結果の判定規則は [NULL許容性メタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-nullable-metadata)を 参照してください。 Machbase SQLでは`''`はSQLの`NULL`のため、`null_ok`は`True`です。ただしPythonコネクターは、 互換性のため文字列型のSQL `NULL`をPythonの空文字列`""`として返す場合があります。 `null_ok`は列のNULL許容性を示すもので、個々の行がNULLかは示しません。行ごとの区別が必要な場合は、 SQLの`IS NULL`条件またはそれを使用したCASE結果も検索してください。 ### SELECT結果のPRIMARY KEYメタデータ Machbase 8.7.0サーバーと対応SDKを使用すると、`cursor.column_metadata`の`is_primary_key`で SELECT結果の直接の列がPRIMARY KEYか確認できます。 ```python cursor.execute("SELECT ID, VALUE, ID + 1 AS ID_EXPR FROM T_PK") for column in cursor.column_metadata: print(column.name, column.is_primary_key) ``` `cursor.description`のDB-API標準の7番目の値(`null_ok`)は従来どおりNULL許容性のみを示します。 式・集計式・外部結合のNULL補完側の列はPKではないため、`is_primary_key`は`False`です。 旧バージョンのサーバーまたはSDKではPKフラグが提供されない場合があります。 ### Named Bind Parameter Python DB-APIモジュールの`paramstyle`は`"named"`です。`cursor.execute()`と `cursor.executemany()`にマッピングを渡すと、`:name`のSQLをサーバーのprepare/bind経路で実行します。 ```python from decimal import Decimal from machbaseAPI import connect conn = connect(host="127.0.0.1", port=5656, user="SYS", password="MANAGER") cur = conn.cursor(dictionary=False) cur.execute( """INSERT INTO SENSOR_DATA (ID, NAME, VALUE) VALUES (:id, :name, :value)""", { "id": 600, "name": "python-client", "value": Decimal("52.125000"), }, ) cur.execute( """SELECT ID, NAME FROM SENSOR_DATA WHERE ID = :id OR PARENT_ID = :id""", {"id": 600}, ) ``` `executemany()`では各行をマッピングとして渡します。 ```python cur.executemany( "INSERT INTO SENSOR_DATA (ID, NAME, VALUE) " "VALUES (:id, :name, :value)", [ {"id": 601, "name": "batch-a", "value": Decimal("1.5")}, {"id": 602, "name": "batch-b", "value": None}, ], ) ``` サーバーのプリペアドステートメントの寿命は、カーソルの種類と呼び出し方式によって異なります。 | カーソル | 呼び出し | サーバーの文の再利用範囲 | |--------|------|----------------------------| | 通常カーソル | `execute(sql, params)` | その呼び出しのみ | | 通常カーソル | `executemany(sql, rows)` | その呼び出し内 | | プリペアドカーソル | `execute()` / `executemany()` | 同じ元SQLを使用する後続の呼び出し | 通常カーソルの`:name`とマッピングはサーバーprepare/bindを使用しますが、呼び出しの完了時に文を閉じます。 複数の呼び出しで同じ文を再利用する場合は`cursor(prepared=True)`を使用します。 マッピングのキーは先頭のコロンなしで指定し、大文字・小文字を区別します。同名が繰り返されると1つの値を 全位置に適用します。名前の欠落、余分なキー、名前付きと位置指定の混用は`ProgrammingError`を返します。 旧サーバーで名前付きAPIを使用すると、SQLSTATE `0A000`の`NotSupportedError`を返します。 互換性のため`%s`と`%(name)s`も維持します。この2形式はクライアントでSQLリテラルを生成する通常カーソルの 既存経路です。プリペアドカーソルでは`%s`を`?`、`%(name)s`を`:name`へ変換し、サーバーの prepare/bind経路で実行します。 共通の名前構文は [Named Bind Parameter syntax](../../reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 ## プリペアドカーソル(2.4) `connection.cursor(prepared=True)`はサーバーのプリペアドステートメントを1つ保持し、同じSQLを 複数回実行する際に再利用します。繰り返しINSERT、条件検索、同じSQLのバッチ実行に使用します。 ```python from machbaseAPI import connect conn = connect( host="127.0.0.1", port=5656, user="SYS", password="MANAGER", ) cur = conn.cursor(dictionary=False, raw=False, prepared=True) sql = "INSERT INTO SENSOR_DATA (ID, NAME, VALUE) VALUES (%s, %s, %s)" cur.execute(sql, (700, "sensor-a", 21.5)) cur.execute(sql, (701, "sensor-b", 22.1)) cur.executemany( sql, [ (702, "sensor-c", 23.0), (703, "sensor-d", None), ], ) cur.close() conn.close() ``` `cursor()`の関連引数は次のとおりです。 - `dictionary=True`: 検索結果を列名ベースの辞書として返します。 - `dictionary=False`: 検索結果をタプルとして返します。 - `raw=True`: 既存のraw結果の仕様を維持します。 - `prepared=True`: 公開型`MachbasePreparedCursor`を返します。 - `prepared=False`: 既存の通常カーソルを返すデフォルト値です。 ### パラメーターマーカー プリペアドカーソルはPython DB-API形式とMachbaseネイティブ形式の両方をサポートします。 | 公開プレースホルダー | サーバーのプレースホルダー | パラメーター形式 | |---------------|-------------|----------------| | `%s` | `?` | tuple、listなどのシーケンス | | `?` | `?` | tuple、listなどのシーケンス | | `%(name)s` | `:name` | dictionaryなどのマッピング | | `:name` | `:name` | dictionaryなどのマッピング | 文字列リテラル、引用符で囲まれた識別子、`--`コメント、`/* ... */`コメント内のプレースホルダー状の 文字は変換しません。1つのSQLで位置指定と名前付きプレースホルダーを混用できません。 名前付きプレースホルダーの名前は英字、`_`、`$`で始まり、以降は数字も使用できます。 名前付きプレースホルダーはMachbase 8.7.0サーバーと対応SDKでサポートします。 ```python sql = ( "SELECT ID, NAME FROM SENSOR_DATA " "WHERE ID = %(target)s OR PARENT_ID = %(target)s" ) cur.execute(sql, {"target": 700}) rows = cur.fetchall() ``` ### 文の再利用 プリペアドカーソルは、元のSQL文字列が前の呼び出しと完全に同じ場合にキャッシュしたサーバーの文を 再利用します。空白やコメントも含めて文字列が異なると、既存の文を解放して新しい文を準備します。 ```python insert_cur = conn.cursor(prepared=True) select_cur = conn.cursor(prepared=True) ``` 1つのカーソルが保持するサーバーの文は1つです。複数のSQLをそれぞれ継続して再利用する場合は、 上記のようにSQLごとにプリペアドカーソルを作成します。`executemany()`終了後も文は保持され、 同じSQLの後続の`execute()`または`executemany()`で再利用されます。 空のパラメーターリストを渡すと、文を準備・実行せず`0`を返します。 ### エラーと終了 次の入力は`ProgrammingError`になります。 - プレースホルダーがあるのにパラメーターを渡さない場合 - 位置指定プレースホルダーにマッピング、名前付きプレースホルダーにシーケンスを渡す場合 - 位置指定と名前付きプレースホルダーを混用する場合 - 名前付きパラメーターのキーが欠ける、または不要なキーが追加される場合 - プレースホルダーのないSQLに空でないパラメーターを渡す場合 プレースホルダーのないSQLには、パラメーターなしとして`None`、空のシーケンス、空のマッピングを 渡せます。空のマッピングは内部で`None`に正規化されるため、プロトコルバージョンに関係なく同じ意味で 処理されます。 パラメーターエラーが発生してもキャッシュした文は保持されるため、正しいパラメーターで同じSQLを 再実行できます。旧サーバーで名前付きパラメーターを使用すると、サーバーのPREPARE前に `NotSupportedError`とSQLSTATE `0A000`が発生します。このエラーは現在のキャッシュ文を解放・置換しません。 旧サーバーでは位置指定プレースホルダーを使用します。 `cursor.close()`はキャッシュしたサーバーの文を解放します。同じカーソルを2回閉じても安全で、 接続が先に閉じられた場合はネットワーク要求なしでローカル状態だけを解放します。 閉じたプリペアドカーソルで`execute()`、`executemany()`、フェッチAPIを呼ぶと`InterfaceError`になります。 プリペアドカーソルはSQLの許容範囲やPython APIのauto-commit動作を変更しません。 テーブル別のDML範囲は[サポート範囲と制約](../../reference/support-scope-constraints/)を参照してください。 ## サポートAPIマトリクス | クラス | API | 説明 | 戻り値 | | -- | -- | -- | -- | | `machbase` | `open(host, user, password, port)` | 基本アカウントとポートでMachbaseサーバーに接続します。 | 成功時`1`、失敗時`0` | | `machbase` | `openEx(host, user, password, port, conn_str)` | 追加の接続文字列プロパティで拡張接続します。 | `1`または`0` | | `machbase` | `close()` | 現在のセッションを終了します。 | `1`または`0` | | `machbase` | `isOpened()` | ハンドルが開いているか確認します。 | `1`または`0` | | `machbase` | `isConnected()` | サーバーとの接続状態を確認します。 | `1`または`0` | | `machbase` | `execute(sql)` | SQLを直接実行します。`SELECT`、`WITH`、`DESC`、`DESCRIBE`、`SHOW`は`select()`、それ以外は`exec_direct()`で実行します。 | `1`または`0` | | `machbase` | `schema(sql)` | スキーマ関連コマンドを実行します。 | `1`または`0` | | `machbase` | `tables()` | 全テーブルのメタデータを検索します。 | `1`または`0` | | `machbase` | `columns(table_name)` | 特定テーブルの列メタデータを検索します。 | `1`または`0` | | `machbase` | `column(table_name)` | 低レベルのカタログ呼び出しで列レイアウトを取得します。 | `1`または`0` | | `machbase` | `statistics(table_name, user='SYS')` | CLI経由でテーブル統計を要求します。 | `1`または`0` | | `machbase` | `select(sql)` | ストリーミング`SELECT`または`DESC`を実行します。 | `1`または`0` | | `machbase` | `fetch()` | `select()`の後に次の行を取得します。 | `(rc, json_str)` | | `machbase` | `selectClose()` | 開いた結果セットのカーソルを閉じます。 | `1`または`0` | | `machbase` | `result()` | 最新のJSONペイロードを返します。 | JSON文字列 | | `machbase` | `appendOpen(table_name, types=None)` | 列の型コードを指定してAppendプロトコルを開始します。省略時はサーバーメタデータの型を使用できます。 | `1`または`0` | | `machbase` | `appendOpenColumns(table_name, columns, types=None)` | Machbase DBMS 8.7.0で選択列またはARRAY要素を対象にAppendを開始します。 | `1`または`0` | | `machbase` | `appendData(table_name, rows_or_types, values=None, format='YYYY-MM-DD HH24:MI:SS', on_ack=None)` | 有効なAppendセッションに行を追加します。型リストを省略する場合は第2引数に行を渡します。呼び出し時にデータパケットを直ちに送信します。 | `1`または`0` | | `machbase` | `appendDataByTime(table_name, rows_or_types, values=None, format='YYYY-MM-DD HH24:MI:SS', aTimes=None, on_ack=None)` | 明示的なタイムスタンプで行を追加します。型リストを省略する場合は第2引数に行を渡し、`aTimes`でタイムスタンプを指定します。呼び出し時にデータパケットを直ちに送信します。 | `1`または`0` | | `machbase` | `appendFlush()` | 送信済みAppendデータの未受信サーバー応答を確認する同期点です。送信を遅延したバッファを空にするAPIではありません。 | `1`または`0` | | `machbase` | `appendClose()` | Appendセッションを終了します。 | `1`または`0` | | `machbase` | `append(table_name, rows_or_types, aValues=None, format='YYYY-MM-DD HH24:MI:SS')` | オープン・追加・クローズをまとめて処理する便利関数です。型リストを省略する場合は第2引数に行を渡します。 | `1`または`0` | | `machbase` | `appendByTime(table_name, rows_or_types, aValues=None, format='YYYY-MM-DD HH24:MI:SS', aTimes=None)` | タイムスタンプを指定するAppendの便利関数です。型リストを省略する場合は第2引数に行を渡し、`aTimes`でタイムスタンプを指定します。 | `1`または`0` | ## DB-API形式のAPI(2.4) | API | 説明 | 戻り値 | | -- | -- | -- | | `connect(**kwargs)` | DB-API接続を作成。`host`、`port`、`user`、`password`などはキーワード引数で渡します。 | `MachbaseConnection` | | `cursor(dictionary=True, raw=False, prepared=False)` | 通常またはプリペアドカーソルを作成 | `MachbaseCursor`または`MachbasePreparedCursor` | | `cursor.execute(sql, params=None)` | SQLを実行 | `cursor` | | `cursor.executemany(sql, seq_of_params)` | 同じSQLを複数のマッピングまたはシーケンスで実行 | 実行回数 | | `cursor.fetchone()` | 1件取得 | `tuple | dict | None` | | `cursor.fetchmany(size)` | 最大`size`件取得 | `list` | | `cursor.fetchall()` | 全件取得 | `list` | | `cursor.description` | 結果列メタデータ。7番目の値は`null_ok`です。 | `tuple | None` | | `cursor.lastrowid` | 成功した単一INSERTのROWID。非サポートの入力方式または失敗後は`None`です。 | `int | None` | | `cursor.close()` | カーソルを終了 | `None` | | `cursor.rowcount` | 影響行数 | `int` | | `connection.append(table, rows, *, types=None, times=None, date_format=..., strict=False, columns=None)` | Appendで行を追加。`columns`は選択列またはARRAY要素対象を指定します。 | 入力行数 | ## 2.3 Appendの型省略と末尾NULLパディング(推奨) `append()`と`appendByTime()`は型リストを省略して呼び出せます。第2引数に行の集合をそのまま渡すと、 サーバーメタデータに基づいて処理します。2.3以降は入力行の末尾の一部の列を省略でき、省略した列は AppendのNULLビットにより`NULL`として保存されます。 ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: db.execute('drop table py_append_auto') db.result() ddl = 'create table py_append_auto(ts datetime, tag varchar(16), reading double)' if db.execute(ddl) == 0: raise SystemExit(db.result()) db.result() rows = [ ['2024-01-01 10:00:00', 'node-1', 30.0], ['2024-01-01 10:01:00', 'node-1', 30.5], ] if db.append('PY_APPEND_AUTO', rows) == 0: raise SystemExit(db.result()) print('append without types result:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### DB-API Appendの末尾NULLの例 `connect().append()`も同じ末尾`NULL`パディング規則を使用します。途中の列を飛ばす位置指定入力は サポートしないため、途中の値を`NULL`にする場合は、その位置に`None`を明示します。 ```python from machbaseAPI import connect conn = connect(host='127.0.0.1', port=5656, user='SYS', password='MANAGER') cur = conn.cursor() try: cur.execute('drop table py_append_null') except Exception: pass cur.execute('create table py_append_null(ts datetime, name varchar(20), value double, note varchar(40))') conn.append('PY_APPEND_NULL', [ ['2024-01-01 10:00:00', 'sensor-1', 12.3], ['2024-01-01 10:00:01', 'sensor-2', None, 'manual null'], ]) cur.execute('select ts, name, value, note from py_append_null order by ts') print(cur.fetchall()) conn.close() ``` 1行目は`note`列を省略しているため`NULL`として保存されます。 2行目は`value`位置に`None`を明示しているため、`value`が`NULL`として保存されます。 ### TAGテーブルのAppendとメタデータNULLの例 TAGテーブルは`name`、`time`、`value`に対応する値まで必須です。`value`の後に定義した追加列や メタデータ列は省略でき、省略した列は`NULL`として保存されます。 ```python from machbaseAPI import connect conn = connect(host='127.0.0.1', port=5656, user='SYS', password='MANAGER') cur = conn.cursor() try: cur.execute('drop table py_tag_append_null') except Exception: pass cur.execute(''' create tag table py_tag_append_null ( name varchar(40) primary key, time datetime basetime, value double summarized, status varchar(20) ) metadata ( site varchar(20), line integer ) ''') conn.append('PY_TAG_APPEND_NULL', [ ['tag-1', '2024-01-01 10:00:00', 12.3], ]) cur.execute('select name, time, value, status, site, line from py_tag_append_null') print(cur.fetchall()) conn.close() ``` この例の`status`、`site`、`line`はすべて`NULL`で保存されます。一方、`value`を省略したTAGの Appendはエラーになります。 ## `machbase`クラスの互換API 既存アプリケーションとの互換性のため維持される`machbase`クラスを説明します。 新規コードには前述のDB-API `connect()`方式を推奨します。 `getSessionId()`、`count()`、`checkBit()`などは旧ネイティブパッケージにはありましたが、 現在の純粋なPython実装にはありません。必要に応じて2.4のDB-API例を参照してください。 各スクリプトのホスト・ポート・アカウントを環境に合わせて変更してください。 すべての例は独立実行でき、`python3 script.py`形式で実行できます。 ### 接続管理 #### machbase.open(), machbase.isOpened(), machbase.isConnected(), machbase.close() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() print('isOpened before open:', db.isOpened()) print('isConnected before open:', db.isConnected()) if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) print('isOpened after open:', db.isOpened()) print('isConnected after open:', db.isConnected()) if db.close() == 0: raise SystemExit(db.result()) print('isOpened after close:', db.isOpened()) print('isConnected after close:', db.isConnected()) if __name__ == '__main__': main() ``` #### machbase.openEx() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() conn_str = 'APP_NAME=python-demo' if db.openEx('127.0.0.1', 'SYS', 'MANAGER', 5656, conn_str) == 0: raise SystemExit(db.result()) print('connected with openEx:', db.isConnected()) if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### DMLと結果バッファ #### machbase.execute(), machbase.result() ```python #!/usr/bin/env python3 import json from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: rc = db.execute('drop table py_exec_demo') print('drop table rc:', rc) print('drop table result:', db.result()) ddl = 'create table py_exec_demo(id integer, note varchar(32))' if db.execute(ddl) == 0: raise SystemExit(db.result()) print('create table result:', db.result()) for idx in range(2): sql = f"insert into py_exec_demo values ({idx}, 'row-{idx}')" if db.execute(sql) == 0: raise SystemExit(db.result()) print('insert result:', db.result()) if db.execute('select * from py_exec_demo order by id') == 0: raise SystemExit(db.result()) payload = db.result() print('select payload:', payload) rows = json.loads(payload) print('decoded rows:', rows) print('row count:', len(rows)) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### ストリーミングSELECTヘルパー #### machbase.select(), machbase.fetch(), machbase.selectClose() ```python #!/usr/bin/env python3 import json from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: rc = db.execute('drop table py_select_demo') print('drop table rc:', rc) print('drop table result:', db.result()) ddl = 'create table py_select_demo(id integer, value double)' if db.execute(ddl) == 0: raise SystemExit(db.result()) print('create table result:', db.result()) for idx in range(5): sql = f"insert into py_select_demo values ({idx}, {idx * 1.5})" if db.execute(sql) == 0: raise SystemExit(db.result()) print('insert result:', db.result()) if db.select('select id, value from py_select_demo order by id') == 0: raise SystemExit(db.result()) fetched = 0 while True: rc, payload = db.fetch() if rc == 0: break print('fetched row:', json.loads(payload)) fetched += 1 print('fetched rows:', fetched) db.selectClose() finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### スキーマヘルパー #### machbase.schema() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: rc = db.schema('drop table py_schema_demo') print('schema drop rc:', rc) print('schema drop result:', db.result()) ddl = 'create table py_schema_demo(name varchar(20), created datetime)' if db.schema(ddl) == 0: raise SystemExit(db.result()) print('schema create result:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### メタデータと統計 #### machbase.tables(), machbase.columns(), machbase.column(), machbase.statistics() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: if db.tables() == 0: raise SystemExit(db.result()) print('tables metadata:', db.result()) if db.columns('PY_EXEC_DEMO') == 0: raise SystemExit(db.result()) print('columns metadata:', db.result()) if db.column('PY_EXEC_DEMO') == 0: raise SystemExit(db.result()) print('column metadata:', db.result()) if db.statistics('PY_EXEC_DEMO') == 0: raise SystemExit(db.result()) print('statistics output:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### Appendプロトコルの基本 `appendOpen()`、`appendData()`、`appendFlush()`、`appendClose()`を組み合わせると、行を効率的に ストリーミングできます。2.1以降は型を省略して`appendOpen()`で開始できます。 `appendData()`と`appendDataByTime()`は呼び出し時にデータパケットを直ちに送信します。 `appendFlush()`は、送信済みAppendデータの未受信サーバー応答を確認する同期点です。 ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: rc = db.execute('drop table py_append_demo') print('drop table rc:', rc) print('drop table result:', db.result()) ddl = 'create table py_append_demo(ts datetime, device varchar(32), value double)' if db.execute(ddl) == 0: raise SystemExit(db.result()) print('create table result:', db.result()) if db.appendOpen('PY_APPEND_DEMO') == 0: raise SystemExit(db.result()) rows = [ ['2024-01-01 09:00:00', 'sensor-a', 21.5], ['2024-01-01 09:05:00', 'sensor-b', 22.1], ] if db.appendData('PY_APPEND_DEMO', rows) == 0: raise SystemExit(db.result()) print('appendData result:', db.result()) if db.appendFlush() == 0: raise SystemExit(db.result()) print('appendFlush result:', db.result()) if db.appendClose() == 0: raise SystemExit(db.result()) print('appendClose result:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` ### Appendの便利関数 #### machbase.append() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: db.execute('drop table py_append_auto') db.result() ddl = 'create table py_append_auto(ts datetime, tag varchar(16), reading double)' if db.execute(ddl) == 0: raise SystemExit(db.result()) db.result() values = [ ['2024-01-01 10:00:00', 'node-1', 30.0], ['2024-01-01 10:01:00', 'node-1', 30.5], ] if db.append('PY_APPEND_AUTO', values) == 0: raise SystemExit(db.result()) print('append() result:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` #### machbase.appendDataByTime(), machbase.appendByTime() ```python #!/usr/bin/env python3 from machbaseAPI.machbaseAPI import machbase def main(): db = machbase() if db.open('127.0.0.1', 'SYS', 'MANAGER', 5656) == 0: raise SystemExit(db.result()) try: db.execute('drop table py_append_time') db.result() ddl = 'create table py_append_time(ts datetime, tag varchar(16), reading double)' if db.execute(ddl) == 0: raise SystemExit(db.result()) db.result() rows = [ ['2024-01-01 11:00:00', 'node-2', 40.1], ['2024-01-01 11:01:00', 'node-2', 40.7], ] epoch_times = [ 1704106800 * 1_000_000_000, 1704106860 * 1_000_000_000, ] if db.appendOpen('PY_APPEND_TIME') == 0: raise SystemExit(db.result()) if db.appendDataByTime('PY_APPEND_TIME', rows, aTimes=epoch_times) == 0: raise SystemExit(db.result()) print('appendDataByTime result:', db.result()) db.appendClose() if db.appendByTime('PY_APPEND_TIME', rows, aTimes=epoch_times) == 0: raise SystemExit(db.result()) print('appendByTime result:', db.result()) finally: if db.close() == 0: raise SystemExit(db.result()) if __name__ == '__main__': main() ``` `aTimes`は行と同じ順序のエポックナノ秒のシーケンスです。 秒単位のUnixタイムスタンプをそのまま渡さないでください。 ## ARRAYと選択列Append Machbase DBMS 8.7.0はARRAYをPythonの`list`で返し、prepared入力には`list`または`tuple`を 使用できます。要素NULLはコレクション内の`None`、配列全体のNULLは列自体の`None`です。 列リストなしの`connection.append(table, rows)`に`SparseArray`を渡すこともできます。 ```python from machbaseAPI import SparseArray sparse = SparseArray(4).set(1, 200).set(3, 400) connection.append("ARRAY_APPEND_FULL_EXAMPLE", [[2, sparse]]) ``` このコードは`ID LONG, A INT32[4]`テーブルと開いた接続を前提とします。全体NULL・空のスパース配列・ 結果確認を含む[通常入力の例](../data-input-load-export/array-append/#python-full-open)を参照してください。 legacyラッパーには[`appendOpen(table)`の例](../data-input-load-export/array-append/#python-legacy-full-open)が あります。 選択対象は`connection.append(..., columns=...)`で指定します。行ごとに異なるARRAY位置を入力する 場合は`SparseArray`を使用します。要素位置を指定した対象と`SparseArray.set()`の位置は0始まりです。 ```python from machbaseAPI import SparseArray, connect connection = connect( host="127.0.0.1", port=5656, user="SYS", password="MANAGER", ) try: connection.append( "ARRAY_APPEND_EXAMPLE", [[1, 10, 40]], columns=["ID", "A[0]", "A[3]"], ) sparse = SparseArray(4).set(1, 200).set(3, 400) connection.append( "ARRAY_APPEND_EXAMPLE", [[2, sparse]], columns=["ID", "A"], ) finally: connection.close() ``` `SparseArray.clear()`は要素数を維持して全要素をNULLに戻します。NULLの区別、検証、既存互換APIの 詳細例は[Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 --- title: "11.7 Node.js / TypeScript" url: https://docs.machbase.com/ja/dbms/development-tools-integration/node-js-typescript/ language: ja kind: section --- # 11.7 Node.js / TypeScript ## 概要 Machbase TypeScriptクライアント(`@machbase/ts-client`)は、ネイティブバインディングなしで Machbase Standard Editionサーバーに接続するライブラリです。Node.jsアプリケーションでSQLの実行、 結果の取得、プリペアドステートメントの処理、ログデータのAppendを実行できます。 このドキュメントではインストール、主要API、例、テストフロー、動作特性を扱います。 ## マルチデータベース 接続設定またはURLの`database`値で初期データベースを指定します。カタログgetterは提供しないため、 SQLの`CURRENT_DATABASE()`と`USE`で確認・変更します。 ```typescript const conn = createConnection({ host: '127.0.0.1', port: 5656, user: 'APP_A', password: 'secret', database: 'FACTORY_A', }); await conn.connect(); const [rows] = await conn.query('SELECT CURRENT_DATABASE()'); console.table(rows); ``` Appenderとプリペアドステートメントは、open/prepare時点のデータベースに固定されます。詳細は [マルチデータベース運用ガイド](/ja/dbms/operations-configuration-recovery/multi-database/#95-nodejs)を 参照してください。 ## インストール ### 要件 - Node.js 18以降(LTSを推奨) - 接続可能なMachbaseサーバー(Standard Edition) ### npmからインストール パッケージマネージャーでインストールします。 ```bash npm install @machbase/ts-client # または yarn add @machbase/ts-client # または pnpm add @machbase/ts-client ``` ### オフラインインストール Machbaseから`.tgz`パッケージを受け取った場合: ```bash # ファイル名の例。バージョンは異なる場合があります npm install ./machbase-ts-client-.tgz ``` ### インストールの確認 ```bash node -e "const { createConnection } = require('@machbase/ts-client'); console.log(typeof createConnection === 'function' ? 'ts-client import ok' : 'ts-client import failed')" ``` > **補足**: このクライアントはNode.jsのTCPソケットを使用し、ブラウザー用ライブラリ(WebSocket転送)は提供しません。 > NFX `cce422d2972`ソースツリーの`package.json`は`@machbase/ts-client` 1.0.1です。ただし、 > 名前付きbind・NULL許容性・PK・ROWID・TRANSACTION機能の一部は、公開1.0.1の配布後に同じソースの > バージョン文字列の下で追加されました。npmのバージョンだけで同じ機能を想定せず、配布成果物の > コミット出所を確認するか、このNFXソースからビルドしてください。 > > 本ドキュメントのデフォルトアカウント(`SYS`/`MANAGER`)はローカルテスト用です。 > 本番環境では専用アカウントとパスワードを使用してください。 ## クイックスタート 次の例はローカルサーバーに接続してシステムテーブルを検索し、セッションを終了します。 ```typescript // src/example.ts import { createConnection } from '@machbase/ts-client'; const conn = createConnection({ host: process.env.MACH_HOST ?? '127.0.0.1', port: +(process.env.MACH_PORT ?? 5656), user: process.env.MACH_USER ?? 'SYS', password: process.env.MACH_PASS ?? 'MANAGER', }); await conn.connect(); const [rows] = await conn.query('SELECT NAME FROM V$TABLES ORDER BY NAME LIMIT ?', [5]); console.log(rows); await conn.end(); ``` > **トランザクションについて:** サーバーはTRANSACTIONテーブルに通常の`BEGIN`、`COMMIT`、 > `ROLLBACK` SQLをサポートします。このクライアントの便利メソッド`beginTransaction`、`commit`、 > `rollback`は未実装のため、`execute()`でSQLを直接実行する必要があります。 ## よくある問題 - **ECONNREFUSED** – サーバーの状態(`machadmin -e`)、ホストとポート、ファイアウォールでの リスナーポートの許可を確認します。デフォルトのSQL接続ポートは5656です。 - **Authentication failed** – ユーザー・パスワードとアカウントの接続権限を確認してください。 ## APIリファレンス ### 接続管理 #### createConnection(config) Machbaseリスナーに接続し、データベースセッションを作成します。 | パラメーター | 型 | デフォルト値 | 説明 | |-----------|------|---------|-------------| | `host` | 文字列 | `127.0.0.1` | MachbaseサーバーのIPまたはホスト名 | | `port` | number | `5656` | リスナーポート | | `user` | 文字列 | – | データベースユーザー(デフォルト`SYS`) | | `password` | 文字列 | – | パスワード(デフォルト`MANAGER`) | | `database` | 文字列 | `data` | データベース名 | | `clientId` | 文字列 | `NPM` | サーバーログに表示するクライアントID | | `showHiddenColumns` | boolean | `false` | メタデータに非表示列を含めるか | | `timezone` | 文字列 | 空 | 任意のタイムゾーン識別子 | | `connectTimeout` | number | 5000 | ソケット接続タイムアウト(ms) | | `queryTimeout` | number | 60000 | コマンドごとのタイムアウト(ms) | ```javascript const conn = createConnection({ host: '192.168.1.10', user: 'SYS', password: 'MANAGER' }); await conn.connect(); ``` ソケット接続失敗、認証エラー、ハンドシェイク応答の異常時はPromiseがrejectされます。 #### connect() サーバーとの接続を開きます。 ```javascript await conn.connect(); ``` #### end() ソケット接続を終了します。`end()`の後に追加操作を試みるとエラーになります。 ```javascript await conn.end(); ``` ### SQLの実行 #### execute(sql, values?) 結果セットを返さない場合もあるコマンドを実行します。DDL(`CREATE`、`ALTER`、`DROP`)や DML(`INSERT`、`UPDATE`、`DELETE`)に使用してください。 ```javascript const [create] = await conn.execute('CREATE TRANSACTION TABLE demo (ID INTEGER, NAME VARCHAR(32))'); console.log('Rows affected:', create.affectedRows); // DDLでは0 await conn.execute('BEGIN'); const [insert] = await conn.execute("INSERT INTO demo VALUES (1, 'alpha')"); console.log('Rows affected:', insert.affectedRows); // -> 1 await conn.execute('COMMIT'); ``` Standard Editionで単一の`INSERT ... VALUES`が成功すると、実行結果の`rowId`にROWIDが含まれます。 64ビット精度を保持するため、`number`ではなく`bigint`で処理します。 ```javascript const [result] = await conn.execute( 'INSERT INTO sensor_log(message) VALUES(?)', ['started'] ); if (result.rowId !== undefined) { const rowId = result.rowId; // bigint } ``` ROWIDがない実行では`rowId`は`undefined`です。バッチ、Append、`INSERT ... SELECT`、UPSERTの 違いは[ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 #### query(sql, values?) 行を返すクエリを実行します。戻り値は`[rows, fields]`形式の2要素タプルです。 ```javascript const [rows, fields] = await conn.query('SELECT ID, NAME FROM demo ORDER BY ID'); console.table(rows); ``` #### Named Bind Parameter `execute()`、`query()`、プリペアドステートメントの`execute()`では、配列が位置指定入力、 通常のオブジェクトが名前付き入力です。 ```typescript export type MachbaseNamedBindInput = Record; export type MachbaseExecuteInput = MachbaseBindInput[] | MachbaseNamedBindInput; ``` ```javascript await conn.execute( 'INSERT INTO demo (ID, NAME) VALUES (:id, :name)', { id: 1, name: 'node-client' }, ); const [rows] = await conn.query( 'SELECT ID, NAME FROM demo WHERE ID = :id OR PARENT_ID = :id', { id: 1 }, ); ``` プリペアドステートメントでもオブジェクトを渡します。 ```javascript const stmt = await conn.prepare( 'SELECT ID, NAME FROM demo WHERE ID = :id' ); try { const [rows] = await stmt.execute({ id: 1 }); } finally { await stmt.close(); } ``` オブジェクトのキーは先頭のコロンなしで指定し、大文字・小文字を区別します。同名の繰り返しには同じ値が 適用されます。オブジェクト入力と`?`の併用、必須キーの欠落、SQLにないキーの指定はエラーになります。 | エラーコード | 状況 | |---|---| | `ERR_MACHBASE_BIND_MISSING` | 必須の名前が欠けている | | `ERR_MACHBASE_BIND_EXTRA` | SQLにない名前を指定した | | `ERR_MACHBASE_BIND_MIXED` | 名前付きと匿名プレースホルダーを混用した | | `ERR_MACHBASE_NAMED_BIND_UNSUPPORTED` | サーバーが名前付きバインディングをサポートしない | `fields`の各`ColumnMeta`オブジェクトは`nullable`プロパティを提供します。 ```typescript import { ColumnNullable } from '@machbase/ts-client'; const [rows, fields] = await conn.query( 'SELECT ID, NAME, ID + 1 AS EXPR_VALUE FROM demo ORDER BY ID' ); for (const field of fields) { if (field.nullable === ColumnNullable.NoNulls) { console.log(field.name, 'NO_NULLS'); } else { console.log(field.name, 'NULL処理が必要'); } } ``` | 列挙値 | 数値 | 意味 | |--------|:------:|------| | `ColumnNullable.NoNulls` | `0` | NULLにならない | | `ColumnNullable.Nullable` | `1` | NULLになり得る | | `ColumnNullable.Unknown` | `2` | 判定不能 | `ColumnNullable.Unknown`は`NOT NULL`を意味しません。NULLが発生し得るものとして処理します。 SQL結果の判定規則は [NULL許容性メタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-nullable-metadata)を 参照してください。 Machbase SQLでは`''`はSQLの`NULL`のため、該当`field.nullable`は`ColumnNullable.Nullable`、 結果行の値はJavaScriptの`null`です。一方、`''''`は単一引用符1文字のため、 `ColumnNullable.NoNulls`と文字列値`'`を返します。 ### SELECT結果のPRIMARY KEYメタデータ Machbase 8.7.0サーバーと対応SDKを使用すると、`query()`または`execute()`が返す`fields`配列の `isPrimaryKey`で、直接の列がPRIMARY KEYか確認できます。 ```ts const [rows, fields] = await conn.query( 'SELECT ID, VALUE, ID + 1 AS ID_EXPR FROM T_PK' ); for (const field of fields) { console.log(field.name, field.isPrimaryKey); } ``` 式・集計式・外部結合のNULL補完側の列は`false`です。 旧バージョンのサーバーまたはSDKではPKフラグが提供されない場合があります。 ### プリペアドステートメントの使用 #### prepare(sql) サーバーにプリペアドステートメントを作成します。 ```javascript const stmt = await conn.prepare('SELECT NAME FROM demo WHERE ID = ?'); try { const [rows] = await stmt.execute([1]); console.log(rows); // -> [ { NAME: 'alpha' } ] } finally { await stmt.close(); } ``` 返されたオブジェクトは次のメソッドを提供します。 - `execute(parameters?)` – 文を実行し、`[rowsOrPacket, fields]`を返します。 - `getColumns()` – 列メタデータのキャッシュを返します。 - `getLastMessage()` – 最新のサーバーメッセージを確認します。 - `getStatementId()` – 内部のStatement IDを取得します。 - `close()` – サーバーリソースを解放します。複数回呼び出しても安全です。 `getColumns()`が返す`ColumnMeta`にも同じ`nullable`値が含まれます。 ```typescript const stmt = await conn.prepare('SELECT ID, NAME FROM demo WHERE ID = ?'); for (const column of stmt.getColumns()) { console.log(column.name, ColumnNullable[column.nullable]); } ``` #### プリペアドステートメントの例 **Prepared SELECTの再利用:** ```javascript const select = await conn.prepare('SELECT DEVICE_ID, SENSOR_VALUE FROM sensors WHERE DEVICE_ID = ?'); for (const { id } of samples) { const [rows] = await select.execute([id]); console.log(`selected ${id}:`, rows); } await select.close(); ``` **Prepared Upsert:** ```javascript const upsert = await conn.prepare( 'INSERT INTO devices (DEVICE_ID, SENSOR_VALUE) VALUES (?, ?) ' + 'ON DUPLICATE KEY UPDATE SET SENSOR_VALUE = ?', ); const [result] = await upsert.execute([deviceId, firstValue, firstValue]); console.log('Affected rows:', result.affectedRows); await upsert.close(); ``` **型指定引数とNULL処理:** ```javascript await update.execute([ { value: null, type: 'varchar' }, { value: new Date(), type: 'varchar' }, { value: 'sensor-200', type: 'varchar' }, ]); ``` 実行サンプルのスクリプトは通常、`npm run build`の後に`dist/examples/`配下に生成されます。 サンプルは一般に`MACHBASE_EXAMPLE_*`、`MACHBASE_SMOKE_*`、最後に`SYS/MANAGER@127.0.0.1`の順で 接続情報を探します。 ### Append API #### appendBatch(table, columns, rows, options?) `appendBatch()`で**LOGテーブル**に複数行を追加します。ユーザーに見える列だけを渡せます。 LOGテーブルには`_arrival_time`と`_rid`が自動的に含まれます。 ```javascript const appendResult = await conn.appendBatch( 'sensor_log', [ { name: 'ID', type: 'int32' }, { name: 'NAME', type: 'varchar' }, { name: 'VALUE', type: 'float64' }, ], [ [1, 'alpha', 0.5], { values: [2, 'bravo', 1.25], arrivalTime: BigInt(Date.now()) * 1_000_000n }, ], ); console.log('Appended rows:', appendResult.rowsAppended); ``` サポートする列の型: `int32`、`int64`、`float64`、`varchar`。 - `rows`は値配列、または`{ values, arrivalTime }`オブジェクトの配列を受け取れます。 `null`はMachbaseのセンチネル値に自動エンコードされます。 - `options`は`arrivalTime`(デフォルト値1つ)または`arrivalTimes`(行別の配列)を指定できます。 - エポックナノ秒を直接計算する際は、先に`bigint`へ変換します。`number`の乗算は安全な整数範囲を超えます。 戻り値は`{ table, rowsAppended, rowsFailed, message }`形式です。 > **ヒント**: 列数不一致の「does not match」エラーは、対象がLOGテーブルでない場合や、列順序が > スキーマと一致しない場合に発生します。TAGテーブルには`appendOpen()`を使用してください。 #### appendOpen(table, columns, options?) 軽量なAppendセッションを開きます。デフォルトではネイティブのAPPEND open/data/closeフローを使用し、 成功したネイティブ書き込みはチャンクごとの応答を返しません。 ```javascript const stream = await conn.appendOpen('sensor_log', [ { name: 'ID', type: 'int32' }, { name: 'NAME', type: 'varchar' }, { name: 'VALUE', type: 'float64' }, ]); await stream.append([ [1, 'alpha', 0.5], [2, 'bravo', 1.25], ]); await stream.append({ values: [3, 'charlie', 2.5] }); await stream.close(); ``` ネイティブAppendを無効化し、プリペアドステートメント方式に固定するには`MACHBASE_NATIVE_APPEND=0`を 設定してください。サーバーが特定テーブルタイプやセッションでネイティブAppendをサポートしない場合は、 ファサードが自動的にプリペアドステートメント方式へフォールバックします。 TAGテーブルの`DATETIME`列には`Date`オブジェクトまたは`bigint`のエポック値を渡してください。 スパースARRAYは`appendOpen()`のARRAY値として渡せます。現在の`@machbase/ts-client`は`columns`引数が 必須のため、全行を入力する場合もテーブルの入力列を順番に定義します。`appendOpen(table)`や空の列リストに よる自動推論はサポートしません。以下の例の`ID`、`A`がテーブルの全入力列なら全行入力です。 ARRAY内の入力位置は各行の`SparseArray`が決めます。 接続から4行の入力・Close・検索までの [全列定義の例](../data-input-load-export/array-append/#node-full-columns)を参照してください。 Machbase DBMS 8.7.0の選択列Appendでは、`name`に通常の列または`ARRAY_COLUMN[position]`を指定します。 行ごとに異なる位置を入力する場合は、`SparseArray`を配列全体の対象に渡します。 要素位置を指定した対象と`SparseArray.set()`の位置は0始まりです。 ```javascript const { SparseArray } = require('@machbase/ts-client'); const stream = await conn.appendOpen('array_append_example', [ { name: 'ID', type: 'int64' }, { name: 'A', type: 'int32-array' }, ]); const sparse = new SparseArray(4).set(1, 200).set(3, 400); await stream.append([[2n, sparse]]); await stream.close(); ``` `MACHBASE_NATIVE_APPEND=0`でprepared代替経路に固定した場合も、`SparseArray`をARRAY互換値として 処理します。全体例とNULLの区別は [Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 #### Appendストリームのappend(rows) 開いたAppendストリームに1行以上を送信します。 ```javascript const frames = await stream.append([ ['S-001', new Date(), 1.0], ['S-002', new Date(Date.now() + 1), 2.0], ]); console.log('frames sent:', frames); ``` ネイティブモードではスループットを最大化するため成功応答を省略し、エラー時だけ失敗パケットを返します。 ### ヘルパーメソッド #### ping() `SELECT 1 FROM V$TABLES`で接続状態を確認します。 ```javascript await conn.ping(); ``` #### promise() 使い慣れた`.promise()`形式のラッパーを提供します。 ```javascript const p = conn.promise(); await p.ping(); const [rows] = await p.query('SELECT NAME FROM V$TABLES ORDER BY NAME LIMIT ?', [5]); ``` #### escape, escapeId, format SQL文字列を安全に組み立てるユーティリティです。 ```javascript const safeName = conn.escapeId('table_name'); const safeValue = conn.escape('user input'); ``` ## テストと診断 ### スクリプト - `npm run build` – TypeScriptのコンパイル - `npm run lint` – `src/`にESLintを実行 - `npm run smoke` – 任意のスモークテスト(環境変数がなければ省略) - `npm test` – 統合テストスイート(実サーバーが必要) 1. LOGテーブルを作成 2. サンプルデータのINSERT/SELECT 3. 位置指定バインディングのプリペアドステートメントを実演 4. Append負荷テスト(デフォルト: 5バッチ x 200行)と件数検証 5. TRANSACTIONテーブルで直接SQLの`BEGIN`/`ROLLBACK`/`COMMIT`の動作を確認 6. Machbaseファサードと`UPDATE`制限の動作を検証 サンプル出力: ```text TRANSACTION transaction commit returned 1 row. machbase-facade-basic callback query returned 3 rows. machbase-facade-update-log-fails message: UPDATE is not supported for LOG tables. append-batch progress: batch 4/5 { table: 'TS_CLIENT_IT_...', rowsAppended: 200, rowsFailed: 0 } append-batch final count: 1004 ``` ## チュートリアル ### クイックスタート(LOGテーブル) ```javascript // quickstart-log.js const { createConnection } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', port: 5656, user: 'SYS', password: 'MANAGER' }); await conn.connect(); const table = 'JS_LOG_' + Math.random().toString(36).slice(2, 7).toUpperCase(); try { await conn.execute(`CREATE LOG TABLE "${table}" (ID INTEGER, NAME VARCHAR(64), VALUE DOUBLE)`); await conn.execute(`INSERT INTO "${table}" VALUES (1, 'A', 0.5)`); const [rows] = await conn.query(`SELECT * FROM "${table}" ORDER BY ID`); console.table(rows); } finally { await conn.execute(`DROP TABLE "${table}"`); await conn.end(); } })(); ``` ### プリペアドステートメントの再利用 ```javascript // prepared-reuse.js const { createConnection } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', user: 'SYS', password: 'MANAGER' }); await conn.connect(); const table = 'JS_VOL_' + Math.random().toString(36).slice(2, 7).toUpperCase(); try { await conn.execute(`CREATE VOLATILE TABLE "${table}" (ID INTEGER PRIMARY KEY, NAME VARCHAR(64))`); for (let i = 1; i <= 3; i++) await conn.execute(`INSERT INTO "${table}" VALUES (${i}, 'N${i}')`); const stmt = await conn.prepare(`SELECT NAME FROM "${table}" WHERE ID = ?`); try { for (const id of [1, 2, 3]) { const [rows] = await stmt.execute([id]); console.log(id, rows[0]?.NAME); } } finally { await stmt.close(); } } finally { await conn.execute(`DROP TABLE "${table}"`); await conn.end(); } })(); ``` ### LOGテーブルのバッチAppend ```javascript // append-batch.js const { createConnection } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', user: 'SYS', password: 'MANAGER' }); await conn.connect(); const table = 'JS_LOGAPP_' + Math.random().toString(36).slice(2, 7).toUpperCase(); try { await conn.execute(`CREATE LOG TABLE "${table}" (ID INTEGER, NAME VARCHAR(64), VALUE DOUBLE)`); const result = await conn.appendBatch( table, [ { name: 'ID', type: 'int32' }, { name: 'NAME', type: 'varchar' }, { name: 'VALUE', type: 'float64' }, ], [[1, 'X', 0.5], [2, 'Y', 1.25]], ); console.log(result); } finally { await conn.execute(`DROP TABLE "${table}"`); await conn.end(); } })(); ``` ### TAGテーブルのストリーミングAppend ```javascript // append-tag-stream.js const { createConnection } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', user: 'SYS', password: 'MANAGER' }); await conn.connect(); const table = 'JS_TAG_' + Math.random().toString(36).slice(2, 7).toUpperCase(); try { await conn.execute(`CREATE TAG TABLE "${table}" (name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED)`); const stream = await conn.appendOpen(table, [ { name: 'NAME', type: 'varchar' }, { name: 'TIME', type: 'int64' }, { name: 'VALUE', type: 'float64' }, ]); const now = Date.now(); await stream.append([ ['T-0001', new Date(now), 1.0], ['T-0002', new Date(now + 1), 2.0], ]); await stream.close(); const [rows] = await conn.query(`SELECT COUNT(*) AS CNT FROM "${table}"`); console.log('count', rows[0]?.CNT); } finally { await conn.execute(`DROP TABLE "${table}"`); await conn.end(); } })(); ``` > ネイティブモードはデフォルトで有効です。無効化には`MACHBASE_NATIVE_APPEND=0`を設定してください。 > 成功時のチャンクごとの応答は省略され、エラーだけが失敗応答として通知されます。 ### PromiseラッパーとPing ```javascript // promise-and-ping.js const { createConnection } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', user: 'SYS', password: 'MANAGER' }); await conn.connect(); try { const p = conn.promise(); await p.ping(); // SELECT 1 FROM V$TABLES const [rows] = await p.query('SELECT NAME FROM V$TABLES ORDER BY NAME LIMIT ?', [5]); console.log(rows.map(r => r.NAME)); } finally { await conn.end(); } })(); ``` ## 動作特性と制限 ### トランザクション サーバーのSQLトランザクションはTRANSACTIONテーブルで動作しますが、ファサードのトランザクション用 便利メソッドは未実装です。同じ接続でSQLを直接実行します。 ```javascript await conn.execute('BEGIN'); await conn.execute('UPDATE orders SET status = ? WHERE order_id = ?', ['DONE', 1001]); await conn.execute('COMMIT'); ``` ### 結果バッファリングとページネーション ラッパーの`query`は結果セット全体をバッファリングしてから返します。大きなテーブルでは `ORDER BY … LIMIT`クエリや主キー範囲を使用して、直接ページ分割してください。 ### パラメーターバインディング 配列入力は位置指定プレースホルダー`?`に、オブジェクト入力は`:name`にバインドします。 サポートする型は`int32`、`int64`、`float64`、`varchar`などの汎用スカラー型です。 `null`を渡す場合は型も明示してください。 ```javascript { value: null, type: 'varchar' } ``` 名前の規則と最大パラメーター数は [Named Bind Parameter syntax](../../reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 ### Append API LOGテーブルには`appendBatch`、段階的な入力には`appendOpen`/`append`を使用します。 特定のテーブルタイプ(例: TAGテーブル)でこの入力方式が非サポートの場合は、プリペアドステートメントの 繰り返し方式に自動置換されます。本番ではデータをチャンクに分け、`rowsFailed`を確認します。 ### エラー処理 エラーは標準の`Error`オブジェクト(ラッパー使用時は`QueryError`)で通知されます。診断には `error.message`または`QueryError`の`code`、`sql`フィールドを確認してください。統合テストでは、 存在しないテーブルの検索と非サポートの`UPDATE`を意図的に実行し、エラーメッセージが十分に説明的か 確認します。 ### テーブルタイプ別のSQLの注意事項 - **LOGテーブル**は`UPDATE`をサポートしません。 - **TAGテーブル**のデータUPDATEはStandard Editionのみでサポートします。タグ選択条件とBASETIME条件が 必要で、タグ名・時間軸・メタデータ列はデータUPDATEのSET対象にできません。 SETの右辺で既存行の列を参照できません。 - **VOLATILEテーブル**のUPDATE/DELETEは主キー条件を使用します。**LOOKUPテーブル**は主キー条件と 一般条件式の両方をサポートし、単一行の変更には主キー条件が効率的です。 ## ベストプラクティス 1. **必ず接続を閉じる**: `try...finally`で`conn.end()`が呼ばれることを保証してください。 2. **プリペアドステートメントの再利用**: 一度作成して複数回実行すると性能が向上します。 3. **バッチ入力の活用**: 単一行INSERTではなく、`appendBatch`や`appendOpen`で大量ロードを行ってください。 4. **エラー処理**: DB操作を`try...catch`で囲み、適切にログ記録します。 5. **接続プールの使用**: 本番では接続プールを導入し、同時リクエストを安定して処理してください。 6. **クエリのパラメーター化**: SQLインジェクションを防ぐため、文字列連結ではなくバインディング (`?`プレースホルダー)を使用してください。 --- title: "11.8 .NET Connector" url: https://docs.machbase.com/ja/dbms/development-tools-integration/net-connector/ language: ja kind: section --- # 11.8 .NET Connector ## 目次 {#index} * [概要](#overview) * [インストール](#install) * [NuGet(統合8.0.55)](#nuget-unified-connector) * [接続文字列リファレンス](#connection-string-reference) * [APIリファレンス](#api-reference) * [使用例](#usage-and-examples) * [プロトコル4.0-fullの全API](#full-provider-apis-protocol-40-full) ## 概要 {#overview} Machbaseは通信プロトコル2.1~4.0をサポートする汎用ADO.NETプロバイダー **UniMachNetConnector**を提供します。現在の統合パッケージは`UniMachNetConnector` 8.0.55で、 `net452`、`net5.0`、`net6.0`、`net7.0`、`net8.0`のターゲットをビルドします。 自動ネゴシエーションは接続文字列に`PROTOCOL=auto`または`auto-full`を指定した場合のみ動作します。 ## インストール {#install} インストール済みMachbaseサーバー・クライアントには、`$MACHBASE_HOME/lib/`に汎用.NETプロバイダーも 配布されます。標準のLinuxインストールには、たとえば`UniMachNetConnector-net50-8.0.55.dll`や `machNetConnector-40-net50-3.2.2.dll`などのプロトコル別アセンブリが含まれる場合があります。 ソースプロジェクトは必要な.NET SDKがある場合、追加の対象フレームワーク向けビルドも可能です。 - **UniMachNetConnector**: フレームワークに依存しないエントリーポイントです。ソースビルドのファイル名は `UniMachNetConnector-net{452|50|60|70|80}-.dll`形式で、デプロイ先フレームワークに 合うファイルを選択します。 - **レガシープロトコルコネクター**: `machNetConnector-XX-net{40|50|60|70|80}-.dll`のように プロトコルごとに分かれたアセンブリです。UniMachNetConnectorが必要に応じてロードします。 アプリケーションでは対象フレームワークに合うDLLを参照するか、デプロイ時に実行ファイルと同じ場所に 配置します。 ## マルチデータベース MachConnector 4.0は接続文字列の`DATABASE`または`DB_NAME`で初期データベースを選択できます。 ```text SERVER=127.0.0.1;PORT_NO=5656;UID=APP_A;PWD=secret;DATABASE=FACTORY_A ``` 標準の`Database`プロパティと`ChangeDatabase()`は現在のカタログの切り替えAPIとして保証されないため、 SQLの`USE`と`CURRENT_DATABASE()`を使用します。接続プールへの返却時のカタログ初期化も、自動的に 行われるとは考えません。詳細な制限は [マルチデータベース運用ガイド](/ja/dbms/operations-configuration-recovery/multi-database/#97-net)を参照してください。 ## NuGetでインストール(統合コネクター、8.0.55) {#nuget-unified-connector} 統合コネクターのパッケージIDは`UniMachNetConnector`です。新規プロジェクトでは、DLLのコピーより NuGetパッケージ参照を推奨します。 - サポートするTFM: net452、net5.0、net6.0、net7.0、net8.0 - net5.0以降のビルドは自己完結型です。net452ビルドはソースプロジェクト基準で `System.ValueTuple` 4.5.0を復元します。 ### クイックスタート(コマンドライン) ```bash # プロジェクトフォルダーで実行 dotnet add package UniMachNetConnector --version 8.0.55 dotnet build ``` ソース(フィード)を明示的に制御する場合は、参照だけ追加して別途復元してください。 ```bash dotnet add package UniMachNetConnector --version 8.0.55 --no-restore # nuget.orgのメタデータを強制更新 dotnet nuget locals http-cache --clear dotnet restore --no-cache --source https://api.nuget.org/v3/index.json ``` ### Visual Studio - プロジェクトを右クリック → NuGetパッケージの管理 → 参照 → 「UniMachNetConnector」を検索 → 8.0.55を選択 → インストール。 ### プロジェクトファイルの例 ```xml ``` ### ローカル・社内フィードの使用(任意) 社内レジストリやフォルダーフィードを使用する場合は、次のようにソースを追加して復元します。 フォルダーフィードは該当ディレクトリに`UniMachNetConnector.8.0.55.nupkg`を配置します。 ```bash # 初回のみ設定 dotnet nuget add source /path/to/local-nuget -n mach-local # nuget.orgと併用して復元 dotnet restore --no-cache \ --source /path/to/local-nuget \ --source https://api.nuget.org/v3/index.json ``` 権限制限がある環境では、パッケージキャッシュのパスを絶対パスで指定してください。 ```bash PKG_DIR="$(pwd)/.nuget-packages"; mkdir -p "$PKG_DIR" NUGET_PACKAGES="$PKG_DIR" dotnet restore --no-cache --source /path/to/local-nuget NUGET_PACKAGES="$PKG_DIR" dotnet run --no-restore ``` > ヒント: 公開直後にNU1102(指定バージョンが見つからない)や「incompatible with 'all' frameworks」が > 表示される場合、通常はインデックス・キャッシュの問題です。`dotnet nuget locals http-cache --clear`後に > `--no-cache`で復元すると解決します。パッケージはnet452とnet5.0~net8.0をサポートします。 ### 最小の使用例 ```csharp using System; using Mach.Data.MachClient; var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var cs = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var conn = new MachConnection(cs); conn.Open(); using var cmd = new MachCommand("SELECT COUNT(*) FROM V$TABLES", conn); var count = Convert.ToInt64(cmd.ExecuteScalar()); Console.WriteLine($"Tables: {count}"); ``` ## 接続文字列リファレンス {#connection-string-reference} 接続文字列の各項目はセミコロン(`;`)で区切ります。表の同じ行にあるキーワードは同じ意味です。 | キーワード | 説明 | 例 | デフォルト値 | |----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|--------------------------------------------------|---------| | `DSN`, `SERVER`, `HOST` | ホスト名またはIPアドレス | `SERVER=127.0.0.1` | なし | | `PORT`, `PORT_NO` | リスナーポート | `PORT=5656` | `5656` | | `USERID`, `USERNAME`, `USER`, `UID` | ユーザー名 | `UID=SYS` | `SYS` | | `PASSWORD`, `PWD` | パスワード | `PWD=manager` | なし | | `CONNECT_TIMEOUT`, `ConnectionTimeout`, `connectTimeout` | 接続タイムアウト(ミリ秒) | `CONNECT_TIMEOUT=10000` | `60000` | | `COMMAND_TIMEOUT`, `CommandTimeout`, `commandTimeout` | コマンドごとのタイムアウト(ミリ秒) | `COMMAND_TIMEOUT=50000` | `60000` | | `PROTOCOL`, `ProtocolVersion`, `MachProtocol` | 優先する通信プロトコル(`2.1`、`3.0`、`4.0`、`4.0-full`、`auto`、`auto-full`など)。省略時は`4.0`。 | `PROTOCOL=auto` | `4.0` | 例: ```csharp var connectionString = string.Format( "SERVER={0};PORT_NO={1};UID=SYS;PWD=MANAGER;COMMAND_TIMEOUT=50000;PROTOCOL=4.0-full", host, port); ``` ### プロトコルの自動検出(`PROTOCOL=auto`) サーバーバージョンが混在する環境では、`PROTOCOL=auto`を指定し、UniMachNetConnectorが実行時に適切な レガシープロトコルをネゴシエートするよう設定できます。動作は次のとおりです。 - `PROTOCOL=auto`は4.0 → 3.0 → 2.2 → 2.1の順でハンドシェイクを試み、接続文字列のホスト・ポート・ ユーザー・パスワード・データベース・`CONNECT_TIMEOUT`値をそのまま使用します。 - `PROTOCOL=auto-full`はサーバーのメジャーバージョンが4なら登録済みの`4.0-full`ディスクリプターを 選択します。ディスクリプターがないビルドだけlimited 4.0を選び、full接続失敗後にlimitedへ 自動再試行しません。 - `SERVER=hostA:5700,hostB:6000`のように複数ホストを指定すると順番に試行します。失敗メッセージには 各ホスト・プロトコルの組み合わせが記録され、問題箇所を特定できます。 - 認証情報は既存レガシードライバーと同様に大文字へ変換されます。デフォルトのデータベース(`data`)を 使用しない場合は`DATABASE=`値を明示してください。 - `CONNECT_TIMEOUT`値は各検出の往復に適用されます。例外メッセージに `Protocol probe received an invalid response`がある場合は、ポート・ファイアウォール・TLS設定を再確認します。 サーバーバージョンが既知なら、`PROTOCOL=2.1`、`3.0`、`4.0`、`4.0-full`のように明示して 自動検出を省略することもできます。 ## APIリファレンス {#api-reference} {{< callout type="warning" >}} 以下に記載されていない機能は未実装、または正常に動作しない場合があります。
宣言済みのAPIでも、未実装・非サポート機能は`NotImplementedException`または `NotSupportedException`を返す場合があります。必要なAPIがインストールしたプロバイダーにあるか、 先に確認してください。 {{< /callout >}} ### MachConnection ```cs public sealed class MachConnection : DbConnection ``` Machbaseとの接続を担当するクラスです。`DbConnection`と同様に`IDisposable`を実装するため、 `Dispose()`または`using`で安全に解放できます。 #### コンストラクター ``` MachConnection(string aConnectionString) ``` 接続文字列を受け取り、`MachConnection`インスタンスを作成します。 #### Open ```cs void Open() ``` 接続文字列を使用して実際の接続を確立します。 #### Close ```cs void Close() ``` 開いている接続を終了します。 #### SetConnectAppendFlush ```cs void SetConnectAppendFlush(bool activeFlush) ``` Append中に自動フラッシュするかを設定します。 #### フィールド | 名前 | 説明 | |--|--| | `State` | `System.Data.ConnectionState`の値を表します。 | | `StatusString` | 現在の接続が依存する`MachCommand`の状態文字列です。内部ログ用のため、クエリ状態の判定には使用しないことを推奨します。 | ### MachCommand ```cs public sealed class MachCommand : DbCommand ``` `MachConnection`経由でSQLコマンドやAppendを実行するクラスです。 `DbCommand`と同様に`IDisposable`を実装します。 #### コンストラクター ```cs MachCommand(string aQueryString, MachConnection aConn) ``` 実行するクエリと接続オブジェクトを指定してインスタンスを作成します。 ```cs MachCommand(MachConnection aConn) ``` クエリが不要なAppend専用コマンドを作成します。 #### CreateParameter ```cs MachParameter CreateParameter() ``` 新しい`MachParameter`を作成します。 #### AppendOpen ```cs MachAppendWriter AppendOpen( string aTableName, int aErrorCheckCount = 0, MachAppendOption option = MachAppendOption.None) ``` Appendセッションを開き、`MachAppendWriter`を返します。 * `aTableName`: 対象テーブル名 * `aErrorCheckCount`: 指定レコード数ごとにサーバーへ送信して失敗の有無を確認します。 つまり自動`APPEND-FLUSH`のタイミングを設定します。 * `option`: `None`または`MicroSecTruncated`を指定できます。 #### AppendData ```cs void AppendData(MachAppendWriter writer, List dataList) ``` リスト内の値を順番にAppendバッファへ格納します。各値の型はテーブル列の型と一致する必要があり、 値の数が不足・超過すると例外になります。 > **補足**: `_arrival_time`を`ulong`で直接指定する場合は、Machbaseが要求する1970-01-01 UTC基準の > ナノ秒値を入力する必要があります。 ```cs void AppendDataWithTime( MachAppendWriter writer, List dataList, DateTime arrivalTime) ``` `_arrival_time`を`DateTime`で明示します。 ```cs void AppendDataWithTime( MachAppendWriter writer, List dataList, ulong arrivalTime) ``` `_arrival_time`をナノ秒単位の`ulong`で指定します。 #### AppendFlush ```cs void AppendFlush(MachAppendWriter writer) ``` バッファ内のデータをサーバーに送信します。呼び出し間隔を短くするとクライアントバッファに残るデータと 送信遅延を減らせますが、通信コストは増える場合があります。呼び出し成功だけでディスクの耐久性を判断せず、 サーバー処理結果と対象テーブルの耐久性ポリシーも確認します。 #### AppendClose ```cs void AppendClose(MachAppendWriter writer) ``` Appendセッションを終了します。内部では`AppendFlush()`の後にプロトコルを終了します。 #### ExecuteNonQuery ```cs int ExecuteNonQuery() ``` クエリを実行し、影響を受けたレコード数を返します。主に`INSERT`、`UPDATE`、`DELETE`、DDLで使用します。 #### RowId ```cs UInt64? RowId ``` Standard Editionで単一の`INSERT ... VALUES`が成功すると、MachConnector 4.0/4.0-fullと Universal .NETの`ExecuteNonQuery()`の後に入力行のROWIDを確認できます。 ```cs using (var command = new MachCommand( "INSERT INTO orders(item) VALUES('pump')", connection)) { command.ExecuteNonQuery(); ulong? rowId = command.RowId; } ``` 返すROWIDがない場合は`null`です。ROWIDは64ビットの`RowId`で読み取り、従来の32ビットの `LastInsertedId`は使用しません。バッチやAppendなどの違いは [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 #### ExecuteScalar ```cs object ExecuteScalar() ``` クエリを実行し、最初の列の値を返します。 #### ExecuteDbDataReader ```cs DbDataReader ExecuteDbDataReader(CommandBehavior behavior) ``` クエリを実行し、結果を順次読み取れる`DbDataReader`を返します。 #### フィールド | 名前 | 説明 | |--|--| | `Connection` / `DbConnection` | 現在接続している`MachConnection`です。 | | `ParameterCollection` / `DbParameterCollection` | バインドするパラメーターのコレクションです。 | | `CommandText` | 実行するSQL文字列です。 | | `CommandTimeout` | サーバー応答を待つ最大時間(ミリ秒)です。値は`MachConnection`設定に従い、ここでは読み取り専用です。 | | `FetchSize` | サーバーから一度に取得するレコード数です。デフォルトは3000です。 | | `IsAppendOpened` | Appendセッションが開いているかを表します。 | | `RowId` | 成功した単一INSERTの64ビットROWIDです。値がない場合は`null`です。 | ### MachDataReader ```cs public sealed class MachDataReader : DbDataReader ``` フェッチした結果を順次読み取るリーダーです。`MachCommand.ExecuteDbDataReader()`で取得した オブジェクトのみ使用できます。 #### GetName ```cs string GetName(int ordinal) ``` 指定インデックスの列名を返します。 #### GetDataTypeName ```cs string GetDataTypeName(int ordinal) ``` Machbaseの列の型名を返します。 #### GetFieldType ```cs Type GetFieldType(int ordinal) ``` .NET側のマッピング型を返します。 #### GetOrdinal ```cs int GetOrdinal(string name) ``` 列名に対応するインデックスを返します。 #### GetValue ```cs object GetValue(int ordinal) ``` 現在のレコードの値を`object`で返します。 #### IsDBNull ```cs bool IsDBNull(int ordinal) ``` 該当列の値が`NULL`か確認します。 #### GetValues ```cs int GetValues(object[] values) ``` 現在のレコードの値を配列に格納し、格納した項目数を返します。 #### GetSchemaTable ```cs DataTable GetSchemaTable() ``` SELECT結果列のスキーマメタデータを返します。`AllowDBNull`でNULL許容性を確認します。 MachConnector40とMachConnector40-full-APIに同じ動作が適用されます。 ```csharp using var reader = command.ExecuteReader(); DataTable schema = reader.GetSchemaTable(); foreach (DataRow row in schema.Rows) { string columnName = Convert.ToString(row["ColumnName"]); object allowDBNull = row["AllowDBNull"]; if (allowDBNull is bool value && !value) { Console.WriteLine($"{columnName}: NO_NULLS"); } else { // trueまたはDBNull.Value: NULL処理が必要 Console.WriteLine($"{columnName}: NULL処理が必要"); } } ``` | `AllowDBNull` | 意味 | |---------------|------| | `false` | NULLにならない | | `true` | NULLになり得る | | `DBNull.Value` | 判定不能 | `DBNull.Value`は`NOT NULL`を意味しません。NULLが発生し得るものとして処理します。 SQL結果の判定規則は [NULL許容性メタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-nullable-metadata)を 参照してください。 Machbase SQLでは`''`はSQLの`NULL`のため、`GetSchemaTable()`の`AllowDBNull`は`true`で、 該当行の`IsDBNull()`も`true`です。`''''`は単一引用符1文字であり、`AllowDBNull=false`の NULLではない文字列結果です。 `GetSchemaTable()`は`ColumnName`、`ColumnOrdinal`、`ColumnSize`、`NumericPrecision`、 `NumericScale`、`DataType`、`ProviderType`、`IsLong`、`AllowDBNull`、`IsKey`を提供します。 `IsKey`が`true`ならSELECT結果の直接の列がPRIMARY KEYです。式や集計式は`false`です。 旧バージョンのサーバーまたはSDKでは`IsKey`が`false`として返る場合があります。 NULL許容性メタデータはDECIMALの精度`1~65`、スケール`0~30`や実際の値を変更しません。 .NETでは精度29以下かつスケール28以下のDECIMALを`System.Decimal`で返します。この範囲を超えるDECIMALは、 精度損失を防ぐため`System.String`で返します。このとき`GetSchemaTable().DataType`、`GetFieldType()`、 実際の行の値のCLR型もすべて`System.String`です。 #### Get*XXXX* ```cs bool GetBoolean(int ordinal) byte GetByte(int ordinal) char GetChar(int ordinal) short GetInt16(int ordinal) int GetInt32(int ordinal) long GetInt64(int ordinal) DateTime GetDateTime(int ordinal) string GetString(int ordinal) decimal GetDecimal(int ordinal) double GetDouble(int ordinal) float GetFloat(int ordinal) ``` 列の値を指定した型で返します。 #### Read ```cs bool Read() ``` 次のレコードを読み取ります。結果がなくなると`false`を返します。 #### フィールド | 名前 | 説明 | |--|--| | `FetchSize` | サーバーから一度に取得するレコード数です。デフォルトは3000で、ここでは変更できません。 | | `FieldCount` | 結果列数です。 | | `this[int ordinal]` | `GetValue(int ordinal)`と同じです。 | | `this[string name]` | `GetValue(GetOrdinal(name))`と同じです。 | | `HasRows` | 結果が存在するかを表します。 | | `RecordsAffected` | フェッチしたレコード数を表します。 | ### MachParameterCollection ```cs public sealed class MachParameterCollection : DbParameterCollection, IEnumerable ``` `MachCommand`にバインドするパラメーター集合を管理するクラスです。 パラメーターを設定して実行すると、その値も送信されます。 > `MachParameter`のバインディングは、プリペアドステートメントとしての実行計画キャッシュを提供しません。 > 繰り返し実行の性能は、実際のクエリとサーバーキャッシュの状態で測定します。 > > 現在のプロバイダーはパラメーターを型別のSQLリテラルに変換してからExecDirectで実行します。 > そのため`MachParameterCollection`は、サーバーのPrepared Named Bindプロトコルや > パラメーターメタデータを使用しません。 #### Add ```cs MachParameter Add(string parameterName, DbType dbType) ``` パラメーター名と型を指定して`MachParameter`を追加し、作成したオブジェクトを返します。 ```cs int Add(object value) ``` 値を追加し、追加先のインデックスを返します。 ```cs void AddRange(Array values) ``` 単純な値の配列をまとめて追加します。 ```cs MachParameter AddWithValue(string parameterName, object value) ``` パラメーター名と値を同時に追加し、作成した`MachParameter`を返します。 #### Contains ```cs bool Contains(object value) ``` その値が追加済みか確認します。 ```cs bool Contains(string parameterName) ``` 指定パラメーター名が存在するか確認します。 #### Clear ```cs void Clear() ``` 全パラメーターを削除します。 #### IndexOf ```cs int IndexOf(object value) ``` その値のインデックスを返します。 ```cs int IndexOf(string parameterName) ``` パラメーター名があるインデックスを返します。 #### Insert ```cs void Insert(int index, object value) ``` 指定位置に値を挿入します。 #### Remove ```cs void Remove(object value) ``` その値を含むパラメーターを削除します。 ```cs void RemoveAt(int index) ``` 指定インデックスのパラメーターを削除します。 ```cs void RemoveAt(string parameterName) ``` 指定名のパラメーターを削除します。 #### フィールド | 名前 | 説明 | |--|--| | `Count` | パラメーター数です。 | | `this[int index]` | 指定インデックスの`MachParameter`です。 | | `this[string name]` | 名前に一致する`MachParameter`です。 | ### MachParameter ```cs public sealed class MachParameter : DbParameter ``` 個々のパラメーターのバインディング情報を保存するクラスです。 #### フィールド | 名前 | 説明 | |--|--| | `ParameterName` | パラメーター名です。 | | `Value` | 送信する値です。 | | `Size` | 値の長さです。 | | `Direction` | `ParameterDirection`値です。デフォルトは`Input`です。 | | `DbType` | .NET側のDB型です。 | | `MachDbType` | Machbase固有の型です。 | | `IsNullable` | `NULL`許容性です。 | | `HasSetDbType` | `DbType`が設定済みかを表します。 | ### MachException ```cs public class MachException : DbException ``` Machbaseで発生したエラーを表す例外クラスです。 #### フィールド | 名前 | 説明 | |--|--| | `MachErrorCode` | 利用可能な場合のMachbaseエラーコードです。Universalプロバイダーが既存互換の例外を変換した場合は`0`になることがあります。 | ### MachAppendWriter ```cs public sealed class MachAppendWriter ``` Appendプロトコル用の補助クラスです。`MachCommand.AppendOpen()`でインスタンスを取得します。 #### SetErrorDelegator ```cs void SetErrorDelegator(ErrorDelegateFuncType callback) void ErrorDelegateFuncType(MachAppendException e); ``` Append中のエラー時に呼び出すデリゲートを登録します。 #### フィールド | 名前 | 説明 | |--|--| | `SuccessCount` | 保存に成功したレコード数です。`AppendClose()`後に確認できます。 | | `FailureCount` | 失敗したレコード数です。`AppendClose()`後に設定されます。 | | `Option` | `AppendOpen()`で使用した`MachAppendOption`値です。 | ### MachAppendException ```cs public sealed class MachAppendException : MachException ``` Append中のエラー情報を追加提供する例外です。サーバーのエラーメッセージをそのまま伝え、 失敗したレコードを文字列で確認できます。 #### GetRowBuffer ```cs string GetRowBuffer() ``` エラーが発生した元のレコードを文字列で返します。 ## 使用例 {#usage-and-examples} ### 接続 次の例は環境変数のパスワードで接続し、LOGテーブルを作成・入力・検索してから削除します。 ```csharp using System; using Mach.Data.MachClient; var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var connString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var connection = new MachConnection(connString); connection.Open(); const string tableName = "NET_QUERY_DEMO"; using (var create = new MachCommand( $"CREATE LOG TABLE {tableName} (id INTEGER, name VARCHAR(40))", connection)) { create.ExecuteNonQuery(); } try { using (var insert = new MachCommand( $"INSERT INTO {tableName} VALUES (1, 'pump')", connection)) { insert.ExecuteNonQuery(); } using var query = new MachCommand($"SELECT id, name FROM {tableName}", connection); using var reader = query.ExecuteReader(); while (reader.Read()) { for (var column = 0; column < reader.FieldCount; column++) { Console.WriteLine($"{reader.GetName(column)} : {reader.GetValue(column)}"); } } } finally { using var drop = new MachCommand($"DROP TABLE {tableName}", connection); drop.ExecuteNonQuery(); } ``` ### パラメーターバインディング `MachParameterCollection`は`:name`、`@name`、`?name`プレースホルダーを処理します。 共通SQL構文と同じ`:name`形式を推奨します。名前検索は大文字・小文字を区別せず、同じ名前が繰り返されると 1つの値が全位置に適用されます。 `:name`形式はMachbase 8.7.0サーバーへの接続で使用します。旧サーバーでは`MachException`を返します。 `@name`と`?name`は既存プロバイダーの互換形式です。 ```csharp var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var connString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var connection = new MachConnection(connString); connection.Open(); const string sql = @" SELECT NAME FROM V$TABLES WHERE NAME = :table_name OR NAME = :table_name"; using var command = new MachCommand(sql, connection); command.Parameters.AddWithValue(":table_name", "V$TABLES"); using var reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine($"{reader.GetName(0)} : {reader.GetValue(0)}"); } ``` NULLは`DBNull.Value`で渡します。共通の名前構文は [Named Bind Parameter syntax](../../reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 ### Append Appendプロトコルを使用すると、大量の時系列データを高速にロードできます。 ```csharp using System; using System.Collections.Generic; using Mach.Data.MachClient; var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var connString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var connection = new MachConnection(connString); connection.Open(); const string tableName = "NET_APPEND_DEMO"; using (var create = new MachCommand( $"CREATE LOG TABLE {tableName} (ID INTEGER, NAME VARCHAR(40))", connection)) { create.ExecuteNonQuery(); } try { using var appendCommand = new MachCommand(connection); var writer = appendCommand.AppendOpen(tableName); writer.SetErrorDelegator(error => Console.Error.WriteLine($"Append row error: {error.Message}\n{error.GetRowBuffer()}")); try { for (var i = 1; i <= 100000; i++) { appendCommand.AppendData(writer, new List { i, $"NAME_{i % 100}" }); if (i % 1000 == 0) appendCommand.AppendFlush(writer); } } finally { if (appendCommand.IsAppendOpened) appendCommand.AppendClose(writer); } Console.WriteLine($"Success Count : {writer.SuccessCount}"); Console.WriteLine($"Failure Count : {writer.FailureCount}"); if (writer.FailureCount != 0) throw new InvalidOperationException($"Append failed rows: {writer.FailureCount}"); } finally { if (connection.State == System.Data.ConnectionState.Open) { try { using var drop = new MachCommand($"DROP TABLE {tableName}", connection); drop.ExecuteNonQuery(); } catch (Exception cleanupError) { Console.Error.WriteLine($"cleanup failed: {cleanupError.Message}"); } } } ``` ### ARRAYと選択列Append Machbase DBMS 8.7.0のfull/legacyプロバイダーはARRAYを`object[]`で返します。 要素NULLは配列内の`null`、配列全体のNULLは`IsDBNull()`で区別します。 通常の`AppendOpen(table)`でも、`MachSparseArray`をARRAY列の値として入力できます。 ```csharp var writer = append.AppendOpen("ARRAY_APPEND_FULL_EXAMPLE"); ``` この場合、入力行はテーブルの列順序に従います。`ID LONG, A INT32[4]`テーブルにスパース値、 空のスパース配列、全体NULLを入力する [通常Openの例](../data-input-load-export/array-append/#dotnet-full-open)では、 `AppendData()`からClose・結果確認まで説明しています。 `AppendOpen()`の`IList`オーバーロードには、通常の列または`ARRAY_COLUMN[position]`を 渡せます。行ごとに異なる位置を入力する場合は、`MachSparseArray`を配列全体の対象に渡します。 要素位置を指定した対象と`MachSparseArray.Set()`の位置は0始まりです。 ```csharp using var append = new MachCommand(connection); var writer = append.AppendOpen( "ARRAY_APPEND_EXAMPLE", new List { "ID", "A" }); var sparse = new MachSparseArray(MachDBType.INT32_ARRAY, 4) .Set(1, 200) .Set(3, 400); try { append.AppendData(writer, new List { 2L, sparse }); } finally { if (append.IsAppendOpened) append.AppendClose(writer); } ``` 空の`MachSparseArray`は全要素がNULLのARRAYで、`DBNull.Value`は配列全体のNULLです。 オーバーロードと全検証例は [Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 ### Error Delegatorの設定 Append中の行エラーは、上の例のようにwriterを開いた直後にデリゲートで受け取り、close後に 成功・失敗件数を確認します。 ### 自動AppendFlushの設定 AppendOpenは自動フラッシュスレッドを開始します。無効化するには、開いたwriterに対して `connection.SetConnectAppendFlush(false)`を呼び出します。自動スレッドのエラーが直ちに公開例外として 通知されない場合があるため、明示的なflush・closeとコールバック・件数の確認を続けます。 ## プロトコル4.0-fullの全API {#full-provider-apis-protocol-40-full} `PROTOCOL=4.0-full`では拡張されたADO.NET APIを使用できます。8.0.55ソースパッケージの 4.0 limited connectorは3.1.3、4.0-full connectorは3.2.2です。インストール済みLinuxパッケージには `$MACHBASE_HOME/lib/`にnet50版のみ含まれる場合があるため、別の対象フレームワークが必要なら ソースビルドまたはNuGetの復元成果物を使用してください。 - `UniMachNetConnector-net50-8.0.55.dll` – DBMS Standard Linuxパッケージで一般的にインストールされる汎用エントリーポイント - `machNetConnector-40-net50-3.1.3.dll` – プロトコル4.0 limited connector - `machNetConnector-40-net50-3.2.2.dll` – プロトコル4.0-full connector ### 4.0-fullで追加された主な型 - `MachDbProviderFactory`: 不変名`Mach.Data`でプロバイダーを登録・作成できます。 - `MachConnectionStringBuilder`: キーワードの入力誤りを避けて接続文字列を構成できます。 - `MachDataAdapter`、`MachRowUpdating`、`MachRowUpdated`: `DataTable`/`DataSet`のワークフローをサポートします。 - `MachCommandBuilder`: SELECT文からINSERT/DELETE(条件によりUPDATE)文を自動生成します。 自動生成SQLが対象テーブルのDML制約に適合するか、実行前に確認します。 ### 全APIの有効化 ```csharp var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var connString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var connection = new MachConnection(connString); connection.Open(); ``` UPDATE/DELETEが必要な場合は、テーブルタイプ別の条件とドライバーのSQL生成範囲を合わせて確認します。 LOGはUPDATEをサポートしません。Machbase DBMS 8.7.0 Standard EditionのTAG UPDATEにはNAMEと BASETIME条件が必要なため、汎用CommandBuilderのSQLに依存せず、 [TAG UPDATE構文](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/)に合うコマンドと バインディングを使用します。 ### 接続文字列ビルダーの使用 ```csharp var builder = new MachConnectionStringBuilder { Server = "127.0.0.1", Port = 5656, UserID = "SYS", Password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required") }; builder["PROTOCOL"] = "4.0-full"; using var connection = new MachConnection(builder.ConnectionString); connection.Open(); ``` ### 例: MachDataAdapterでSQL INSERT LOOKUPテーブルを`DataTable`へ取り込んで新しい行を追加すると、CommandBuilderが通常のSQL INSERTを 実行します。この経路はAppendプロトコルではありません。 ```csharp using Mach.Data.MachClient; using System; using System.Data; var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); var connString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; using var connection = new MachConnection(connString); connection.Open(); using (var create = new MachCommand( "CREATE LOOKUP TABLE dotnet_lookup_demo (id INTEGER PRIMARY KEY, name VARCHAR(80))", connection)) { create.ExecuteNonQuery(); } var adapter = new MachDataAdapter( "SELECT id, name FROM dotnet_lookup_demo ORDER BY id", connection); var builder = new MachCommandBuilder(adapter); var table = new DataTable(); adapter.Fill(table); var newRow = table.NewRow(); newRow["id"] = 2001; newRow["name"] = "Inserted from MachDataAdapter"; table.Rows.Add(newRow); adapter.MachRowUpdating += (sender, args) => { Console.WriteLine( $"About to run {args.StatementType} with SQL: {args.Command?.CommandText}"); }; adapter.Update(table); using var drop = new MachCommand("DROP TABLE dotnet_lookup_demo", connection); drop.ExecuteNonQuery(); ``` > **ヒント**: 送信前にSQLを確認するには、上記のように`Update()`前にイベントを購読してください。 ### 例: DbProviderFactoryの活用 `MachDbProviderFactory.Instance`を使用すると、`DbProviderFactories`、Dapperなどプロバイダーに 依存しない構成にMachbaseを接続できます。 ```csharp using System; using System.Data.Common; using Mach.Data.MachClient; DbProviderFactory factory = MachDbProviderFactory.Instance; using DbConnection connection = factory.CreateConnection()!; var password = Environment.GetEnvironmentVariable("MACHBASE_PASSWORD") ?? throw new InvalidOperationException("MACHBASE_PASSWORD is required"); connection.ConnectionString = $"SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD={password};PROTOCOL=4.0-full"; connection.Open(); using DbCommand command = connection.CreateCommand(); command.CommandText = "SELECT COUNT(*) FROM V$TABLES"; var count = (long)command.ExecuteScalar(); Console.WriteLine($"Visible tables: {count}"); ``` 設定ベースのアプリケーションでファクトリーを自動公開するには、起動時に `MachDbProviderFactory.Register()`を1回呼び、`DbProviderFactories.GetFactory("Mach.Data")`が 同じインスタンスを返すように構成してください。 `4.0-full`プロトコルはMachbase 7.x以降のサーバーでのみ使用できます。それより前のバージョンでは `PROTOCOL=4.0`(制限された機能)または2.x/3.xプロトコルを使用する必要があります。 --- title: "11.9 Go" url: https://docs.machbase.com/ja/dbms/development-tools-integration/go/ language: ja kind: section --- # 11.9 Go ## neo-clientの概要 `neo-client`はMachbase Neo用のGoクライアントモジュールです。v2から標準の`database/sql` ドライバーを中心に再構成され、旧バージョン(v1)のネイティブ`machgo`パッケージは提供されなくなりました。 v1のコードはv2と互換性がないため、`machgo.Config`や`mdb.Connect()`を使用する既存コードは、 以下を参照して`database/sql`ベースに移行してください。 `neo-client`は次のパッケージを提供します。 - `client`(モジュールルート、インポートパス`github.com/machbase/neo-client/v2`): 標準`database/sql`ドライバー、`Appender`、構造体スキャン・名前付きパラメーターヘルパー - `api`: Machbase専用のデータ型とオプション定義 - `machnet`: `client`が内部で使用する低レベルのプロトコル・転送実装。アプリケーションコードで 直接インポートする必要はほとんどありません。 ### 前提条件 - **Machbaseサーバー**: ネイティブポート(デフォルト`5656`)にアクセス可能な稼働中のDBMSまたはNeoサーバー - **Go 1.22以降** - **アカウント情報**: 有効なMachbaseユーザーアカウント(ローカル開発環境では`sys` / `manager`など) ## はじめに ### インストール ```sh go get github.com/machbase/neo-client/v2 ``` ### インポート ドライバーパッケージはブランク識別子でインポートします。ドライバー名`machbase`で自動登録されるため、 別途`sql.Register()`を呼び出す必要はありません。 ```go import ( "context" "database/sql" "fmt" _ "github.com/machbase/neo-client/v2" ) ``` ## 接続 ### DSN形式 `neo-client`は次のDSN形式をサポートします。 - サーバー値のみ: `host`または`host:port` - URL形式: `tcp://user:password@host:port/database?as=proxy&fetch_rows=100` - セミコロンで区切った`key=value`リスト: `key=value;key=value;...` (例: `user=sys;password=manager;server=127.0.0.1:5656`) `key=value`形式は次の規則に従います。 - 値は`"..."`または`'...'`で引用できます。 - 引用された値内の`;`はリテラル文字として扱います。 - 引用された値内ではバックスラッシュエスケープを使用できます。二重引用符の値では`\"`、 単一引用符の値では`\'`、および`\\`を使用できます。 - 引用符が閉じていない、または対応しない場合は解析エラーになります。 例: ```text user="sys as demo";password="12;34";server=127.0.0.1:5656; password="a\"b";server=127.0.0.1:5656; ``` サポートするDSNキーは次のとおりです。 | キー | 説明 | |----|------| | `server` | `tcp://user:password@127.0.0.1:5656`形式のサーバーURL | | `host`, `port` | サーバーホストとポートを個別指定(デフォルトポート: `5656`) | | `user`, `uid` | ログインユーザー | | `password`, `pwd` | ログインパスワード | | `database`, `db` | 初期データベース | | `auth_mode` | 認証方式: `password`または`challenge` | | `auth_key_file`, `auth_key_pem` | `auth_mode=challenge`の秘密鍵ファイルパスまたはインラインPEM | | `auth_sig_scheme` | チャレンジ認証の署名方式 | | `fetch_rows`, `fetchrows` | 1回のフェッチで取得する最大行数(デフォルト`1000`) | | `statement_cache`, `statementcache` | 文キャッシュモード: `auto`、`on`、`off`(デフォルト`auto`) | | `io_metrics`, `iometrics` | I/Oメトリクスの有効化: `true`、`false` | | `alternative_servers` | `127.0.0.2:5656,backup.example.com:5657`のようなカンマ区切りの代替サーバー一覧 | `auth_key_file`または`auth_key_pem`を指定し、`auth_mode`を省略するとチャレンジ認証になります。 URLクエリパラメーターも同じオプション名を使用します。 ```text tcp://sys:manager@127.0.0.1:5656/DATABASE_A?statement_cache=on&io_metrics=true ``` 不明なキーは`key=value`のDSNではエラーですが、URLクエリ文字列では無視されます。 URLパスは初期データベースも指定します(`tcp://sys:manager@127.0.0.1:5656/DATABASE_A`)。 物理接続ごとに指定データベースが選択され、アプリケーションが直接`USE`を実行した場合は、 その接続がプールで再利用される前に指定データベースへ復元されます。 ## 検索例 次の例は標準の`database/sql`パッケージでシステムテーブル`M$SYS_TABLES`を検索します。 ```go package main import ( "context" "database/sql" "fmt" _ "github.com/machbase/neo-client/v2" ) func main() { db, err := sql.Open("machbase", "server=tcp://sys:manager@127.0.0.1:5656") if err != nil { panic(err) } defer db.Close() ctx := context.Background() rows, err := db.QueryContext(ctx, `SELECT NAME, ID, TYPE FROM M$SYS_TABLES ORDER BY NAME`) if err != nil { panic(err) } defer rows.Close() for rows.Next() { var ( name string id int64 typ int ) if err := rows.Scan(&name, &id, &typ); err != nil { panic(err) } fmt.Println(name, id, typ) } if err := rows.Err(); err != nil { panic(err) } } ``` ## テーブルの作成と入力 次の例は`database/sql`でTagテーブルを作成し、`ExecContext`で行を入力します。 ```sql CREATE TAG TABLE IF NOT EXISTS example ( name VARCHAR(100) PRIMARY KEY, time DATETIME BASE TIME, value DOUBLE ); ``` ```go package main import ( "context" "database/sql" "fmt" "time" _ "github.com/machbase/neo-client/v2" ) func main() { dsn := "server=tcp://sys:manager@127.0.0.1:5656" db, err := sql.Open("machbase", dsn) if err != nil { panic(err) } defer db.Close() ctx := context.Background() _, err = db.ExecContext(ctx, `CREATE TAG TABLE IF NOT EXISTS EXAMPLE ( NAME VARCHAR(100) PRIMARY KEY, TIME DATETIME BASE TIME, VALUE DOUBLE )`) if err != nil { panic(err) } ts := time.Now() for i := 0; i < 10; i++ { rec := []any{ "example-client", ts.Add(time.Duration(i) * time.Second), 3.14 * float64(i), } result, err := db.ExecContext(ctx, `INSERT INTO EXAMPLE VALUES (?, ?, ?)`, rec...) if err != nil { panic(err) } affected, err := result.RowsAffected() if err != nil { panic(err) } fmt.Println("Rows affected:", affected) } } ``` ROWID対応のStandard Editionで単一の`INSERT ... VALUES`が成功すると、`Result.LastInsertId()`で 入力行のROWIDを確認できます。戻り値の型は`int64`のため、ROWIDの64ビット値を保持するには`uint64`に 変換します。バッチ、Appender、`INSERT ... SELECT`、UPSERTはROWIDを返しません。詳細な条件は [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## トランザクション Machbaseは`CREATE TABLE`で作成した通常のテーブル(TRANSACTIONテーブル)で `BEGIN`/`COMMIT`/`ROLLBACK`をサポートします。TAG/LOGテーブルはトランザクションをサポートせず、 トランザクション内でTAG/LOGテーブルにDMLを実行すると`MACHCLI-ERR-2362`になります。 標準の`database/sql`トランザクションAPIをそのまま使用できます。 ```go tx, err := db.BeginTx(ctx, nil) if err != nil { panic(err) } if _, err := tx.ExecContext(ctx, `INSERT INTO EXAMPLE_TX VALUES (?, ?, ?)`, name, ts, value); err != nil { tx.Rollback() panic(err) } if err := tx.Commit(); err != nil { panic(err) } ``` 繰り返す準備コードを減らすには`client.Tx`/`client.TxConn`のクロージャーヘルパーを使用します。 関数が`nil`を返すとコミットし、エラーを返すとロールバックしてそのエラーをそのまま返します。 panicが発生するとロールバック後に再度panicします。 ```go import client "github.com/machbase/neo-client/v2" err := client.Tx(ctx, db, func(tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, `INSERT INTO EXAMPLE_TX VALUES (?, ?, ?)`, name, ts, value); err != nil { return err // 自動ROLLBACK } return nil // 自動COMMIT }) // TxConnはdb.Conn(ctx)で取得した特定の接続でトランザクションを実行します。 conn, _ := db.Conn(ctx) defer conn.Close() err = client.TxConn(ctx, conn, func(tx *sql.Tx) error { // ... return nil }) ``` クロージャーのエラーはそのまま返されるため、`errors.Is`/`errors.As`を引き続き使用できます。 強制ロールバックにはセンチネルエラーを返す方法が一般的です。Machbaseはトランザクションオプション (分離レベル、読み取り専用)をサポートしないため、ドライバーが拒否します。 ## 高性能な大量入力(`Appender`) 大量の時系列入力には、行単位の`INSERT`の代わりに`client.Appender`を使用します。 Appenderはクライアントでレコードをバッファリングし、専用チャネルでサーバーにストリーミングするため、 個別のINSERT文より大幅に高速です。 ```go import client "github.com/machbase/neo-client/v2" appender := &client.Appender{} // 一部の列のみ指定: 以下のAppend()はこの3値だけを送信し、残りの列はNULLになります。 if err := appender.Connect(ctx, dsn, "EXAMPLE", "NAME", "TIME", "VALUE"); err != nil { panic(err) } defer func() { successCount, failCount, err := appender.Close() // 残りのバッファをフラッシュ if err != nil { panic(err) } fmt.Println("Append finished. Success:", successCount, "Fail:", failCount) }() for _, rec := range records { // Connectに渡した列と同じ順序で値を1つずつ渡します。 if err := appender.Append(rec.Name, rec.Time, rec.Value); err != nil { panic(err) } } ``` 主なポイント: - **列選択**: `Connect`(または`WithInputColumns`)に渡す列リストが、各`Append`呼び出しで 順番に提供する列を正確に決めます。リストにない列はNULLとして入力されます。 - **列リストを省略**すると(例: `appender.Connect(ctx, dsn, "EXAMPLE")`)、Appenderはテーブルの **全列**を対象とし、各`Append`は`nil`を含めて全列の値を提供する必要があります。 そうしないと値の数のエラーになります。 - `Append`は行をバッファリングします。即時送信は`Flush()`を呼び出します。`Close()`はフラッシュとともに セッション単位の成功・失敗件数を返します。 - バッファリングは`WithBatchMaxRows`、`WithBatchMaxBytes`、`WithBatchMaxDelay`で調整できます。 - `WithBatchMaxRows(rows)`: デフォルト`512`、最小`1` - `WithBatchMaxBytes(bytes)`: デフォルト`512KB`、最小`4KB` - `WithBatchMaxDelay(duration)`: デフォルト`5ms`、最小`1ms`。`0`は時間ベースの閾値を使用しません。 - AppenderはTAG、LOG、TRANSACTIONテーブルで動作しますが、SQLを迂回するため、Appendはいずれの トランザクションにも含まれません。 ```go appender := &client.Appender{} if err := appender.Connect(ctx, dsn, "EXAMPLE", "NAME", "TIME", "VALUE"); err != nil { panic(err) } defer appender.Close() appender. WithBatchMaxBytes(1024 * 1024). // 1 MBの閾値 WithBatchMaxRows(2000). // 行数の閾値 WithBatchMaxDelay(500 * time.Millisecond) // 最大遅延の閾値 ``` {{< callout type="warning" >}} 有効なAppenderを使用する接続で通常のクエリを併用しないでください。 Appendのワークロードには別接続を使用してください。 {{< /callout >}} ### ARRAYと選択列Append 通常の`appender.Connect(ctx, dsn, table)`で列引数を省略し、ARRAY列の値に`api.NewSparseArray()`で 作成したオブジェクトを渡せます。固定要素の選択とは異なります。 ```go if err := appender.Connect(ctx, dsn, "ARRAY_APPEND_FULL_EXAMPLE"); err != nil { return err } ``` `ID LONG, A INT32[4]`テーブルの入力順序、スパース値の構成、エラー時のClose、検索確認は [通常Connectの例](../data-input-load-export/array-append/#go-full-open)を参照してください。 ```go func appendSelected(ctx context.Context, dsn string) error { appender := &client.Appender{} if err := appender.Connect( ctx, dsn, "ARRAY_APPEND_EXAMPLE", "ID", "A[0]", "A[3]", ); err != nil { return err } if err := appender.Append(int64(1), int32(10), int32(40)); err != nil { _, _, _ = appender.Close() return err } success, failed, err := appender.Close() if err != nil { return err } if failed != 0 { return fmt.Errorf( "append result: success=%d failed=%d", success, failed, ) } return nil } ``` 上記は`context`、`fmt`、`client "github.com/machbase/neo-client/v2"`のインポートを前提とします。 行ごとに異なる位置を入力する場合は`api.NewSparseArray()`を使用します。`Array.Set()`、`Get()`、 `Entries()`、および要素位置を指定したAppend対象の位置は0始まりです。 APIとバージョン制限は [Sparse ARRAYと選択列Append API](../data-input-load-export/array-append/)を参照してください。 ## 結果を構造体にスキャン 列順に全対象を列挙する代わりに、`db`タグで列を構造体フィールドにマッピングできます。 ヘルパーは取得済みの`*sql.Rows`をそのまま受け取るため、標準`database/sql` APIと併用できます。 ```go import client "github.com/machbase/neo-client/v2" type TagRecord struct { Name string `db:"NAME"` Time time.Time `db:"TIME"` Value float64 `db:"VALUE"` cached string // 非公開またはタグなしのフィールドは無視 } records, err := client.Select[TagRecord](ctx, db, `SELECT NAME, TIME, VALUE FROM EXAMPLE WHERE NAME = ? ORDER BY TIME LIMIT 100`, "sensor-1") ``` 提供するヘルパー: | 関数 | 用途 | | --- | --- | | `Select[T](ctx, q, query, args...)` | クエリを実行し、全行を`[]T`にスキャン | | `Get[T](ctx, q, query, args...)` | クエリを実行し、最初の行をスキャン。結果がなければ`sql.ErrNoRows` | | `ScanAll[T](rows)` / `ScanOne[T](rows)` | 呼び出し側がすでに開いたrowsに同じ操作を実行 | | `ScanEach[T](rows, fn)` | メモリ使用量を一定に保ちながら1行ずつストリーミング | | `NewCursor[T](rows)` | 明示的な`Next`/`Value`/`Err`イテレーター | | `ScanStruct(rows, &dest)` | `rows.Next()`を呼ばずに現在の行をスキャン | | `ScanRow(rows, &dest)` / `ScanRows(rows, &slice)` | ジェネリクスを使用しない形式 | `T`は構造体、構造体ポインター、単一列クエリのスカラー、`map[string]any`のいずれかです。 マッピング規則: - タグキーは`db`で、既存DTOをそのまま使用できるように`json`タグを代替として使用します。 - 列名は大文字・小文字を区別せずに一致するため、`db:"id"`は`ID`列と一致します。 - `db:"-"`はフィールドを除外し、**タグなしフィールドも除外**されます。タグなしフィールドを名前で マッピングするには`WithNameMapper(client.NameMapperIdentity())`を呼び出してください。 - 埋め込み構造体は平坦化され、名前のあるネスト構造体は`parent.child`で指定します。 - NULL列は`nil`になる`*T`フィールド、または`sql.Null[T]`で受け取れます。 デフォルトのマッピングは厳密です。一致するフィールドがない列と、一致する列がないフィールドは どちらもエラーとなり、変更された`SELECT *`が値を黙って欠落させることを防ぎます。 呼び出しごとに`WithLaxColumns()`または`WithLaxFields()`で緩和できます。 DATETIME列を`string`、`int64`、`time.Time`フィールドにスキャンする際は、machbase-neo HTTP APIの `timeformat`/`tz`クエリパラメーターと名前を合わせた追加の`db`タグオプションを使用できます。 ```go type Row struct { Time string `db:"TIME,timeformat=2006-01-02 15:04:05,tz=Local"` // カスタムレイアウト + 表示タイムゾーン Epoch int64 `db:"TIME,timeformat=ms"` // ミリ秒単位のエポック At time.Time `db:"TIME,tz=UTC"` // フィールド別にタイムゾーンを上書き } ``` - `timeformat=`: `string`/`*string`フィールドのGo時刻レイアウト (またはエポックを数値文字列で表す`ns`/`us`/`ms`/`s`) - `timeformat=ns|us|ms|s`: `int64`/`*int64`フィールドのエポック単位 - `tz=|Local|UTC`: `string`/`time.Time`フィールド(およびポインター形式)のタイムゾーン このオプションはタグがなくても適用されます。DATETIME列に一致する`string`、`int64`、`time.Time`の フィールドは、デフォルトとして`WithDateTime(timeformat, tz)`を使用します。`WithDateTime`も未設定なら `timeformat="2006-01-02 15:04:05.999"`と`tz="Local"`を使用します。 フィールド自体のタグは常に`WithDateTime`より優先されます。 `Select`、`ScanAll`、`ScanRows`は結果全体をメモリに読み込むため、`WithMaxRows`(デフォルト1000)を 超えると`ErrScanTooManyRows`で中断します。`WithMaxRows(n)`で上限を増やすか、`WithMaxRows(0)`で 制限を解除できます。制限のない`ScanEach`や`NewCursor`でストリーミングすることもできます。 ```go rows, err := db.QueryContext(ctx, `SELECT NAME, TIME, VALUE FROM EXAMPLE`) if err != nil { panic(err) } defer rows.Close() // ヘルパーは受け取ったrowsを閉じない var total float64 err = client.ScanEach(rows, func(rec TagRecord) error { total += rec.Value return nil }) ``` ## 名前付きパラメーター `NamedArgs`は構造体または`map[string]any`を、同じ`db`タグで`sql.Named`引数に変換します。 SQLテキストを検査・書き換えず、`:name`プレースホルダーはサーバーが直接解釈します。 ```go type condition struct { Name string `db:"name"` From time.Time `db:"from"` To time.Time `db:"to"` } args, err := client.NamedArgs(condition{Name: "sensor-1", From: begin, To: end}) if err != nil { panic(err) } records, err := client.Select[TagRecord](ctx, db, ` SELECT NAME, TIME, VALUE FROM EXAMPLE WHERE NAME = :name AND TIME BETWEEN :from AND :to`, args...) ``` 名前付きパラメーターには、パラメーター名メタデータを報告するサーバー(Machbase v8.7.0以降)が 必要です。`client.SupportsNamedParameters(ctx, db)`で確認します。非サポートの場合、クエリは `client.ErrNamedParamsUnsupported`で失敗するため、位置指定プレースホルダー`?`を使用する必要があります。 一般的なSQL機能とSDK別の違いは [Named Bind Parameter syntax](../../reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 ## Machbase 8.7: DECIMALと名前付きパラメーター Machbase 8.7は正確なDECIMAL値、NULL許容列情報、名前付きパラメーターを提供します。 ```go import "database/sql" import client "github.com/machbase/neo-client/v2" amount, err := client.ParseDecimal("1234567890.125", 30, 3) if err != nil { panic(err) } result, err := conn.ExecContext(ctx, "INSERT INTO payments(id, amount) VALUES (:id, :amount)", sql.Named("id", int32(1)), sql.Named("amount", amount), ) if err != nil { panic(err) } ``` `database/sql`ドライバーは`sql.Named`を受け取り、DECIMALの検索値を正確な文字列で返します。 パラメーター名は大文字・小文字を区別せずに一致し、繰り返すプレースホルダーには1回渡した値を適用します。 名前付き引数と位置指定引数は混用できません。`client.NamedArgs`は構造体またはmapから `sql.Named`リストを作成します。 Machbase 8.5.xに接続する場合は、そのサーバーバージョンがサポートするテーブル・データ型と、 位置指定パラメーター`?`を使用してください。名前付きパラメーターとMachbase 8.7のデータ型は使用できず、 NULL許容列情報が不明な場合(`ColumnType.Nullable()`が`ok=false`を返す場合)があります。 ### プリペアドステートメントと文キャッシュ `db.PrepareContext`で作成した文は複数回実行できます。ドライバーの文キャッシュは接続単位で動作し、 DSNキー`statement_cache=auto|on|off`で設定します。テーブルを削除して再作成した場合や結果列の型が 変わった場合は、キャッシュしたメタデータを更新するため文を再準備します。`USE`でセッションの データベースを変えた後も、既存の準備済み文やカーソルを別データベースの操作に再利用せず、 新しく準備またはオープンする必要があります。 ## 付属サンプルの実行 実行可能なサンプルはneo-clientリポジトリの`_example/`に含まれています。 ```sh go run ./_example/query.go -s 127.0.0.1:5656 -u sys -p manager go run ./_example/append.go -s 127.0.0.1:5656 -u sys -p manager go run ./_example/insert.go -s 127.0.0.1:5656 -u sys -p manager go run ./_example/scanbytag.go -s 127.0.0.1:5656 -u sys -p manager ``` ## 補足と制限事項 - 位置指定と名前付きプレースホルダーの両方を使用できますが、1つの文で混用できません。 名前付きAPIは`sql.Named()`を使用します。共通SQL機能とSDK別の違いは [Named Bind Parameter syntax](../../reference/sql/syntax/named-bind-parameter-syntax/)を参照してください。 - `database/sql`の接続プールは通常の`sql.DB`の方式で動作します。DSNに`database`/`db`を指定すると、 物理接続ごとに指定データベースを選択します。アプリケーションが直接`USE`を実行したセッションは、 プールへの返却前に設定済みデータベースへ復元されます。 - ROWID対応のStandard Editionでは、単一INSERT結果で`Result.LastInsertId()`を呼び出せます。 返された`int64`を`uint64`に変換してROWIDのビットパターンを保持します。詳細は [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 - 使用後の`Rows`、`Stmt`、`sql.Conn`、`sql.DB`は必ず閉じてください。 構造体スキャンヘルパーは受け取ったrowsを閉じません。 - `Appender.Close()`はAppendセッションの成功・失敗件数を返します。 - パラメーター型はドライバー実装に従います。一般的なSQL型、`time.Time`、`[]byte`、`net.IP`、 `api.Decimal`をサポートしますが、`bool`パラメーターはサポートしません。 --- title: "11.10 データの入力とエクスポート" url: https://docs.machbase.com/ja/dbms/development-tools-integration/data-input-load-export/ language: ja kind: section --- # 11.10 データの入力とエクスポート SQL、Append API、ファイルツールからデータ量と運用方式に合う経路を選択します。このページは選択と 検証のフローを説明します。全オプションは各ツール・SQLリファレンスを参照してください。 ## 入力方式の選択 | 方式 | 適している場合 | 主な確認値 | |------|-------------|-------------| | 単一行INSERT | 少量入力、エラーの即時確認 | 影響行数、生成ID | | preparedバッチ | 同じSQLの繰り返し実行 | 項目別の結果と失敗位置 | | Append API | 継続的なTAG・LOGの大量収集 | サーバー処理応答、成功・失敗件数 | | `LOAD DATA INFILE` | サーバーが読み取れるファイルのロード | サーバーファイルの権限、入力件数 | | `machloader`・`csvimport` | クライアントファイルのロード | ログ・エラー行ファイル、入力・失敗件数 | ### 経路とツールの比較 | 経路・ツール | 実行場所と用途 | |---|---| | SDK Append | アプリケーションから継続的に複数のTAG・LOG行を送信 | | SQL INSERT | 少量入力と通常のSQL連携 | | `LOAD DATA INFILE` | サーバーが読み取れるファイルをSQLでロード | | `machloader` | クライアントファイルのマッピング・ログ・エラー行ファイルを細かく制御 | | `csvimport`・`csvexport` | 単純なCSV入出力のラッパー | | `tagmetaimport` | TAGメタデータの一括登録・変更 | `tagmetaimport`はTAG測定値の入力ツールではありません。正確なオプションは [コマンドラインツール](/ja/dbms/reference/command-line-tools/)を確認してください。 元データを保持する必要がある時系列・イベントはTAGまたはLOGに入れます。リレーショナルな変更は TRANSACTION、小さな参照データはLOOKUP、再生成可能なメモリキャッシュはVOLATILEを使用します。 テーブル選択後、予想件数、許容遅延、再試行単位、重複ポリシーに基づいて入力方式を決めます。 ## SQL INSERT 次の例は作成から後片付けまで順番に実行できます。 ```sql CREATE LOG TABLE integration_insert_demo ( event_time DATETIME, sensor_id VARCHAR(32), value DOUBLE ); INSERT INTO integration_insert_demo VALUES (TO_DATE('2026-01-01 00:00:00'), 'TEMP-01', 25.3); SELECT sensor_id, value FROM integration_insert_demo; DROP TABLE integration_insert_demo; ``` アプリケーションでは値をpreparedパラメーターでバインドし、返された影響行数を確認します。 ## Append API Appendは各SDKの専用APIでテーブルを開き、複数行を送ってからフラッシュ・クローズするフローです。 列順序と型を対象スキーマに合わせ、接続を通常のクエリと分けます。言語別の完全なコードは 本章のSDK別ページを参照してください。 Machbase DBMS 8.7.0では、Append Open時に入力する列や`ARRAY`要素の対象を選択できます。 行ごとに異なるARRAY位置を入力する場合はSDKのスパースARRAYオブジェクトを使用します。 選択基準、API、検証例は[Sparse ARRAYと選択列Append API](array-append/)を参照してください。 ## LOAD DATA INFILE `LOAD DATA INFILE`はサーバーからアクセスできるファイルをSQLでロードします。 ファイルパスはサーバープロセスの視点で解釈されるため、次の点を確認します。 - サーバーホストにファイルが存在するか - サーバープロセスのアカウントがファイルを読み取れるか - 区切り文字、引用文字、エンコーディング、日付形式が元データと一致するか - 失敗行を識別するログ・エラー行ファイルをどこに保存するか 構文とサポートするオプションは [LOAD DATA INFILE](/ja/dbms/reference/sql/syntax/load-data-infile-syntax/)を参照してください。 ## CSVファイルの準備 先頭行をヘッダーにするか決め、全行で列数と順序を統一します。NULL、空文字列、区切り文字を含む文字列、 改行、DATETIME形式をサンプルファイルで先に検証します。大きなファイルは全体実行前に小さなサンプルで テーブルスキーマと変換規則を確認します。 ## machloaderでインポート 基本構文は次のとおりです。 ```bash "$MACHBASE_HOME/bin/machloader" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -i -t SENSOR_LOG -d /data/sensor.csv -l /data/sensor.log -b /data/sensor.bad ``` ヘッダーがある場合は`-H`、区切り文字がカンマ以外なら`-D`、日付形式が異なる場合は`-F`を明示します。 全オプションは[machloader](/ja/dbms/reference/command-line-tools/machloader/)を参照してください。 ## csvimportでインポート `csvimport`はmachloaderでよく使うCSVオプションを簡略化したツールです。 ```bash "$MACHBASE_HOME/bin/csvimport" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -t SENSOR_LOG -d /data/sensor.csv -H -l /data/sensor.log -b /data/sensor.bad ``` `-C`の自動作成では、すべての列が意図した業務用の型になるとは限りません。本番ロードは テーブルを明示的に作成し、スキーマを確認してから実行します。 ## エクスポート方式の選択 | 方式 | 適している場合 | |------|-------------| | `SAVE DATA INTO` | SQL条件と検索列を選択してサーバーファイルを作成 | | `machloader -o` | テーブル単位のエクスポートと詳細オプションの使用 | | `csvexport` | 単純なCSVエクスポート | | SDK SELECT | アプリケーションで行を変換・送信する必要がある場合 | ## ファイル所有権とパス `SAVE DATA INTO`のパスとファイル権限はサーバープロセス基準です。machloaderとcsvexportの 出力ファイルは、ツールを実行したOSユーザー基準です。相対パスを避け、既存ファイルの上書きポリシーと 利用可能なディスク容量を先に確認します。 ## SAVE DATA INTO SQL条件で結果をエクスポートする際に使用します。本番経路で実行する前に、小さな結果と専用の検証パスで ファイル作成・エンコーディング・ヘッダーを確認します。全構文は [SAVE DATA INTO](/ja/dbms/reference/sql/syntax/save-data-into-syntax/)を参照してください。 ## machloaderでエクスポート ```bash "$MACHBASE_HOME/bin/machloader" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -o -t SENSOR_LOG -d /data/sensor-export.csv -H -l /data/sensor-export.log ``` ## csvexportでエクスポート ```bash "$MACHBASE_HOME/bin/csvexport" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -t SENSOR_LOG -d /data/sensor-export.csv -H -l /data/sensor-export.log ``` ## バッチ処理 - バッチサイズは行サイズと遅延要件に基づいて負荷テストします。 - 各バッチの入力元オフセットと対象の成功件数を記録します。 - 部分失敗時は、全体の再実行より失敗行だけを分離して再処理します。 - 同じ行を再送しても安全になるよう、業務キーと重複ポリシーを定義します。 ## 大量入力のエラー処理 1. ツールの終了コードと集計件数を確認します。 2. ログでサーバーのエラーコードと最初の失敗原因を確認します。 3. エラー行ファイルの列数、型、NULL、日付形式、エンコーディングを元データと比較します。 4. 修正した小さなファイルで再検証し、失敗行だけを再入力します。 5. 対象テーブルの最終件数、時間範囲、サンプル行を確認します。 認証情報や機密の生データがログ・エラー行ファイルに残る可能性があるため、アクセス権と保持期間を設定します。 --- title: "11.10.1 Sparse ARRAYと選択列Append API" url: https://docs.machbase.com/ja/dbms/development-tools-integration/data-input-load-export/array-append/ language: ja kind: page --- # 11.10.1 Sparse ARRAYと選択列Append API Machbase DBMS 8.7.0では、固定長`ARRAY`の一部の位置だけを入力できます。入力位置が行ごとに異なる 場合はスパースARRAYを使用し、複数のAppend行で同じ位置を入力する場合はAppend Open時に選択列を 指定します。 スパースARRAYは**1つの列に入れる値の表現方法**であり、選択列は**1行で入力する列や要素を選ぶ方法**です。 通常のOpenで全行を入力する場合も、ARRAY列にスパースオブジェクトを渡せます。Node.jsは `appendOpen()`の列定義引数が必須のため、全列を列挙して同じ入力を行います。 `ARRAY`型の宣言、通常の入力、検索、SDK別の密なARRAY処理は [数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ## 入力方式の選択 | 要件 | 推奨方式 | |---|---| | SQLの1行で値のある位置だけを指定 | `ARRAY_SPARSE(position => value, ...)` | | 複数のAppend行が常に同じ位置を入力 | Append Openの`A[0]`、`A[3]`対象 | | 通常Openで全行を入力し、ARRAY位置が変わる | 全行のARRAY値にSDKのスパースオブジェクトを渡す | | 一部の列のみ入力し、ARRAY位置も変わる | 選択リストの全体`A`対象とSDKのスパースオブジェクト | | 全要素がNULLで、配列自体は非NULLのARRAY | 空のスパースオブジェクト | | ARRAY自体がNULL | SQLの`NULL`またはSDKの配列全体NULL値 | 位置はSQLとすべてのMachbase専用SDK APIで0から始まります。 ## SQLのスパース入力 ### ARRAY_SPARSE 対象列があるINSERTまたはUPDATEの文脈では、位置と値だけを指定します。 ```sql CREATE LOG TABLE ARRAY_APPEND_EXAMPLE ( ID LONG, A INT32[4] ); INSERT INTO ARRAY_APPEND_EXAMPLE (ID, A) VALUES (1, ARRAY_SPARSE(0 => 10, 3 => 40)); ``` SELECTのように対象型を推論できない文脈では、要素型と要素数を先に指定します。 ```sql SELECT ARRAY_SPARSE(INT32[4], 0 => 10, 3 => 40); SELECT ARRAY_SPARSE(DECIMAL(12,4)[4], 1 => 1.2500); ``` - 位置は`0..cardinality-1`の範囲の整数リテラルである必要があります。 - ペアの順序は任意ですが、同じ位置を重複指定できません。 - 省略した位置と`position => NULL`は要素NULLになります。 - `ARRAY_SPARSE()`または`ARRAY_SPARSE(INT32[4])`は、全要素がNULLのARRAYです。 - 配列全体のNULLは`ARRAY_SPARSE()`ではなくSQLの`NULL`で入力します。 - 不正な位置や要素変換は文全体を失敗させます。 ### スパースの直接短縮表記 `ARRAY_SPARSE`ラッパーなしで、角括弧内に位置と値のペアを直接記述できます。 ```sql INSERT INTO ARRAY_APPEND_EXAMPLE (ID, A) VALUES (2, [0 => 10, 3 => 40]); SELECT [1 => 12, 33 => 23]; ``` 対象ARRAYがある場合は、その型と要素数を使用します。単独の式では密なARRAYと同じ数値の共通型を推論し、 要素数を`最大のposition + 1`で決定します。そのため2番目の例は`INT32[34]`です。 単独の全NULLスパース式は要素型を判定できないためエラーです。この場合は `ARRAY_SPARSE(TYPE[N], ...)`形式を使用します。`[]`は従来の密な空コンストラクターとして維持され、 `ARRAY[0 => 1]`はサポートしません。 ### INSERT対象への位置指定 複数行が同じ位置を入力する場合は、列リストに要素対象を直接指定します。 ```sql INSERT INTO ARRAY_APPEND_EXAMPLE (ID, A[0], A[3]) VALUES (2, 10, 40); -- Aは存在しますが全要素がNULLです。 INSERT INTO ARRAY_APPEND_EXAMPLE (ID, A[0], A[3]) VALUES (3, NULL, NULL); -- A自体がNULLです。 INSERT INTO ARRAY_APPEND_EXAMPLE (ID) VALUES (4); ``` 同じ文で`A`と`A[0]`を併記したり、同じ要素を2回指定したりすることはできません。 スカラー列や範囲外の位置を要素対象にするとエラーです。 要素位置を指定した対象は`INSERT ... VALUES`とAppendの選択対象でサポートします。 `INSERT ... SELECT`と`UPDATE ... SET A[0] = ...`ではサポートしません。 ## Appendの共通規則 ### 全行入力と選択入力 通常Openはテーブルの入力列順序を使用し、選択Openは指定した対象リストの順序を使用します。 以下の実習の通常Openでは`ID`、`A`の順に2つの値を渡し、`_arrival_time`値は別途入れません。 この例の各APIがLOGの自動時刻を処理します。受信時刻を明示する場合は、該当SDKの時刻指定APIを使用します。 Node.jsは通常Openと選択Openが別メソッドに分かれていません。全体入力にも`name`と`type`のある 列定義が必要で、この実習では`ID`と`A`をテーブル順に列挙します。 `appendOpen(table)`だけを呼び出す方式や、空の列リストを渡す方式はサポートしません。 ### 実習の準備と再実行 通常の例と選択の例を分けて実行できるよう、別々のテーブルを使用します。 各例を実行する前に、接続先データベースで次の準備SQLを実行します。 ```sql CREATE LOG TABLE ARRAY_APPEND_FULL_EXAMPLE (ID LONG, A INT32[4]); ``` 通常の例のファイル名には`full`を付けます。選択の例は前に作成した`ARRAY_APPEND_EXAMPLE`を使用します。 Cの選択例はこのテーブルを直接再作成するため、実習専用の名前であることを確認してください。 他SDKの選択例でも同じ構造の空の`ARRAY_APPEND_EXAMPLE`を準備します。 各SDKの例は**独立して実行**します。異なるSDKを同じテーブルに連続して実行するとIDが重複します。 再実行時は結果を確認して[実習の後片付け](#sparse-append-cleanup)を行い、該当テーブルを再作成します。 サーバーアドレス・ポート・アカウントは実際の実習環境に合わせます。 ### 共通の結果 どちらの入力方式も次の4行を作成します。通常の例はID=1もスパースオブジェクトで入力し、 選択の例はID=1に固定要素対象を使用します。 ```text ID=1 A=[10,null,null,40] スパースオブジェクトまたは固定要素対象 ID=2 A=[null,200,null,400] ARRAY列にスパースオブジェクト ID=3 A=[null,null,null,null] 空のスパースオブジェクト ID=4 A=NULL 全体NULL ``` スパースオブジェクトで省略したARRAY要素は要素NULLになります。`entry_count == 0`や空の スパースオブジェクトは、長さ0の配列ではなく、宣言された長さのすべての要素がNULLの配列です。 全体NULLは配列値自体がないことを意味し、`ARRAY_LENGTH`の結果もNULLです。 ### 選択Openの規則 次の規則は**選択Openの対象リスト**に適用されます。通常Openで列引数を省略することと 「空の選択リスト」を混同しないでください。 選択リストにない通常の列は既存のAppend規則に従って処理されます。 - NULL許容列はNULLを使用します。 - DEFAULTがある列はDEFAULTを使用します。 - 値が必須の列が欠けると、Append Openまたは行入力が失敗します。 選択対象リストは空にできず、大文字・小文字を無視して重複してはいけません。 ARRAY全体の対象と、同じARRAYの要素対象を同時に開くことはできません。 Append Open後は、各行の値の数と順序が対象リストと完全に一致する必要があります。 行入力中にエラーが発生しても開いたAppendハンドルは閉じる必要があります。 Append Open自体が失敗した場合はSDKが内部状態を解放するため、同じ接続を再使用できます。 ## C SQLCLI ARRAYの入力と検索には次の公開型を使用します。 | 型または定数 | 用途 | |---|---| | `SQL_MACHBASE_ARRAY` | SQL ARRAY型の識別 | | `SQL_C_MACHBASE_ARRAY` | 密なARRAYの検索・バインド用ディスクリプター | | `SQL_C_MACHBASE_SPARSE_ARRAY` | preparedのスパースARRAY入力 | | `SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH` | Appendスパースディスクリプターの識別 | ### 通常OpenでスパースARRAYを入力 `SQLAppendOpen()`で開き、`SQL_APPEND_PARAM`配列に`ID`と`A`を渡します。 `A`の`mVar.mData`には`SQL_MACHBASE_SPARSE_ARRAY_DESC`のアドレス、`mVar.mLength`には `SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH`を指定します。列選択は行わず、値の数を明示する `SQLAppendDataV3(..., row, 2)`を使用します。 旧式の`SQLAppendData(void *[])`にこのディスクリプターをそのまま渡す例ではありません。 前の準備SQLで作成した空の`ARRAY_APPEND_FULL_EXAMPLE`を使用します。ディスクリプターと位置・値・ インジケーターバッファはAppend呼び出しが終わるまで有効である必要があります。同じ開いたハンドルで 1行目と2行目の入力位置を変え、空のスパース配列と全体NULLも入力します。 ```c /* sparse_append_full.c */ #include #include #include #include static int ok(SQLRETURN rc) { return rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; } static void fail(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt, const char *where) { SQLCHAR state[6] = {0}; SQLCHAR message[1024] = {0}; SQLINTEGER native = 0; SQLSMALLINT length = 0; SQLError(env, dbc, stmt, state, &native, message, (SQLSMALLINT)sizeof(message), &length); fprintf(stderr, "%s: %s %d %s\n", where, state, (int)native, message); exit(EXIT_FAILURE); } int main(void) { SQLHENV env = SQL_NULL_HENV; SQLHDBC dbc = SQL_NULL_HDBC; SQLHSTMT sql = SQL_NULL_HSTMT; SQLHSTMT append = SQL_NULL_HSTMT; SQLCHAR conn[] = "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER;CONNTYPE=1"; SQL_APPEND_PARAM row[2]; SQLUSMALLINT positions[2] = {0, 3}; SQLINTEGER values[2] = {10, 40}; SQLLEN indicators[2] = {0, 0}; SQL_MACHBASE_SPARSE_ARRAY_DESC sparse; SQLBIGINT success = 0; SQLBIGINT failure = 0; SQLINTEGER id; SQLLEN idInd; SQLLEN textInd; SQLCHAR text[128]; if (!ok(SQLAllocEnv(&env)) || !ok(SQLAllocConnect(env, &dbc)) || !ok(SQLDriverConnect(dbc, NULL, conn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT)) || !ok(SQLAllocStmt(dbc, &sql)) || !ok(SQLAllocStmt(dbc, &append))) fail(env, dbc, SQL_NULL_HSTMT, "connect"); memset(&sparse, 0, sizeof(sparse)); sparse.struct_size = sizeof(sparse); sparse.element_c_type = SQL_C_SLONG; sparse.cardinality = 4; sparse.entry_count = 2; sparse.positions = positions; sparse.values = values; sparse.value_stride = sizeof(values[0]); sparse.element_indicators = indicators; memset(row, 0, sizeof(row)); if (!ok(SQLAppendOpen(append, (SQLCHAR*)"ARRAY_APPEND_FULL_EXAMPLE", 0))) fail(env, dbc, append, "sparse open"); row[0].mLong = 1; row[1].mVar.mData = &sparse; row[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "first sparse row"); } positions[0] = 1; values[0] = 200; values[1] = 400; row[0].mLong = 2; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "sparse row"); } row[0].mLong = 3; sparse.entry_count = 0; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "empty sparse row"); } row[0].mLong = 4; row[1].mVar.mData = NULL; row[1].mVar.mLength = 0; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "whole NULL row"); } success = 0; failure = 0; if (!ok(SQLAppendClose(append, &success, &failure)) || success != 4 || failure != 0) fail(env, dbc, append, "sparse close"); if (!ok(SQLExecDirect(sql, (SQLCHAR*)"SELECT ID,A FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID", SQL_NTS))) fail(env, dbc, sql, "select"); if (!ok(SQLBindCol(sql, 1, SQL_C_SLONG, &id, sizeof(id), &idInd)) || !ok(SQLBindCol(sql, 2, SQL_C_CHAR, text, sizeof(text), &textInd))) fail(env, dbc, sql, "bind verify"); for (;;) { SQLRETURN fetch = SQLFetch(sql); if (fetch == SQL_NO_DATA) break; if (!ok(fetch)) fail(env, dbc, sql, "fetch verify"); printf("%d %s\n", (int)id, textInd == SQL_NULL_DATA ? "NULL" : (char*)text); } SQLFreeStmt(append, SQL_DROP); SQLFreeStmt(sql, SQL_DROP); SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); return EXIT_SUCCESS; } ``` ```bash cc -I"$MACHBASE_HOME/include" sparse_append_full.c \ -L"$MACHBASE_HOME/lib" -lmachbasecli -lm -ldl -lrt -pthread \ -o sparse_append_full LD_LIBRARY_PATH="$MACHBASE_HOME/lib" ./sparse_append_full ``` プログラムはCloseの成功4件・失敗0件を確認し、検索したIDと配列を出力します。 詳細な期待値は[結果の確認](#結果の確認)と比較します。入力エラー時はAppendを閉じてからプロセスを 終了します。再試行前に、テーブルに実際に反映された行を確認します。 ### 選択列Openで入力 `SQLAppendOpenColumns()`とワイド文字版は、最後の要素が`NULL`の列名ポインター配列を受け取ります。 列数を指定する別の引数はありません。 ```c SQLRETURN SQL_API SQLAppendOpenColumns( SQLHSTMT aStmtHandle, SQLCHAR *aTableName, SQLCHAR **aColumnNames, SQLINTEGER aErrorCheckCount); SQLRETURN SQL_API SQLAppendOpenColumnsW( SQLHSTMT aStmtHandle, SQLWCHAR *aTableName, SQLWCHAR **aColumnNames, SQLINTEGER aErrorCheckCount); ``` `aColumnNames == NULL`または最初の要素が`NULL`の場合はエラーです。Cポインターには配列長の情報が ないため、呼び出し側は必ず最後の`NULL`まで有効な配列を渡す必要があります。終端の`NULL`を忘れると 配列境界外を読み取る可能性があるため、安全に診断されるとは考えないでください。 次の`sparse_append.c`はテーブルを作成して4行をAppendし、結果を出力します。 ```c /* sparse_append.c */ #include #include #include #include static int ok(SQLRETURN rc) { return rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; } static void fail(SQLHENV env, SQLHDBC dbc, SQLHSTMT stmt, const char *where) { SQLCHAR state[6] = {0}; SQLCHAR message[1024] = {0}; SQLINTEGER native = 0; SQLSMALLINT length = 0; SQLError(env, dbc, stmt, state, &native, message, (SQLSMALLINT)sizeof(message), &length); fprintf(stderr, "%s: %s %d %s\n", where, state, (int)native, message); exit(EXIT_FAILURE); } int main(void) { SQLHENV env = SQL_NULL_HENV; SQLHDBC dbc = SQL_NULL_HDBC; SQLHSTMT sql = SQL_NULL_HSTMT; SQLHSTMT append = SQL_NULL_HSTMT; SQLCHAR conn[] = "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER;CONNTYPE=1"; SQLCHAR *fixed[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A[0]", (SQLCHAR*)"A[3]", NULL}; SQLCHAR *whole[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A", NULL}; SQL_APPEND_PARAM row[3]; SQLUSMALLINT positions[2] = {1, 3}; SQLINTEGER values[2] = {200, 400}; SQLLEN indicators[2] = {0, 0}; SQL_MACHBASE_SPARSE_ARRAY_DESC sparse; SQLBIGINT success = 0; SQLBIGINT failure = 0; SQLINTEGER id; SQLLEN idInd; SQLLEN textInd; SQLCHAR text[128]; if (!ok(SQLAllocEnv(&env)) || !ok(SQLAllocConnect(env, &dbc)) || !ok(SQLDriverConnect(dbc, NULL, conn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT)) || !ok(SQLAllocStmt(dbc, &sql)) || !ok(SQLAllocStmt(dbc, &append))) fail(env, dbc, SQL_NULL_HSTMT, "connect"); SQLExecDirect(sql, (SQLCHAR*)"DROP TABLE ARRAY_APPEND_EXAMPLE", SQL_NTS); if (!ok(SQLExecDirect(sql, (SQLCHAR*)"CREATE LOG TABLE ARRAY_APPEND_EXAMPLE(ID LONG,A INT32[4])", SQL_NTS))) fail(env, dbc, sql, "create"); memset(row, 0, sizeof(row)); row[0].mLong = 1; row[1].mInteger = 10; row[2].mInteger = 40; if (!ok(SQLAppendOpenColumns(append, (SQLCHAR*)"ARRAY_APPEND_EXAMPLE", fixed, 0))) fail(env, dbc, append, "fixed open"); if (!ok(SQLAppendDataV3(append, row, 3))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "fixed row"); } if (!ok(SQLAppendClose(append, &success, &failure)) || success != 1 || failure != 0) fail(env, dbc, append, "fixed close"); memset(&sparse, 0, sizeof(sparse)); sparse.struct_size = sizeof(sparse); sparse.element_c_type = SQL_C_SLONG; sparse.cardinality = 4; sparse.entry_count = 2; sparse.positions = positions; sparse.values = values; sparse.value_stride = sizeof(values[0]); sparse.element_indicators = indicators; memset(row, 0, sizeof(row)); if (!ok(SQLAppendOpenColumns(append, (SQLCHAR*)"ARRAY_APPEND_EXAMPLE", whole, 0))) fail(env, dbc, append, "sparse open"); row[0].mLong = 2; row[1].mVar.mData = &sparse; row[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "sparse row"); } row[0].mLong = 3; sparse.entry_count = 0; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "empty sparse row"); } row[0].mLong = 4; row[1].mVar.mData = NULL; row[1].mVar.mLength = 0; if (!ok(SQLAppendDataV3(append, row, 2))) { SQLAppendClose(append, &success, &failure); fail(env, dbc, append, "whole NULL row"); } success = 0; failure = 0; if (!ok(SQLAppendClose(append, &success, &failure)) || success != 3 || failure != 0) fail(env, dbc, append, "sparse close"); if (!ok(SQLExecDirect(sql, (SQLCHAR*)"SELECT ID,A FROM ARRAY_APPEND_EXAMPLE ORDER BY ID", SQL_NTS))) fail(env, dbc, sql, "select"); if (!ok(SQLBindCol(sql, 1, SQL_C_SLONG, &id, sizeof(id), &idInd)) || !ok(SQLBindCol(sql, 2, SQL_C_CHAR, text, sizeof(text), &textInd))) fail(env, dbc, sql, "bind verify"); for (;;) { SQLRETURN fetch = SQLFetch(sql); if (fetch == SQL_NO_DATA) break; if (!ok(fetch)) fail(env, dbc, sql, "fetch verify"); printf("%d %s\n", (int)id, textInd == SQL_NULL_DATA ? "NULL" : (char*)text); } SQLFreeStmt(append, SQL_DROP); SQLFreeStmt(sql, SQL_DROP); SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); return EXIT_SUCCESS; } ``` 次のようにビルドして実行します。 ```bash cc -I"$MACHBASE_HOME/include" sparse_append.c \ -L"$MACHBASE_HOME/lib" -lmachbasecli -lm -ldl -lrt -pthread \ -o sparse_append LD_LIBRARY_PATH="$MACHBASE_HOME/lib" ./sparse_append ``` ディスクリプターの位置は0始まりです。ソートは不要ですが重複できません。 エントリーのインジケーターが`SQL_NULL_DATA`の場合、その位置は要素NULLです。 `entry_count == 0`は空のスパースARRAYで、配列全体のNULLは`mVar.mData = NULL`、 `mVar.mLength = 0`で指定します。 ## C++ SQLCLI ### 通常OpenでスパースARRAYを入力 Cと同じディスクリプターと`SQLAppendOpen()`を使用します。位置・値バッファは`std::array`で保持し、 成功・例外の両経路でAppendを閉じます。通常の実習テーブルを先に準備します。 ```cpp /* sparse_append_full.cpp */ #include #include #include #include static bool ok(SQLRETURN rc) { return rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; } struct Handles { SQLHENV env{SQL_NULL_HENV}; SQLHDBC dbc{SQL_NULL_HDBC}; SQLHSTMT stmt{SQL_NULL_HSTMT}; ~Handles() { if (stmt != SQL_NULL_HSTMT) SQLFreeStmt(stmt, SQL_DROP); if (dbc != SQL_NULL_HDBC) { SQLDisconnect(dbc); SQLFreeConnect(dbc); } if (env != SQL_NULL_HENV) SQLFreeEnv(env); } }; int main() { Handles h; SQLCHAR conn[] = "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER;CONNTYPE=1"; if (!ok(SQLAllocEnv(&h.env)) || !ok(SQLAllocConnect(h.env, &h.dbc)) || !ok(SQLDriverConnect(h.dbc, nullptr, conn, SQL_NTS, nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT)) || !ok(SQLAllocStmt(h.dbc, &h.stmt))) throw std::runtime_error("connect"); std::array positions{0, 3}; std::array values{10, 40}; std::array indicators{0, 0}; SQL_MACHBASE_SPARSE_ARRAY_DESC sparse{}; sparse.struct_size = sizeof(sparse); sparse.element_c_type = SQL_C_SLONG; sparse.cardinality = 4; sparse.entry_count = 2; sparse.positions = positions.data(); sparse.values = values.data(); sparse.value_stride = sizeof(values[0]); sparse.element_indicators = indicators.data(); std::array row{}; row[1].mVar.mData = &sparse; row[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; SQLBIGINT success = 0, failure = 0; if (!ok(SQLAppendOpen(h.stmt, (SQLCHAR*)"ARRAY_APPEND_FULL_EXAMPLE", 0))) throw std::runtime_error("SQLAppendOpen"); try { for (int id = 1; id <= 4; ++id) { row[0].mLong = id; if (id == 2) { positions[0] = 1; values[0] = 200; values[1] = 400; } else if (id == 3) { sparse.entry_count = 0; } else if (id == 4) { row[1].mVar.mData = nullptr; row[1].mVar.mLength = 0; } if (!ok(SQLAppendDataV3(h.stmt, row.data(), 2))) throw std::runtime_error("SQLAppendDataV3"); } } catch (...) { SQLAppendClose(h.stmt, &success, &failure); throw; } if (!ok(SQLAppendClose(h.stmt, &success, &failure)) || success != 4 || failure != 0) throw std::runtime_error("SQLAppendClose"); if (!ok(SQLExecDirect(h.stmt, (SQLCHAR*)"SELECT ID,A FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID", SQL_NTS))) throw std::runtime_error("verify query"); SQLINTEGER id{}; SQLLEN idInd{}, arrayInd{}; SQLCHAR value[128]{}; if (!ok(SQLBindCol(h.stmt, 1, SQL_C_SLONG, &id, sizeof(id), &idInd)) || !ok(SQLBindCol(h.stmt, 2, SQL_C_CHAR, value, sizeof(value), &arrayInd))) throw std::runtime_error("bind verify"); for (;;) { SQLRETURN fetch = SQLFetch(h.stmt); if (fetch == SQL_NO_DATA) break; if (!ok(fetch)) throw std::runtime_error("fetch verify"); std::cout << id << ' ' << (arrayInd == SQL_NULL_DATA ? "NULL" : (char*)value) << '\n'; } } ``` ```bash c++ -std=c++11 -I"$MACHBASE_HOME/include" sparse_append_full.cpp \ -L"$MACHBASE_HOME/lib" -lmachbasecli -lm -ldl -lrt -pthread \ -o sparse_append_full_cpp LD_LIBRARY_PATH="$MACHBASE_HOME/lib" ./sparse_append_full_cpp ``` ### 選択列Openで入力 C++専用の転送オブジェクトを新設せず、SQLCLIディスクリプターを使用します。次の例はRAIIラッパーで closeを保証し、C++コンテナーの存続中にディスクリプターを送信します。 ```cpp /* sparse_append.cpp */ #include #include #include #include static bool ok(SQLRETURN rc) { return rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; } struct Handles { SQLHENV env{SQL_NULL_HENV}; SQLHDBC dbc{SQL_NULL_HDBC}; SQLHSTMT stmt{SQL_NULL_HSTMT}; ~Handles() { if (stmt != SQL_NULL_HSTMT) SQLFreeStmt(stmt, SQL_DROP); if (dbc != SQL_NULL_HDBC) { SQLDisconnect(dbc); SQLFreeConnect(dbc); } if (env != SQL_NULL_HENV) SQLFreeEnv(env); } }; static void append(Handles& h, SQLCHAR **columns, SQL_APPEND_PARAM *row, SQLINTEGER count) { SQLBIGINT success = 0, failure = 0; if (!ok(SQLAppendOpenColumns(h.stmt, (SQLCHAR*)"ARRAY_APPEND_EXAMPLE", columns, 0))) throw std::runtime_error("SQLAppendOpenColumns"); try { if (!ok(SQLAppendDataV3(h.stmt, row, count))) throw std::runtime_error("SQLAppendDataV3"); } catch (...) { SQLAppendClose(h.stmt, &success, &failure); throw; } if (!ok(SQLAppendClose(h.stmt, &success, &failure)) || failure != 0) throw std::runtime_error("SQLAppendClose"); } int main() { Handles h; SQLCHAR conn[] = "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER;CONNTYPE=1"; if (!ok(SQLAllocEnv(&h.env)) || !ok(SQLAllocConnect(h.env, &h.dbc)) || !ok(SQLDriverConnect(h.dbc, nullptr, conn, SQL_NTS, nullptr, 0, nullptr, SQL_DRIVER_NOPROMPT)) || !ok(SQLAllocStmt(h.dbc, &h.stmt))) throw std::runtime_error("connect"); SQLCHAR *fixed[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A[0]", (SQLCHAR*)"A[3]", nullptr}; std::array row{}; row[0].mLong = 1; row[1].mInteger = 10; row[2].mInteger = 40; append(h, fixed, row.data(), 3); std::array pos{1, 3}; std::array val{200, 400}; std::array ind{0, 0}; SQL_MACHBASE_SPARSE_ARRAY_DESC sparse{}; sparse.struct_size = sizeof(sparse); sparse.element_c_type = SQL_C_SLONG; sparse.cardinality = 4; sparse.entry_count = 2; sparse.positions = pos.data(); sparse.values = val.data(); sparse.value_stride = sizeof(val[0]); sparse.element_indicators = ind.data(); SQLCHAR *whole[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A", nullptr}; std::array sparseRow{}; sparseRow[0].mLong = 2; sparseRow[1].mVar.mData = &sparse; sparseRow[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; append(h, whole, sparseRow.data(), 2); sparse.entry_count = 0; sparseRow[0].mLong = 3; append(h, whole, sparseRow.data(), 2); sparseRow[0].mLong = 4; sparseRow[1].mVar.mData = nullptr; sparseRow[1].mVar.mLength = 0; append(h, whole, sparseRow.data(), 2); if (!ok(SQLExecDirect(h.stmt, (SQLCHAR*)"SELECT ID,A FROM ARRAY_APPEND_EXAMPLE ORDER BY ID", SQL_NTS))) throw std::runtime_error("verify query"); SQLINTEGER id{}; SQLLEN idInd{}, arrayInd{}; SQLCHAR value[128]{}; if (!ok(SQLBindCol(h.stmt, 1, SQL_C_SLONG, &id, sizeof(id), &idInd)) || !ok(SQLBindCol(h.stmt, 2, SQL_C_CHAR, value, sizeof(value), &arrayInd))) throw std::runtime_error("bind verify"); for (;;) { SQLRETURN fetch = SQLFetch(h.stmt); if (fetch == SQL_NO_DATA) break; if (!ok(fetch)) throw std::runtime_error("fetch verify"); std::cout << id << ' ' << (arrayInd == SQL_NULL_DATA ? "NULL" : (char*)value) << '\n'; } } ``` ```bash c++ -std=c++11 -I"$MACHBASE_HOME/include" sparse_append.cpp \ -L"$MACHBASE_HOME/lib" -lmachbasecli -lm -ldl -lrt -pthread \ -o sparse_append_cpp ``` ## Machbase ODBC拡張 ### 通常OpenでスパースARRAYを入力 Machbaseドライバーを直接リンクするCプログラムは、[Cの通常Open例](#c-full-open)の `sparse_append_full.c`をそのまま使用します。このソースも`SQLAppendOpen()`の後に `SQLAppendDataV3()`でスパースディスクリプターを渡し、`OpenColumns`は呼び出しません。 同じバージョンのヘッダーとODBC拡張ライブラリでビルドします。 ```bash cc -I"$MACHBASE_HOME/include" sparse_append_full.c \ -L"$MACHBASE_HOME/lib" -lmachbasecli_dll -lm -ldl -lrt -pthread \ -o sparse_append_full_odbc LD_LIBRARY_PATH="$MACHBASE_HOME/lib" ./sparse_append_full_odbc ``` 実行前に通常の実習テーブルを準備します。この例のハンドルはMachbaseドライバーが直接生成するもので、 汎用ODBC Driver Managerのハンドルと混用しません。 ### 選択列Openで入力 Machbaseドライバーライブラリを直接リンクし、`machbase_sqlcli.h`を使用するODBC Cアプリケーションは 同じ拡張関数を使用できます。次の例は直接のMachbaseドライバーAPIで4行を入力します。 テーブルは前節のDDLで事前に作成します。 ```c /* sparse_odbc.c */ #include #include #include static int ok(SQLRETURN rc) { return rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO; } int main(void) { SQLHENV env = SQL_NULL_HENV; SQLHDBC dbc = SQL_NULL_HDBC; SQLHSTMT stmt = SQL_NULL_HSTMT; SQLBIGINT success = 0, failure = 0; SQLCHAR connection[] = "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER;CONNTYPE=1"; if (!ok(SQLAllocEnv(&env)) || !ok(SQLAllocConnect(env, &dbc)) || !ok(SQLDriverConnect(dbc, NULL, connection, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT)) || !ok(SQLAllocStmt(dbc, &stmt))) return 1; SQLCHAR *fixed[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A[0]", (SQLCHAR*)"A[3]", NULL}; SQL_APPEND_PARAM row[3] = {0}; row[0].mLong = 1; row[1].mInteger = 10; row[2].mInteger = 40; if (!ok(SQLAppendOpenColumns(stmt, (SQLCHAR*)"ARRAY_APPEND_EXAMPLE", fixed, 0))) return 2; if (!ok(SQLAppendDataV3(stmt, row, 3))) { SQLAppendClose(stmt, &success, &failure); return 2; } if (!ok(SQLAppendClose(stmt, &success, &failure)) || success != 1 || failure != 0) return 2; SQLUSMALLINT positions[2] = {1, 3}; SQLINTEGER values[2] = {200, 400}; SQLLEN indicators[2] = {0, 0}; SQL_MACHBASE_SPARSE_ARRAY_DESC sparse = {0}; sparse.struct_size = sizeof(sparse); sparse.element_c_type = SQL_C_SLONG; sparse.cardinality = 4; sparse.entry_count = 2; sparse.positions = positions; sparse.values = values; sparse.value_stride = sizeof(values[0]); sparse.element_indicators = indicators; SQLCHAR *whole[] = {(SQLCHAR*)"ID", (SQLCHAR*)"A", NULL}; memset(row, 0, sizeof(row)); row[0].mLong = 2; row[1].mVar.mData = &sparse; row[1].mVar.mLength = SQL_APPEND_SPARSE_ARRAY_DESC_LENGTH; if (!ok(SQLAppendOpenColumns(stmt, (SQLCHAR*)"ARRAY_APPEND_EXAMPLE", whole, 0))) return 3; if (!ok(SQLAppendDataV3(stmt, row, 2))) { SQLAppendClose(stmt, &success, &failure); return 3; } sparse.entry_count = 0; row[0].mLong = 3; if (!ok(SQLAppendDataV3(stmt, row, 2))) { SQLAppendClose(stmt, &success, &failure); return 3; } row[0].mLong = 4; row[1].mVar.mData = NULL; row[1].mVar.mLength = 0; if (!ok(SQLAppendDataV3(stmt, row, 2))) { SQLAppendClose(stmt, &success, &failure); return 3; } success = 0; failure = 0; if (!ok(SQLAppendClose(stmt, &success, &failure)) || success != 3 || failure != 0) return 3; SQLFreeStmt(stmt, SQL_DROP); SQLDisconnect(dbc); SQLFreeConnect(dbc); SQLFreeEnv(env); puts("ODBC sparse append OK"); return 0; } ``` ```bash cc sparse_odbc.c -I/opt/machbase/include -L/opt/machbase/lib \ -lmachbasecli_dll -lm -ldl -lrt -pthread -o sparse_odbc LD_LIBRARY_PATH=/opt/machbase/lib ./sparse_odbc ``` {{< callout type="warning" >}} 汎用ODBC Driver Managerが作成した文ハンドルと直接のSQLCLI拡張ではハンドルABIが異なるため、 混用しないでください。選択列AppendにはMachbaseドライバー拡張と直接のドライバーハンドルを使用する 必要があります。汎用ODBC APIにはAppend Openの選択対象はありません。 {{< /callout >}} ## JDBC ### 通常OpenでスパースARRAYを入力 `executeAppendOpen(table, errorCheckCount)`オーバーロードを使用します。返されたメタデータに合わせて `ID`と`MachSparseArray`を渡し、通常の実習テーブルの自動時刻は直接入力しません。 `null`は全体NULL、空の`MachSparseArray`は全要素がNULLの配列です。 `SparseAppendFull.java`として保存し、ARRAY機能を含むJDBC JARで実行します。 ```java import com.machbase.jdbc.MachConnection; import com.machbase.jdbc.MachSparseArray; import com.machbase.jdbc.MachStatement; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class SparseAppendFull { public static void main(String[] args) throws Exception { try (MachConnection con = (MachConnection)DriverManager.getConnection( "jdbc:machbase://127.0.0.1:5656/machbasedb", "SYS", "MANAGER"); MachStatement st = (MachStatement)con.createStatement()) { Map entries = new HashMap(); entries.put(0, 10); entries.put(3, 40); MachSparseArray sparse = con.createSparseArrayOf("INT32", 4, entries); try (ResultSet opened = st.executeAppendOpen("ARRAY_APPEND_FULL_EXAMPLE", 0)) { try { ResultSetMetaData meta = opened.getMetaData(); for (int id = 1; id <= 4; id++) { if (id == 2) sparse.clear().set(1, 200).set(3, 400); if (id == 3) sparse.clear(); ArrayList row = new ArrayList(); row.add(Long.valueOf(id)); row.add(id == 4 ? null : sparse); st.executeAppendData(meta, row); } } finally { st.executeAppendClose(); } } try (ResultSet rs = st.executeQuery( "SELECT ID,A,ARRAY_LENGTH(A) " + "FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID")) { int count = 0; while (rs.next()) { System.out.println(rs.getLong(1) + " " + rs.getString(2)); count++; } if (count != 4) throw new IllegalStateException("Expected 4 rows"); } } } } ``` ```bash javac -cp "$MACHBASE_JDBC_JAR" SparseAppendFull.java java -cp ".:$MACHBASE_JDBC_JAR" SparseAppendFull ``` `MACHBASE_JDBC_JAR`には使用するJDBC JARの実際のパスを設定します。上記のクラスパス区切り文字は Linux用です。エラーなく4行が検索されることを確認し、[共通の期待値](#結果の確認)と比較します。 ### 選択列Openで入力 既存の`executeAppendOpen(String, int)`は全行APIとして維持されます。 次のオーバーロードで選択対象を指定します。 ```java ResultSet executeAppendOpen(String tableName, String[] inputColumns, int errorCheckCount) ``` ```java import com.machbase.jdbc.MachConnection; import com.machbase.jdbc.MachSparseArray; import com.machbase.jdbc.MachStatement; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class SparseAppend { static void append(MachStatement st, String[] columns, Object[][] values) throws Exception { try (ResultSet metaResult = st.executeAppendOpen( "ARRAY_APPEND_EXAMPLE", columns, 0)) { ResultSetMetaData meta = metaResult.getMetaData(); try { for (Object[] value : values) { ArrayList row = new ArrayList(); for (Object item : value) row.add(item); st.executeAppendData(meta, row); } } finally { st.executeAppendClose(); } } } public static void main(String[] args) throws Exception { Class.forName("com.machbase.jdbc.MachDriver"); MachConnection con = (MachConnection)DriverManager.getConnection( "jdbc:machbase://127.0.0.1:5656/machbasedb", "SYS", "MANAGER"); try { try (MachStatement st = (MachStatement)con.createStatement()) { append(st, new String[] {"ID", "A[0]", "A[3]"}, new Object[][] {{1L, 10, 40}}); Map entries = new HashMap(); entries.put(1, 200); entries.put(3, 400); MachSparseArray sparse = con.createSparseArrayOf( "INT32", 4, entries); MachSparseArray empty = con.createSparseArrayOf( "INT32", 4, new HashMap()); append(st, new String[] {"ID", "A"}, new Object[][] { {2L, sparse}, {3L, empty}, {4L, null} }); try (ResultSet rs = st.executeQuery( "SELECT ID,A,ARRAY_LENGTH(A) " + "FROM ARRAY_APPEND_EXAMPLE ORDER BY ID")) { while (rs.next()) System.out.println( rs.getLong(1) + " " + rs.getString(2)); } } } finally { con.close(); } } } ``` `createSparseArrayOf()`に渡すmapのキーは0始まりの要素位置です。`MachSparseArray.clear()`と `set()`で同じオブジェクトを再利用できます。空のmapは全要素がNULLのARRAY、Javaの`null`は 配列全体のNULLです。 ## Python DB-API ### 列リストなしでスパースARRAYを入力 DB-APIの`append()`は内部でOpen・入力・Closeを処理します。`columns=`を省略し、各行に`ID`と `SparseArray`を渡します。通常の実習テーブルを先に準備し、次のコードを`sparse_append_full.py`として 保存して実行します。 ```python from machbaseAPI import SparseArray, connect conn = connect(host="127.0.0.1", port=5656, user="SYS", password="MANAGER") try: first = SparseArray(4).set(0, 10).set(3, 40) second = SparseArray(4).set(1, 200).set(3, 400) empty = SparseArray(4) conn.append("ARRAY_APPEND_FULL_EXAMPLE", [ [1, first], [2, second], [3, empty], [4, None], ]) rows = conn.cursor(dictionary=False).execute( "SELECT ID,A,ARRAY_LENGTH(A) " "FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID" ).fetchall() expected = [ (1, [10, None, None, 40], 4), (2, [None, 200, None, 400], 4), (3, [None, None, None, None], 4), (4, None, None), ] assert rows == expected, rows print("Python full-row sparse append OK") finally: conn.close() ``` ```bash python3 sparse_append_full.py ``` 検索結果が期待値と一致すると`Python full-row sparse append OK`を出力します。 ### 選択列を指定して入力 既存の`append(table, rows)`は維持され、`columns=`キーワードで選択対象を指定します。 ```python from machbaseAPI import SparseArray, connect def main(): conn = connect(host="127.0.0.1", port=5656, user="SYS", password="MANAGER", database="MACHBASEDB") try: conn.append( "ARRAY_APPEND_EXAMPLE", [[1, 10, 40]], columns=["ID", "A[0]", "A[3]"], ) sparse = SparseArray(4).set(1, 200).set(3, 400) empty = SparseArray(4) conn.append( "ARRAY_APPEND_EXAMPLE", [[2, sparse], [3, empty], [4, None]], columns=["ID", "A"], ) rows = conn.cursor(dictionary=False).execute( "SELECT ID,A,ARRAY_LENGTH(A) " "FROM ARRAY_APPEND_EXAMPLE ORDER BY ID" ).fetchall() expected = [ (1, [10, None, None, 40], 4), (2, [None, 200, None, 400], 4), (3, [None, None, None, None], 4), (4, None, None), ] assert rows == expected, rows print("Python sparse append OK") finally: conn.close() if __name__ == "__main__": main() ``` `SparseArray.clear()`は要素数を維持したまま全要素をNULLに戻します。 ### Python legacyラッパー #### 通常のappendOpenで入力 `appendOpen(table)`で開いて`appendData()`を使用します。スパース配列の作成に `appendOpenColumns()`の呼び出しは不要です。通常の実習テーブルを準備し、 `sparse_append_full_legacy.py`として保存して実行します。 ```python from machbaseAPI import SparseArray, machbase db = machbase() if db.open("127.0.0.1", "SYS", "MANAGER", 5656) != 1: raise RuntimeError(db.result()) try: if db.appendOpen("ARRAY_APPEND_FULL_EXAMPLE") != 1: raise RuntimeError(db.result()) try: sparse = SparseArray(4).set(0, 10).set(3, 40) for row_id in range(1, 5): if row_id == 2: sparse.clear().set(1, 200).set(3, 400) if row_id == 3: sparse.clear() row = [row_id, None if row_id == 4 else sparse] if db.appendData("ARRAY_APPEND_FULL_EXAMPLE", None, row) != 1: raise RuntimeError(db.result()) finally: if db.appendClose() != 1: raise RuntimeError(db.result()) if db.select( "SELECT ID,A,ARRAY_LENGTH(A) " "FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID" ) != 1: raise RuntimeError(db.result()) print(db.result()) finally: db.close() ``` ```bash python3 sparse_append_full_legacy.py ``` `db.result()`の検索結果を[共通の期待値](#結果の確認)と比較します。 #### 選択列Openで入力 既存の`appendOpen(table, types=None)`は全行APIとして維持されます。選択対象には `appendOpenColumns(table, columns, types=None)`を使用します。 ```python from machbaseAPI import SparseArray, machbase db = machbase() if db.open("127.0.0.1", "SYS", "MANAGER", 5656) != 1: raise RuntimeError(db.result()) try: if db.appendOpenColumns( "ARRAY_APPEND_EXAMPLE", ["ID", "A[0]", "A[3]"] ) != 1: raise RuntimeError(db.result()) try: if db.appendData( "ARRAY_APPEND_EXAMPLE", None, [1, 10, 40] ) != 1: raise RuntimeError(db.result()) finally: if db.appendClose() != 1: raise RuntimeError(db.result()) sparse = SparseArray(4).set(1, 200).set(3, 400) empty = SparseArray(4) if db.appendOpenColumns( "ARRAY_APPEND_EXAMPLE", ["ID", "A"] ) != 1: raise RuntimeError(db.result()) try: for row in ([2, sparse], [3, empty], [4, None]): if db.appendData("ARRAY_APPEND_EXAMPLE", None, row) != 1: raise RuntimeError(db.result()) finally: if db.appendClose() != 1: raise RuntimeError(db.result()) finally: db.close() ``` `appendData()`の値の数と順序は、開いた対象リストに従います。 新規コードでは、より簡潔なDB-APIの`append(..., columns=...)`を推奨します。 ## Node.js ### 全列の定義でスパースARRAYを入力 Node.jsも`appendOpen()`でスパース配列を入力します。ただし現在の`@machbase/ts-client`では `appendOpen(table, columns, options?)`の`columns`は必須です。別の`OpenColumns`メソッドはなく、 全体入力と選択入力を同じメソッドで表します。 次の例は通常の実習テーブルの2つの入力列`ID`、`A`を順に定義します。`A[0]`などの要素対象をOpenに 指定せず、各行の`SparseArray`が位置を決めます。`sparse_append_full.js`として保存し、 ARRAY機能を含むパッケージを使用するプロジェクトで実行します。 ```javascript 'use strict'; const { createConnection, SparseArray } = require('@machbase/ts-client'); (async () => { const conn = createConnection({ host: '127.0.0.1', port: 5656, user: 'SYS', password: 'MANAGER', }); await conn.connect(); try { const stream = await conn.appendOpen('ARRAY_APPEND_FULL_EXAMPLE', [ { name: 'ID', type: 'int64' }, { name: 'A', type: 'int32-array' }, ]); try { await stream.append([ [1n, new SparseArray(4).set(0, 10).set(3, 40)], [2n, new SparseArray(4).set(1, 200).set(3, 400)], [3n, new SparseArray(4)], [4n, null], ]); } finally { await stream.close(); } const [rows] = await conn.query( 'SELECT ID,A,ARRAY_LENGTH(A) LEN ' + 'FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID', ); if (rows.length !== 4) throw new Error('Expected 4 rows'); console.log(rows); } finally { await conn.end(); } })().catch(error => { console.error(error); process.exitCode = 1; }); ``` ```bash node sparse_append_full.js ``` 4行が検索されることを確認して[共通の期待値](#結果の確認)と比較します。 列定義なしの`appendOpen(table)`や`[]`を渡して自動推論する方式はサポートしません。 ### 選択列・要素を定義して入力 `AppendColumnDefinition.name`に、列全体または要素位置を指定した対象を設定します。 ```javascript 'use strict'; const { createConnection, SparseArray } = require('@machbase/ts-client'); async function appendRows(connection, columns, rows) { const appender = await connection.appendOpen('ARRAY_APPEND_EXAMPLE', columns); try { await appender.append(rows); } finally { await appender.close(); } } (async () => { const connection = createConnection({ host: '127.0.0.1', port: 5656, user: 'SYS', password: 'MANAGER', }); await connection.connect(); try { await appendRows(connection, [ { name: 'ID', type: 'int64' }, { name: 'A[0]', type: 'int32' }, { name: 'A[3]', type: 'int32' }, ], [[1n, 10, 40]]); const sparse = new SparseArray(4).set(1, 200).set(3, 400); const empty = new SparseArray(4); await appendRows(connection, [ { name: 'ID', type: 'int64' }, { name: 'A', type: 'int32-array' }, ], [[2n, sparse], [3n, empty], [4n, null]]); const [rows] = await connection.query( 'SELECT ID,A,ARRAY_LENGTH(A) LEN ' + 'FROM ARRAY_APPEND_EXAMPLE ORDER BY ID', ); console.log(rows); } finally { await connection.end(); } })().catch((error) => { console.error(error.stack || error); process.exitCode = 1; }); ``` `MACHBASE_NATIVE_APPEND=0`でprepared代替経路を選択した場合も、`SparseArray`をARRAY互換値として 処理します。 ## .NET full/legacyプロバイダー ### 通常のAppendOpenでスパースARRAYを入力 `AppendOpen(table)`で開き、`AppendData()`に`MachSparseArray`を渡します。 通常の実習テーブルを先に準備します。次のコードは、ARRAY機能を含むfull/legacyプロバイダーを参照する C#プロジェクトの`Program.cs`として使用します。 ```csharp using System; using System.Collections.Generic; using Mach.Data.MachClient; public class SparseAppendFull { public static void Main() { using var conn = new MachConnection( "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER"); conn.Open(); using var command = new MachCommand(conn); var writer = command.AppendOpen("ARRAY_APPEND_FULL_EXAMPLE"); try { var first = new MachSparseArray(MachDBType.INT32_ARRAY, 4) .Set(0, 10).Set(3, 40); var second = new MachSparseArray(MachDBType.INT32_ARRAY, 4) .Set(1, 200).Set(3, 400); var empty = new MachSparseArray(MachDBType.INT32_ARRAY, 4); var rows = new List> { new List { 1L, first }, new List { 2L, second }, new List { 3L, empty }, new List { 4L, DBNull.Value }, }; foreach (var row in rows) command.AppendData(writer, row); } finally { if (command.IsAppendOpened) command.AppendClose(writer); } if (writer.FailureCount != 0) throw new InvalidOperationException("APPEND row failure"); using var verify = new MachCommand( "SELECT ID,A,ARRAY_LENGTH(A) FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID", conn); using var reader = verify.ExecuteReader(); int count = 0; while (reader.Read()) { Console.WriteLine(reader.IsDBNull(1) ? $"{reader.GetInt64(0)} NULL" : $"{reader.GetInt64(0)} " + string.Join(",", (object[])reader.GetValue(1))); count++; } if (count != 4) throw new InvalidOperationException("Expected 4 rows"); } } ``` 次のプロジェクトファイルを`Program.cs`と同じディレクトリに`SparseAppendFull.csproj`として保存します。 この例は.NET 8用プロバイダーを使用します。 ```xml Exe net8.0 false $(MachbaseProviderDll) ``` 以下のパスを、ARRAY機能を含む.NET 8プロバイダーDLLの実際のパスに置き換えます。 ```bash dotnet build SparseAppendFull.csproj -p:MachbaseProviderDll=/absolute/path/to/provider.dll dotnet bin/Debug/net8.0/SparseAppendFull.dll ``` Closeの失敗件数が0で検索結果が4行であることを確認し、[共通の期待値](#結果の確認)と比較します。 ### 選択列Openで入力 full APIと既存互換のMachConnector40は、選択対象を受け取るオーバーロードを提供します。 既存の`AppendOpen(string)`とerror-checkオーバーロードは維持されます。 ```csharp MachAppendWriter AppendOpen(string tableName, IList inputColumns); MachAppendWriter AppendOpen(string tableName, IList inputColumns, int errorCheckCount, MachAppendOption option); ``` ```csharp using System; using System.Collections.Generic; using Mach.Data.MachClient; static void Append(MachConnection connection, IList columns, IList> rows) { using var command = new MachCommand(connection); var writer = command.AppendOpen("ARRAY_APPEND_EXAMPLE", columns); try { foreach (var row in rows) command.AppendData(writer, row); } finally { if (command.IsAppendOpened) command.AppendClose(writer); } if (writer.FailureCount != 0) throw new InvalidOperationException("APPEND row failure"); } using var connection = new MachConnection( "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER"); connection.Open(); Append(connection, new List { "ID", "A[0]", "A[3]" }, new List> { new List { 1L, 10, 40 } }); var sparse = new MachSparseArray(MachDBType.INT32_ARRAY, 4) .Set(1, 200).Set(3, 400); var empty = new MachSparseArray(MachDBType.INT32_ARRAY, 4); Append(connection, new List { "ID", "A" }, new List> { new List { 2L, sparse }, new List { 3L, empty }, new List { 4L, DBNull.Value }, }); using var verify = new MachCommand( "SELECT ID,A,ARRAY_LENGTH(A) FROM ARRAY_APPEND_EXAMPLE ORDER BY ID", connection); using var reader = verify.ExecuteReader(); while (reader.Read()) Console.WriteLine(reader.IsDBNull(1) ? $"{reader.GetInt64(0)} NULL" : $"{reader.GetInt64(0)} " + string.Join(",", (object[])reader.GetValue(1))); ``` `MachSparseArray.Clear()`はオブジェクトを、全要素がNULLで再利用可能な状態に戻します。 配列全体のNULLは`DBNull.Value`です。Append Open成功後にメタデータ処理が失敗した場合は、 プロバイダーが開いたハンドルを解放し、接続は再利用できます。 ## Go neo-client ### 列引数なしのConnectで入力 `Appender.Connect(ctx, dsn, table)`の列引数を省略し、`Append(id, sparse)`で入力します。 この例のLOG入力では`_arrival_time`は直接渡しません。`*api.Array`のnilは全体NULLであり、 空のスパースオブジェクトとは区別します。 以下のコードには、要素位置が0始まりのARRAY機能を含む`neo-client/v2`ソースが必要です。 そのソースを`go.work`または`replace`で接続したGoモジュールに`sparse_append_full.go`として保存します。 接続するソースは以下の選択例と同じバージョン条件に従います。 ```go package main import ( "context" "database/sql" "errors" "fmt" client "github.com/machbase/neo-client/v2" "github.com/machbase/neo-client/v2/api" ) func appendFull(ctx context.Context, dsn string) error { first, err := api.NewSparseArray(api.SqlTypeInt32, 4) if err != nil { return err } if err = first.Set(0, int32(10)); err != nil { return err } if err = first.Set(3, int32(40)); err != nil { return err } second, err := api.NewSparseArray(api.SqlTypeInt32, 4) if err != nil { return err } if err = second.Set(1, int32(200)); err != nil { return err } if err = second.Set(3, int32(400)); err != nil { return err } empty, err := api.NewSparseArray(api.SqlTypeInt32, 4) if err != nil { return err } var wholeNull *api.Array appender := &client.Appender{} if err = appender.Connect(ctx, dsn, "ARRAY_APPEND_FULL_EXAMPLE"); err != nil { return err } for _, row := range [][]any{ {int64(1), first}, {int64(2), second}, {int64(3), empty}, {int64(4), wholeNull}, } { if err = appender.Append(row...); err != nil { _, _, closeErr := appender.Close() return errors.Join(err, closeErr) } } success, failure, err := appender.Close() if err != nil { return err } if success != 4 || failure != 0 { return fmt.Errorf("success=%d failure=%d", success, failure) } return nil } func main() { ctx := context.Background() dsn := "server=tcp://sys:manager@127.0.0.1:5656" if err := appendFull(ctx, dsn); err != nil { panic(err) } db, err := sql.Open(client.DefaultDriverName, dsn) if err != nil { panic(err) } defer db.Close() rows, err := db.QueryContext(ctx, "SELECT ID,A,ARRAY_LENGTH(A) FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID") if err != nil { panic(err) } defer rows.Close() count := 0 for rows.Next() { var id int64 var value sql.NullString var length sql.NullInt64 if err = rows.Scan(&id, &value, &length); err != nil { panic(err) } if value.Valid { fmt.Println(id, value.String, length.Int64) } else { fmt.Println(id, "NULL") } count++ } if err = rows.Err(); err != nil { panic(err) } if count != 4 { panic("Expected 4 rows") } } ``` ```bash go run sparse_append_full.go ``` Closeの成功4件・失敗0件と検索結果を確認します。 ### 選択列Connectで入力 この例はMachbase Neoサーバー経由ではなく、`neo-client`がMachbase DBMSに直接接続する経路です。 要素位置が0始まりのARRAYと選択列Append APIは [`neo-client` PR #17](https://github.com/machbase/neo-client/pull/17)以降のv2モジュールのソースに 含まれます。公開v2リリースが指定されるまでは、公開モジュールのバージョンに同じ機能が含まれると 考えないでください。 ```go package main import ( "context" "database/sql" "errors" "fmt" client "github.com/machbase/neo-client/v2" "github.com/machbase/neo-client/v2/api" ) func appendRows(ctx context.Context, dsn, table string, columns []string, rows [][]any) error { appender := &client.Appender{} if err := appender.Connect(ctx, dsn, table, columns...); err != nil { return err } for _, row := range rows { if err := appender.Append(row...); err != nil { _, _, closeErr := appender.Close() return errors.Join(err, closeErr) } } success, failure, err := appender.Close() if err != nil { return err } if failure != 0 { return fmt.Errorf("append success=%d failure=%d", success, failure) } return nil } func main() { ctx := context.Background() dsn := "server=tcp://sys:manager@127.0.0.1:5656" db, err := sql.Open(client.DefaultDriverName, dsn) if err != nil { panic(err) } defer db.Close() if err := db.PingContext(ctx); err != nil { panic(err) } if err := appendRows(ctx, dsn, "ARRAY_APPEND_EXAMPLE", []string{"ID", "A[0]", "A[3]"}, [][]any{{int64(1), int32(10), int32(40)}}); err != nil { panic(err) } sparse, err := api.NewSparseArray(api.SqlTypeInt32, 4) if err != nil { panic(err) } if err := sparse.Set(1, int32(200)); err != nil { panic(err) } if err := sparse.Set(3, int32(400)); err != nil { panic(err) } empty, err := api.NewSparseArray(api.SqlTypeInt32, 4) if err != nil { panic(err) } var wholeNull *api.Array if err := appendRows(ctx, dsn, "ARRAY_APPEND_EXAMPLE", []string{"ID", "A"}, [][]any{ {int64(2), sparse}, {int64(3), empty}, {int64(4), wholeNull}, }); err != nil { panic(err) } rows, err := db.QueryContext(ctx, "SELECT ID,A,ARRAY_LENGTH(A) FROM ARRAY_APPEND_EXAMPLE ORDER BY ID") if err != nil { panic(err) } defer rows.Close() for rows.Next() { var id int64 var value sql.NullString var length sql.NullInt64 if err := rows.Scan(&id, &value, &length); err != nil { panic(err) } if !value.Valid { fmt.Println(id, "NULL"); continue } fmt.Println(id, value.String, length.Int64) } if err := rows.Err(); err != nil { panic(err) } } ``` `Appender.Connect(ctx, dsn, table, columns...)`の可変長引数が選択対象です。 `WithInputColumns(columns...)`を使用する場合は`Connect()`より前に適用します。 1つの`Appender`で`Append`、`Flush`、`Close`を同時に呼び出さないでください。 ## 結果の確認 通常の例の実行後、次のクエリで値、全体NULL、要素NULLを確認します。 ```sql SELECT ID, A, ARRAY_LENGTH(A), A[0], A[1], A[2], A[3] FROM ARRAY_APPEND_FULL_EXAMPLE ORDER BY ID; ``` 選択の例の実行後は次のクエリを使用します。両テーブルの期待値は同じです。 ```sql SELECT ID, A, ARRAY_LENGTH(A), A[0], A[1], A[2], A[3] FROM ARRAY_APPEND_EXAMPLE ORDER BY ID; ``` | ID | A | `ARRAY_LENGTH(A)` | |---:|---|---:| | 1 | `[10,null,null,40]` | 4 | | 2 | `[null,200,null,400]` | 4 | | 3 | `[null,null,null,null]` | 4 | | 4 | `NULL` | `NULL` | 各SDKの例を同じテーブルに連続して実行するとIDが重複します。実際の検証では例ごとにテーブルを 空にするか、異なるID範囲を使用します。 ## 実習の後片付け 検索結果の確認後、今回作成した実習テーブルだけを削除します。両方の例を実行した場合は次の2文を使用し、 片方だけなら該当テーブルだけを削除します。 ```sql DROP TABLE ARRAY_APPEND_FULL_EXAMPLE; DROP TABLE ARRAY_APPEND_EXAMPLE; ``` 各文はテーブルとデータをまとめて削除します。同名の既存業務テーブルには適用しないでください。 再実行時は準備SQLから進めます。 ## バージョンと制限事項 - `ARRAY`と選択列AppendはMachbase DBMS 8.7.0の機能です。 - ARRAYの公開要素位置は0から始まります。以前の開発バージョンで位置を1から指定していたスパースARRAYと 選択対象の呼び出しは、位置を1ずつ減らす必要があります。JDBCのパラメーター番号など、別途1始まりの 標準APIまで変更しないでください。 - Machbase DBMS 8.7.0サーバーとARRAY機能を含むSDKビルドを合わせて使用します。 - 既存の全行Append Open関数・メソッドのシグネチャーと意味は維持されます。 - C APIの列名リストはNULL終端配列であり、件数は別途受け取りません。 - 不正な要素数、重複・範囲外の位置、重複対象、全体・要素対象の衝突、値の数の不一致はエラーです。 - Go ARRAY APIは正式なモジュールリリースまで、機能を含む開発ソースを接続する必要があります。 - SDKは失敗行を成功件数に含めてはいけません。 --- title: "12. 性能チューニング" url: https://docs.machbase.com/ja/dbms/performance-tuning/ language: ja kind: section --- # 12. 性能チューニング 性能問題は、データモデル、入力経路、クエリ実行計画、メモリ、ストレージの順に診断・調整します。 設定を変える前にボトルネックと再現条件を確認し、変更前後を同じワークロードで測定します。 ## 推奨する診断順序 1. 対象クエリと入力処理の遅延、スループット、エラー率を記録します。 2. データ特性とテーブルタイプが一致するか確認します。 3. `EXPLAIN`、`V$STMT`、`V$SESSION` で実行状態を確認します。 4. インデックス、バッチサイズ、キャッシュ、ストレージ設定を1項目ずつ調整します。 5. 同じデータとワークロードで効果を再測定します。 ## この章の構成 | 順序 | 節 | 内容 | |-----:|------|------| | 12.1 | [性能問題へのアプローチ](./performance-approach/) | 基準値、ボトルネック分類、実行計画、システムビュー | | 12.2 | [モデリングの性能調整](./performance-tuning-modeling/) | テーブルタイプとスキーマ設計の確認 | | 12.3 | [インデックスのチューニング](./index-tuning/) | タイプ別のインデックス選択と書き込みコスト | | 12.5 | [クエリと分析の性能調整](./performance-query-tuning/) | 時間条件、実行計画、ROLLUP、ウィンドウ関数 | | 12.6 | [キャッシュとメモリのチューニング](/ja/dbms/performance-tuning/cache-tuning-memory/) | PVO Cache、Min-Max Cache、メモリ使用量 | | 12.7 | [ストレージと Cluster のチューニング](./tuning-storage-cluster/) | ディスク I/O、チェックポイント、Cluster 構成 | スループットと応答時間は、ハードウェア、データ分布、スキーマ、インデックス、同時利用者数に依存します。 設定例は出発点として使い、運用ワークロードで検証してください。 --- title: "12.1 性能問題へのアプローチ" url: https://docs.machbase.com/ja/dbms/performance-tuning/performance-approach/ language: ja kind: page --- # 12.1 性能問題へのアプローチ 再現条件と基準値を確保してからボトルネックを絞り込みます。根拠なく複数の設定やインデックスを 同時に変更すると、原因と効果を区別できません。 ## 1. 再現条件の記録 - 遅くなった SQL または入力経路 - 開始・終了時刻とデータベース・ユーザー - 対象テーブル、時間範囲、行数、結果件数 - 同時セッション・クエリ・Appender 数 - 正常時と問題時の遅延・スループット - 直前のデプロイ、スキーマ、設定、データ分布の変更 ## 2. リソースのボトルネック確認 ```bash iostat -x 1 5 top -b -n 1 free -h ``` CPU・I/O・メモリは固定しきい値ではなく正常時の基準値と比較します。短時間の急増と継続的な飽和を 区別し、OS 指標の時刻をサーバートレースやクエリの時刻と合わせます。 ## 3. 実行中の処理確認 ```sql SELECT sess_id, id AS stmt_id, state, record_size, query FROM V$STMT ORDER BY sess_id, id; SELECT id, user_name, user_ip, login_time, client_type FROM V$SESSION ORDER BY login_time DESC; ``` 長時間実行の文、異常に増えたセッション、同じクエリの同時実行を探します。システムビューの列は 使用中のバージョンで `DESC` により確認します。 ## 4. 実行計画と範囲の確認 遅い SELECT は `EXPLAIN` でテーブル、スキャン方式、キー範囲、フィルター、結合を確認します。 TAG・LOG に時間条件があるか、関数や型変換がインデックス範囲の利用を妨げていないかを調べます。 詳細は[クエリと分析の性能調整](../performance-query-tuning/)を参照してください。 ## 5. 1項目変更して再測定 クエリ、インデックス、バッチ、同時実行、キャッシュ・設定の順に候補を絞ります。 1項目ずつ変更し、同じ再現条件で次を比較します。 | 項目 | 比較対象 | |------|--------| | クエリ | 応答時間の分布、結果行、実行計画 | | 入力 | rows/s、サーバー処理応答の遅延、失敗件数 | | サーバー | CPU、I/O、メモリ、セッション | | 副作用 | 他のクエリの遅延、入力性能低下、再起動への影響 | 効果がない、または副作用が大きい場合は、記録した以前の値に戻します。スキーマやストレージ構造の 変更は最後の手段として検討し、先に検証環境と復旧手順を準備します。 ## 最終診断チェックリスト - 現在の処理とセッションを正常時の基準値と比較したか。 - 実際の SQL と時間範囲で実行計画を確認したか。 - インデックス・ROLLUP 変更による入力コストを確認したか。 - OS とサーバー指標の時刻を対象処理に合わせたか。 - 設定・スキーマを1項目ずつ変更したか。 - 復元用の値と再測定結果を記録したか。 --- title: "12.2 モデリングの性能調整" url: https://docs.machbase.com/ja/dbms/performance-tuning/performance-tuning-modeling/ language: ja kind: page --- # 12.2 モデリングの性能調整 モデリングでは、データのライフサイクル、検索キー、変更方法に適したテーブルタイプとスキーマを選びます。 不適切なテーブルタイプを、設定やインデックスだけで補おうとしないでください。 ## テーブルタイプの選択 | データ | 最初に検討 | |--------|-----------| | 名前・時刻・数値が中心の時系列 | TAG | | 追記型イベント・ログ | LOG | | リレーショナルな変更とトランザクション | TRANSACTION | | 小規模で永続的な参照データ | LOOKUP | | 再生成できるインメモリキャッシュ | VOLATILE | ## スキーマ設計基準 - クエリと入力に実際に必要な列だけを定義します。 - 文字列長は観測した最大値と増加の可能性で決めます。 - 時刻、数値、IP は文字列ではなく適切な SQL 型で保存します。 - TAG メタデータには、タグについて比較的安定した属性を置きます。 - NULL 許可とデフォルト値を業務上の意味に合わせます。 - リレーショナルキーでは、自然キーとサロゲートキーの寿命と変更可能性を比較します。 文字列長に一律の余裕率を適用しないでください。現在の分布と上限、切り詰め時の影響を測定し、 スキーマ変更手順を準備します。 ## インデックスと集計 条件式と結合キーを基準にインデックス候補を選びます。読み出し改善だけでなく、入力遅延、 保存領域、メモリも測定します。繰り返す TAG 時間集計には ROLLUP を検討し、 ほとんど参照しない集計単位を無制限に作らないでください。 ## 検証順序 1. 代表データとクエリを準備します。 2. 選択したタイプと最小スキーマで基準値を測定します。 3. インデックスまたは ROLLUP を1つ追加します。 4. 読み書き、メモリ、ストレージを再測定します。 5. 維持する価値のない構造は削除します。 詳細な設計は[テーブルタイプの概念と選択](/ja/dbms/data-modeling-table-design/)を参照してください。 --- title: "12.3 インデックスのチューニング" url: https://docs.machbase.com/ja/dbms/performance-tuning/index-tuning/ language: ja kind: page --- # 12.3 インデックスのチューニング インデックスは、実際の条件式や結合キーの読み出しコストを下げる場合だけ追加します。 作成前後のクエリ遅延、入力スループット、メモリ、ストレージを併せて測定します。 ## テーブル別の確認 | テーブルタイプ | 主キー・アクセス経路 | 追加インデックス | |------------|--------------------|------------| | TAG | 名前と BASETIME に基づくアクセス | 対応する値・メタデータのインデックス | | LOG | `_ARRIVAL_TIME` 範囲 | LSM, BITMAP, KEYWORD | | LOOKUP | PRIMARY KEY | 対応するセカンダリインデックス | | VOLATILE | 任意の PRIMARY KEY | REDBLACK セカンダリインデックス | | TRANSACTION | PRIMARY KEY | リレーショナルなセカンダリインデックス | 対応タイプと構文は、各テーブルの章と[インデックス構文](/ja/dbms/reference/sql/syntax/index-syntax/)を確認します。 ## 適用手順 1. 遅い SQL の `EXPLAIN` と結果件数を記録します。 2. 条件の選択性と値の分布を確認します。 3. 同じ先頭列を持つインデックスがすでにないか確認します。 4. 候補を1つ作成し、構築完了を確認します。 5. 同じ条件でクエリと入力を再測定します。 6. 効果がない、または書き込みコストが大きいインデックスは削除します。 ```sql SHOW INDEXES; SHOW INDEXGAP; ``` インデックス数に対して固定のスループット低下率を当てはめないでください。行サイズ、キー分布、 同時実行、ストレージによって変わるため、運用に近いデータで測定します。 ## 注意事項 - 選択性の低い列を索引化する前にスキャンと比較します。 - インデックス列への関数・型変換でキー範囲を使えなくしていないか確認します。 - 複合インデックスは、頻出する条件の組み合わせと先頭列を基準に設計します。 - 構築中は入力・クエリ負荷と `SHOW INDEXGAP` を監視します。 - 未使用インデックスを削除する前に、ピーク負荷やバッチ処理でも不要か確認します。 詳細は TAG、LOG、LOOKUP、VOLATILE、TRANSACTION 各章の「インデックスと性能」を参照してください。 --- title: "12.4 入力性能のチューニング" url: https://docs.machbase.com/ja/dbms/performance-tuning/performance-tuning/ language: ja kind: page --- # 12.4 入力性能のチューニング 入力性能は、経路、行サイズ、バッチ、同時実行、インデックス、ストレージの影響を受けます。 代表データで経路全体のスループットとサーバー処理応答の遅延を測定して調整します。 ## 入力経路の選択 入力経路と SDK・テーブルタイプ別の対応は [データの入力とエクスポート](/ja/dbms/development-tools-integration/data-input-load-export/)で選択します。 このページでは、選択した経路のスループットと遅延を調整します。 ## 測定順序 1. 実際に近いスキーマ、行サイズ、インデックスを準備します。 2. 1接続と小さいバッチで基準値を測定します。 3. バッチサイズを段階的に増やし、rows/s と flush・サーバー処理応答の遅延を記録します。 4. クライアントの CPU・メモリと、サーバーの CPU・I/O・メモリを併せて監視します。 5. 接続数を増やし、全体のスループットと p95・p99 応答時間を比較します。p99 は要求の99%が その時間内に完了する遅延値で、遅い要求の影響を確認するために使います。 6. 失敗・再接続・重複処理のシナリオを実行します。 バッチサイズやスレッド数に一律の推奨値を使わないでください。大きすぎるバッチはメモリと 失敗時の再処理範囲を増やし、小さすぎるバッチはネットワーク往復の割合を増やします。 ## Append の運用 Append のライフサイクル・エラー・重複処理の仕様は [共通連携概念](/ja/dbms/development-tools-integration/concepts-common/#append-api-batch)と [SDK Append 対応表](/ja/dbms/development-tools-integration/sdk-support-scope/#append-table-type-matrix)に従います。 バッチサイズと接続数を変えながら、毎秒の入力行数(rows/s)、p95・p99 遅延、 サーバー処理応答、失敗件数を記録します。 ## ファイルのロード ファイル形式、失敗行ファイル、終了コード、最終行数の検証は [データの入力とエクスポート](/ja/dbms/development-tools-integration/data-input-load-export/)を参照してください。 ここでは、同じ検証を完了したワークロードの性能だけを比較します。 ## ボトルネックの分類 | 観測 | 次に確認 | |------|-----------| | クライアント CPU が飽和 | シリアライズ、変換、ログ出力 | | ネットワーク待機が増加 | バッチ、往復通信、パケット損失 | | サーバー CPU が飽和 | インデックス数、SQL 解析、同時実行 | | ストレージ遅延が増加 | チェックポイント、デバイスキュー、保持処理 | | メモリ使用量が増加 | バッチバッファ、接続数、キャッシュ | | 一部のノードだけが遅い | キー分布、ルーティング、ノード別リソース | ## 変更前後の比較 成功行数と失敗行数を検証してから、スループットの改善を判断します。入力開始からサーバー反映までの 遅延も測定し、クエリ性能と復旧時間への影響を確認します。 --- title: "12.5 クエリと分析の性能調整" url: https://docs.machbase.com/ja/dbms/performance-tuning/performance-query-tuning/ language: ja kind: page --- # 12.5 クエリと分析の性能調整 結果の正確さを維持しながら、読み出す行・パーティションとソート・集計の処理量を減らします。 変更前後は同じデータ、条件、同時実行数で、実行時間と結果件数を比較します。 ## 基本原則 1. TAG・LOG のクエリは、必要な時間範囲を先に限定します。 2. 必要な列だけを選び、無制限の `SELECT *` を避けます。 3. 頻出する等価・範囲条件や JOIN キーに適したインデックスを検討します。 4. 繰り返す長期間の TAG 集計には ROLLUP を使用します。 5. ヒントや設定を変える前に `EXPLAIN` で実行計画を確認します。 6. 平均だけでなく遅延分布、読み出し行数、CPU・I/O、同時クエリへの影響を記録します。 ## 検証用の例 次の例では LOG テーブルとインデックスを作成し、実行計画と結果を確認してから削除します。 ```sql CREATE LOG TABLE perf_event_demo ( device_id VARCHAR(32), level VARCHAR(16), code INTEGER, message VARCHAR(100) ); CREATE INDEX idx_perf_event_code ON perf_event_demo(code) INDEX_TYPE LSM; INSERT INTO perf_event_demo VALUES ('DEV-01', 'WARN', 1001, 'temperature high'); INSERT INTO perf_event_demo VALUES ('DEV-02', 'INFO', 1000, 'started'); EXEC TABLE_FLUSH(perf_event_demo); EXPLAIN SELECT device_id, level, message FROM perf_event_demo WHERE code = 1001 AND _ARRIVAL_TIME >= NOW - 60000000000; SELECT device_id, level, message FROM perf_event_demo WHERE code = 1001 AND _ARRIVAL_TIME >= NOW - 60000000000; DROP TABLE perf_event_demo; ``` 少量のサンプルから、インデックススキャンが常に速いと結論付けないでください。運用に近いデータ分布と 条件の選択性で、作成前後を比較します。 ## SELECT と JOIN - 大きな元テーブルは時間・キー条件で先に絞り込みます。 - JOIN 条件の両側で型と長さを合わせます。 - WHERE の列を関数で包み、インデックス範囲を使えなくしていないか確認します。 - outer JOIN を inner JOIN に変える前に、NULL で補完された行が失われないか比較します。 - 結果順序が必要なら `ORDER BY` を明示します。 - ページ分割では、大きな OFFSET より業務キー・時刻による継続読み出しを検討します。 オプティマイザーが SQL に書かれたテーブル順序に従うとは限りません。結合順序を強制するヒントは、 統計やデータ分布の変化で逆効果になる場合があるため、実行計画と結果を併せて検証します。 ## EXPLAIN の利用 `EXPLAIN` はクエリを実行せずに計画を表示します。`EXPLAIN FULL` は実行を伴う場合があるため、 運用負荷のない限定的な環境で使用します。 実行計画では次を確認します。 | 項目 | 確認する問い | |------|------| | 対象テーブル | 意図したテーブルとビューが選ばれているか | | スキャン方式 | 条件とインデックスに適したアクセス経路か | | 時間範囲 | TAG・LOG のパーティション範囲が限定されるか | | JOIN | 大きな入力に対して不要な結合が行われていないか | | ソート・集計 | 大きな中間結果をソート・マテリアライズしていないか | バージョンで変わり得る内部オブジェクト ID や実行計画全体の文字列を自動検査の固定値にしないでください。 テーブル名、スキャン方式、主要条件など、意味が安定した要素を検査します。 ## CTE CTE は複雑なクエリを読みやすくしますが、自動的に性能を改善するわけではありません。同じ CTE の再評価、 CTE 内へのフィルター適用、大きな中間結果の生成を実行計画で確認します。Machbase 8.7.0 は Standard Edition で非再帰 SELECT CTE をサポートし、再帰 CTE はサポートしません。 構文と例は [CTE](/ja/dbms/reference/sql/syntax/cte-syntax/)を参照してください。 ## 検索演算子 | 条件 | 確認事項 | |------|------| | 等価・範囲比較 | 列の型とインデックスタイプが適合するか | | `LIKE 'prefix%'` | 前方一致検索と文字列インデックスを利用するか | | 先頭ワイルドカード | 全体スキャンのコストを許容できるか | | `SEARCH`・`ESEARCH` | KEYWORD インデックスと構文が適合するか | | `REGEXP` | 時間条件や他のインデックス条件で先に候補行を絞ったか | | JSON パス | テーブルタイプと JSON インデックスの対応を確認したか | | IP 範囲 | IPV4・IPV6 型とインデックスの対応を確認したか | 条件の正確な意味とインデックス利用条件は [SEARCH・ESEARCH・REGEXP](/ja/dbms/reference/sql/syntax/search-esearch-regexp-syntax/)と [JSON 演算子](/ja/dbms/reference/sql/functions/operators-json/)を参照してください。 ## ウィンドウ関数と PIVOT ウィンドウのパーティションやソートキーが大きいと、ソート・メモリコストが増えることがあります。 まず時間と業務キーで入力を絞り、同じウィンドウを重複計算していないか確認します。 PIVOT は出力カテゴリ数を限定し、想定外カテゴリの処理方法を決めます。 構文は[ウィンドウ関数](/ja/dbms/reference/sql/syntax/window-function-over-syntax/)と [PIVOT](/ja/dbms/reference/sql/syntax/pivot-syntax/)を参照してください。 ## 変更前後のチェックリスト - 結果行数と NULL 分布が同じか。 - 同じ時間範囲とタイムゾーンを使っているか。 - コールド・ウォームキャッシュを区別したか。 - 単独実行だけでなく同時クエリでも比較したか。 - 入力スループットやメモリへの副作用がないか。 - ロールバック用の DDL・設定値と基準測定値を記録したか。 ## 関連 SQL 文書 | トピック | 詳細文書 | |---|---| | SELECT・時間条件 | [SELECT 構文](/ja/dbms/reference/sql/syntax/select-syntax/) | | VIEW・CTE・集合演算 | [SQL 構文リファレンス](/ja/dbms/reference/sql/syntax/) | | ヒント | [SELECT ヒント](/ja/dbms/reference/sql/syntax/select-hint-syntax/) | | 関数・集計 | [関数リファレンス](/ja/dbms/reference/sql/functions/) | --- title: "12.6 PVO Cache とメモリのチューニング" url: https://docs.machbase.com/ja/dbms/performance-tuning/cache-tuning-memory/ language: ja kind: page --- # 12.6 PVO Cache とメモリのチューニング ## PVO Cache の運用 PVO Cache は SQL 実行計画を再利用します。クエリ結果の行を保存するキャッシュではありません。 ## メモリ設定のチューニング PVO Cache、Min-Max Cache、プロセス上限、クエリの一時メモリを、利用可能な物理メモリの 予算内でまとめて計画します。 --- title: "12.7 ストレージと Cluster のチューニング" url: https://docs.machbase.com/ja/dbms/performance-tuning/tuning-storage-cluster/ language: ja kind: page --- # 12.7 ストレージと Cluster のチューニング ストレージと Cluster の調整は、ワークロード測定、障害復旧目標、ノード別リソース使用量に基づいて行います。 固定のハードウェア仕様や任意の設定値を、すべての環境に当てはめないでください。 ## ストレージとチェックポイント 同じ時間範囲で次を比較します。 - 入力 rows/s とサーバー処理応答の遅延 - クエリ応答時間と読み出し量 - デバイス別 IOPS、スループット、キュー、遅延 - チェックポイントの開始・終了と所要時間 - メモリ・スワップの変化 - 障害後に許容する復旧時間 ```bash iostat -x 1 5 df -h ``` チェックポイント間隔と I/O 関連設定の現在値を [設定リファレンス](/ja/dbms/reference/configuration/configuration/)で確認します。 1項目ずつ変更し、再起動の要否とロールバック値を記録します。 ## パスと容量 - データ、バックアップ、エクスポートのパスの所有者と空き容量を確認します。 - 同じ物理デバイス上でパスを分けただけで I/O が分散するとは限りません。 - 稼働中のデータファイルを手動で移動しないでください。 - 保持ポリシーとバックアップ領域の増加を併せて計算します。 - ファイルシステム・マウント設定の変更は、サポート範囲と復旧手順を検証します。 古いデータの削除に、内部パーティションテーブル名を直接使わないでください。タイプ別の `DELETE ... BEFORE`、保持ポリシー、バックアップポリシーなど、公開 SQL と運用機能を使用します。 ## Cluster の測定 クライアント、Broker、Warehouse、Coordinator の指標を分けて確認します。 | 区間 | 確認項目 | |------|------| | クライアント → Broker | 接続、往復通信、バッチサイズ | | Broker | セッション、ルーティング、CPU・ネットワーク | | Warehouse | ノード別の入力・クエリ・ディスクの偏り | | ノード間通信 | 帯域幅、パケット損失、遅延 | | Coordinator | ノード状態と disk-full ポリシー | 特定ノードに負荷が集中した場合は、タグ・キー分布、ルーティング、Warehouse グループ、ノード別の ストレージとネットワークを確認します。`TAG_PARTITION_COUNT` を Cluster のノード分散制御に使わないでください。 ## 設定変更の原則 - 名前、許容範囲、デフォルト値は、インストール済みバージョンのリファレンスで確認します。 - 任意の推奨値ではなく、現在の基準値と目標を記録します。 - バッファを増やす場合、スループットに加えてメモリとテールレイテンシーを測定します。 - 複製設定の変更前に、正常時と障害時の復旧時間を比較します。 - disk-full の上下しきい値にヒステリシスを設け、実際の増設・整理手順と結び付けます。 - Edition 別の非サポート機能は[サポート範囲](/ja/dbms/reference/support-scope-constraints/)で確認します。 ## 変更チェックリスト 1. ノード・区間別のボトルネックの根拠があるか。 2. 現在値と出典を記録したか。 3. 検証環境で正常・障害シナリオを測定したか。 4. ノード別のデプロイ順序と再起動の要否を確認したか。 5. 結果が悪い場合に戻す値と手順があるか。 6. 変更後にバックアップ・復旧も検証したか。 --- title: "13. 運用・設定・復旧" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/ language: ja kind: section --- # 13. 運用・設定・復旧 Machbase サーバーの起動・停止、設定変更、監視、バックアップ・リストア、Cluster 運用を扱います。 日常運用の手順を先に整え、変更と復旧は計画に従って実施します。 ## この章の構成 | 順序 | 節 | 内容 | |-----:|------|------| | 13.1 | [サーバーとデータベースの運用](./server-database/) | 起動・停止、データベースの作成・削除、ライセンス | | 13.2 | [複数データベース](./multi-database/) | 論理データベース、権限、バックアップ・リストア、クライアント連携 | | 13.3 | [設定の運用](./configuration/) | 設定ファイル、メモリ、ネットワーク、ストレージ、タイムゾーン | | 13.4 | [ALTER SYSTEM の運用](./alter-system/) | 実行時の設定変更とシステム制御 | | 13.5 | [データ保持ポリシー](./policy-data-retention/) | Retention の作成、適用、確認、解除 | | 13.6 | [監視と診断](./diagnosis-observability/) | システムビュー、ログ、セッション、容量、障害の兆候 | | 13.7 | [スキーマ変更チェックリスト](./checklist-schema-alter/) | DDL 前後の影響分析と検証 | | 13.8 | [バックアップ・リストア・マウント](./backup-restore-mount/) | オンラインバックアップ、オフラインリストア、読み取り専用マウント | | 13.9 | [Cluster の運用](./cluster/) | トポロジー、ノードの追加・削除、状態管理 | 日常点検には[サーバーとデータベースの運用](./server-database/)、[設定の運用](./configuration/)、 [監視と診断](./diagnosis-observability/)を利用します。複数データベースを導入する前に [複数データベース](./multi-database/)を確認してください。スキーマや設定の変更には [ALTER SYSTEM の運用](./alter-system/)と[スキーマ変更チェックリスト](./checklist-schema-alter/)、 障害復旧とバックアップ検証には[バックアップ・リストア・マウント](./backup-restore-mount/)を参照します。 --- title: "13.1 サーバーとデータベースの運用" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/server-database/ language: ja kind: page --- # 13.1 サーバーとデータベースの運用 `machadmin` はサーバーインスタンスの起動・停止、物理データベースの作成・削除、ライセンスの インストール、オフラインリストアを行います。SQL `CREATE DATABASE` で作る論理データベースと、 `machadmin -c` で作る物理インスタンスのデータベースを区別してください。 ## 主なオプションの確認 ```bash "$MACHBASE_HOME/bin/machadmin" -h ``` インストール済みリリースのヘルプを基準に、オプションと影響を確認します。 ## サーバーの起動と停止 状態確認は安全に実行できます。 ```bash "$MACHBASE_HOME/bin/machadmin" -e ``` 起動・停止は、サービスマネージャーまたは運用手順書のいずれかに統一します。 - 起動前に設定、ライセンス、データパス、空き容量を確認します。 - 起動後に `machadmin -e`、5656への接続、軽量 SQL、サーバーログを確認します。 - 正常停止前に新しい接続・入力を止め、実行中のトランザクション、バックアップ、Appender を確認します。 - 強制停止は、正常停止が繰り返し失敗し、復旧への影響を評価した場合だけ使用します。 - 復旧モードを任意に強制せず、エラーと公式の復旧手順を確認します。 コマンド出力はリリースで変わるため、成功メッセージ全体を自動処理の判定条件にしないでください。 プロセスの終了コードと実際の接続を併せて確認します。 ## 物理インスタンスのデータベース `machadmin -c` と `machadmin -d` は、`DBS_PATH` にある物理インスタンスのデータを作成・削除します。 論理データベースには[複数データベース](../multi-database/)の SQL を使用します。 物理データベースの削除・初期化は、インスタンスの全データを失う可能性がある破壊的操作です。 起動エラーの解消のためにデータベースを削除・再作成しないでください。まずエラーを診断し、 既存データを保護した状態で復旧方法を選びます。 実行前の確認事項: 1. 対象 `MACHBASE_HOME` と `DBS_PATH` の絶対パス 2. サービスとプロセスの完全停止 3. 最新バックアップと隔離環境でのリストア検証 4. 保持する設定、ライセンス、ログ 5. ロールバックの可否と想定復旧時間 6. 2名の作業者によるインスタンスとパスの相互確認 データディレクトリ内のファイルやメタデータを手動で作成・移動・削除しないでください。 ## ライセンスのインストールと確認 ライセンスファイルは機密情報として扱い、内容や実際のキーを文書、サポート依頼、ログへコピーしないでください。 | 状態 | 方法 | |------|------| | サーバー停止中にインストール | 現行リリースの `machadmin` ライセンスオプション | | サーバー稼働中にインストール | `ALTER SYSTEM INSTALL LICENSE` | | 適用確認 | `machadmin` のライセンス情報と `V$LICENSE_INFO` | ```sql SELECT * FROM V$LICENSE_INFO; ``` インストール前に対象インスタンス、Edition、有効期間、ファイル権限を確認します。オンライン インストールのパスはサーバープロセスから読み取れる必要があります。更新後は新しい接続と 必要な Edition 機能を検証し、元のライセンスファイルに保持ポリシーを適用します。 ## 障害原因の特定に必要な情報 - `machadmin -e` の結果と終了コード - リリース、Edition、`MACHBASE_HOME` - 実際の設定・データパス - サーバーの起動・停止時刻 - 最初のエラー前後のサーバーログ - ファイルシステムの空き容量と権限 - 直前の設定・ライセンス・ストレージ変更 サーバーが起動しないだけで物理データベースを削除したり、初期化による復旧を先に実行したりしないでください。 バックアップを保持したまま原因を診断します。 --- title: "13.2 複数データベース" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/multi-database/ language: ja kind: page --- # 13.2 複数データベース Standard Edition では、1つのサーバー内に複数の論理データベースを作成し、オブジェクトとアクセス権限を 分離できます。このページでは導入と運用の流れを説明します。SQL 構文、権限、SDK オプション、 バックアップ手順は、リンク先の詳細文書を参照してください。 ## 適用範囲 - 複数データベースは Standard Edition の機能です。 - 論理データベースは、独立したサーバープロセスやリソース割り当て枠を作りません。 - オブジェクト名は `object`、`owner.object`、`database.owner.object` の最大3部分です。 - 別データベースを指定する場合、所有者を省略しないでください。 - マウントされたデータベースは、アクティブなデータベースとは別の、読み取り専用バックアップ参照経路です。 ## 導入前の決定事項 1. データベースごとの所有者とアプリケーションユーザーを決めます。 2. `CONNECT` とオブジェクト単位の最小権限を定義します。 3. 接続プールによる現在のデータベースの初期化・復元方法を確認します。 4. バックアップ単位、復旧順序、マウント名の規則を決めます。 5. データベース別の使用量と障害を区別する監視基準を用意します。 ## 簡単な検証 次の例では、2つのデータベースが分離されることを確認し、最後に両方を削除します。 ```sql CREATE DATABASE IF NOT EXISTS manual_multidb_a; CREATE DATABASE IF NOT EXISTS manual_multidb_b; USE manual_multidb_a; CREATE LOG TABLE sensor_event ( event_time DATETIME, message VARCHAR(100) ); INSERT INTO sensor_event VALUES (SYSDATE, 'from-a'); USE manual_multidb_b; CREATE LOG TABLE sensor_event ( event_time DATETIME, message VARCHAR(100) ); INSERT INTO sensor_event VALUES (SYSDATE, 'from-b'); SELECT message FROM manual_multidb_a.SYS.sensor_event; SELECT message FROM manual_multidb_b.SYS.sensor_event; USE MACHBASEDB; DROP DATABASE manual_multidb_a CASCADE FORCE; DROP DATABASE manual_multidb_b CASCADE FORCE; ``` `USE database_name` は現在の接続のデータベースを変更します。トランザクション、開いたカーソル、 プリペアドステートメント(*prepared statement*)、Appender がある状態では切り替えないでください。 別のデータベースのオブジェクトは `database.owner.object` で指定します。 ## 権限の境界 ユーザーには、対象データベースの `CONNECT` と、実際のオブジェクト操作に必要な権限の両方が必要です。 データベースの作成・削除・権限管理 SQL は[アカウントと権限](/ja/dbms/security-access-control/privileges/) を参照してください。運用アカウントへ管理者権限を一括付与しないでください。 ## アプリケーションの接続 初期データベースのオプション名と接続プールの初期化動作は SDK ごとに異なります。各 SDK の 接続文書でサポートを確認し、接続を借りた直後に次の値を検証します。 ```sql SELECT CURRENT_DATABASE(); ``` 言語別設定は[開発とアプリケーション連携](/ja/dbms/development-tools-integration/)、 サーバー・SDK の互換性は[サーバーと SDK の互換性](/ja/dbms/reference/support-scope-constraints/compatibility-xma-protocol/) を参照してください。 ## バックアップと復旧 バックアップ前に、含めるアクティブデータベースと復旧順序を記録します。マウントされたデータベースにも `USE` は可能ですが、読み取り専用(*read-only*)で `SELECT` だけを実行できます。 正確なコマンドと検証手順は[バックアップ・リストア・マウント](../backup-restore-mount/)を参照してください。 ## 運用チェックリスト - 接続直後と接続プールの再利用直後に `CURRENT_DATABASE()` が期待値を返すか。 - SQL と監視が、異なるデータベースの同名オブジェクトを混同していないか。 - ユーザーには対象データベースとオブジェクトの必要最小限の権限だけを付与したか。 - バックアップ・復旧訓練で全対象データベースを確認したか。 - データベース削除前に、開いた接続、オブジェクト、バックアップの保持条件を確認したか。 正確な `CREATE/DROP/USE DATABASE` 構文は [DATABASE 構文](/ja/dbms/reference/sql/syntax/database-syntax/)を参照してください。 --- title: "13.3 設定の運用" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/configuration/ language: ja kind: page --- # 13.3 設定の運用 設定変更は、現在値、変更理由、適用方法、検証値、ロールバックを記録し、1項目ずつ行います。 設定プロパティの全一覧とデフォルト値は、現行リリースの [設定リファレンス](/ja/dbms/reference/configuration/configuration/)を参照してください。 ## 設定ファイル デフォルトの設定ファイルは `$MACHBASE_HOME/conf/machbase.conf` です。パッケージやサービス構成に よって別ファイルを使う場合があるため、起動コマンドと実環境を確認します。 変更前に次を記録します。 - ファイルパス、所有者、権限 - 変更対象のファイル内の値と `V$PROPERTY` の現在値 - 単位と許容範囲 - 実行時変更の可否と再起動の要否 - 関連ノード・インスタンスの範囲 - ロールバック値と検証 SQL パスワード、AUTH KEY、ライセンス内容は、通常の設定バックアップや作業記録に含めないでください。 ## 実行中の変更と再起動 `ALTER SYSTEM SET` で実行時に変更できるのは、対応する一部のプロパティだけです。 文書に例があるという理由で、任意のプロパティを変更しないでください。 ```sql SELECT NAME, VALUE FROM V$PROPERTY ORDER BY NAME; ``` 1. 設定リファレンスで動的変更の対応を確認します。 2. メンテナンス範囲と影響する接続・クエリを定めます。 3. 現在値を保存します。 4. 検証環境または限定したワークロードで1項目だけ変更します。 5. 応答時間、スループット、メモリ・I/O、エラーを比較します。 6. 採用する値は設定ファイルにも反映し、再起動後に戻らないようにします。 7. 再起動後、`V$PROPERTY` と機能テストで適用を確認します。 ## 設定プロパティの検索 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME LIKE 'PVO_CACHE%' ORDER BY NAME; ``` 正確な名前が分かる場合は `NAME = '...'` で検索します。似た名前から推測して設定しないでください。 ## メモリ設定 プロセス上限、テーブル領域・キャッシュ、入力バッファ、クエリ・セッションの一時メモリを 1つの予算として考えます。OS と同一ホスト上の他プロセスに必要なメモリも確保します。 - 通常・ピーク負荷時の常駐メモリと利用可能メモリ - スワップの有無と増加時刻 - 同時クエリ・Appender・セッション数 - PVO、Min-Max、LOOKUP・VOLATILE などのキャッシュ使用量 - インデックス作成、ソート、集計などの一時処理 固定比率や例のバイト数をそのまま適用しないでください。 ## ネットワークとセッション リスナーのアドレス・ポート、最大セッション数、接続・クエリタイムアウトは、アプリケーション接続数と 障害分離要件を基準に決めます。ファイアウォールとバインドは別々に検証し、セッション上限を増やす前に 接続リークとプール設定を確認します。 ```sql SELECT ID, USER_NAME, USER_IP, LOGIN_TIME, CLIENT_TYPE FROM V$SESSION ORDER BY LOGIN_TIME DESC; ``` ## ストレージとチェックポイント `DBS_PATH`、チェックポイント、direct I/O、I/O スレッドの設定は、データの場所と復旧時間に直接影響します。 運用データファイルを手動で移動したり、別のパスを推測したりしないでください。 - 実際のデータ・バックアップパスとファイルシステムを確認します。 - 同じ期間のチェックポイント時間とデバイス遅延を比較します。 - 再起動が必要な設定には、サービス停止・復旧手順を準備します。 - 変更後に正常な再起動、バックアップ、リストアを検証します。 ## タイムゾーン 時刻文字列の入力・表示に使うタイムゾーンを、サーバー、コマンドラインツール、SDK で一貫して設定します。 epoch の単位と `DATETIME` の精度は別に確認し、同じ値を入力して読み出す往復テストを行います。 ## サーバーとセッションのタイムゾーン サーバーのデフォルトタイムゾーンと、クライアントが選択したセッションタイムゾーンを区別します。 アプリケーションの文字列入出力基準は対応する接続オプションで明示し、新しい接続の `SHOW TIMEZONE` と サンプル `DATETIME` クエリで確認します。設定方法は [タイムゾーン設定](/ja/dbms/reference/configuration/configuration-timezone/)を参照してください。 既存接続のセッション設定は自動では変わりません。 ## machsql `-z` ```bash "$MACHBASE_HOME/bin/machsql" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -z +0900 ``` 入力・出力文字列が指定したオフセットで解釈・表示されることをサンプルで確認します。 ## machloader `-z` ```bash "$MACHBASE_HOME/bin/machloader" -s 127.0.0.1 -P 5656 -u APP_USER -p "$MACH_SAMPLE_PASSWORD" -z +0900 -i -t SENSOR_LOG -d /data/sensor.csv ``` 元の CSV のタイムゾーンと日時形式を併せて文書化します。 ## SDK 接続のタイムゾーン 対応オプション名は SDK によって異なります。[11章 開発とアプリケーション連携](/ja/dbms/development-tools-integration/) でドライバーの接続オプションを確認し、入力・クエリ・接続プールの再利用後も同じタイムゾーンが 適用されることを検証します。 ## 変更記録 | 項目 | 記録 | |------|------| | 対象 | ホスト、インスタンス、ノード、データベース | | 変更 | プロパティと変更前後の値 | | 根拠 | 基準値と目標 | | 適用 | 実行時または再起動 | | 検証 | SQL、ワークロード、OS 指標 | | ロールバック | 値、実行順序、担当者 | 未確認の推奨値や旧リリースのデフォルト値を、現在の設定として扱わないでください。 --- title: "13.4 ALTER SYSTEM の運用" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/alter-system/ language: ja kind: page --- # 13.4 ALTER SYSTEM の運用 `ALTER SYSTEM` はインスタンス全体に影響する可能性がある管理コマンドです。実行前に対象、権限、 進行中の処理、ロールバックまたは解除コマンドを確認します。構文全体は [システム・セッション ALTER 構文](/ja/dbms/reference/sql/syntax/system-session-alter-syntax/)を参照してください。 ## 共通手順 1. 現在のサーバー、データベース、リリースを確認します。 2. 関連セッション、文、バックアップ、チェックポイントの状態を記録します。 3. ブロッキング、I/O、メモリへの影響を確認します。 4. メンテナンス時間と失敗時の対応を決めます。 5. 実行直後に結果、関連仮想テーブル、ログを確認します。 ## CHECKPOINT ```text ALTER SYSTEM CHECKPOINT; ``` チェックポイントはストレージ I/O を増加させることがあります。バックアップ・停止前に必要性を検討し、 同時に行う大量入力やクエリへの影響を観察します。単に遅いという理由で繰り返し実行しないでください。 ## CHECK DISK_USAGE ```text ALTER SYSTEM CHECK DISK_USAGE; ``` ファイルシステムの状態とデータベースのストレージメタデータを点検する際に使用します。事前に 空き容量とマウント状態を確認し、結果ログを調べます。数値を合わせるために内部ファイルを編集してはいけません。 ## INSTALL LICENSE ```text ALTER SYSTEM INSTALL LICENSE; ALTER SYSTEM INSTALL LICENSE = '/absolute/path/license.dat'; ``` ライセンスの入手元、対象インスタンス、Edition、有効期限を確認します。内容を文書やログへコピーせず、 アクセス権限を制限します。インストール後は `V$LICENSE_INFO` と新しい接続で適用を確認します。 ## KILL と CANCEL SESSION ```text ALTER SYSTEM CANCEL SESSION session_id; ALTER SYSTEM KILL SESSION session_id; ``` まず `V$SESSION` と `V$STMT` でユーザー、クライアント IP、SQL、状態を確認します。実行中の文を 止める場合は `CANCEL`、接続自体の終了が必要なら `KILL` を検討します。トランザクション、Appender、 アプリケーションの再試行が引き起こす重複とロールバックへの影響を確認します。 ## FREEZE と UNFREEZE ```text ALTER SYSTEM FREEZE; ALTER SYSTEM UNFREEZE; ``` freeze は、公開バックアップ機能で代替できないファイルシステムスナップショットの手順でのみ検討します。 事前に許容する読み書きと最大 freeze 時間を定め、すべてのエラー経路で `UNFREEZE` を実行する 担当者と確認手順を用意します。セッションを freeze 状態のまま放置してはいけません。 ## FLUSH AGER ```text ALTER SYSTEM FLUSH AGER; ``` 削除済み領域の回収遅延を調査する際に、使用を検討します。保持ポリシー、DELETE の状態、 ストレージの余裕を先に確認し、正常なバックグラウンド処理を繰り返し強制しないでください。 ## FLUSH PVO_CACHE ```text ALTER SYSTEM FLUSH PVO_CACHE; ``` 実行計画キャッシュを消去すると、後続クエリが再解析・再最適化されます。スキーマや実行計画の問題を 切り分ける場合だけ実行し、同時クエリの一時的な遅延増大を観察します。継続的な性能問題の 対策としてキャッシュ消去を使わないでください。 ## FLUSH SYS_STAT ```text ALTER SYSTEM FLUSH SYS_STAT; ``` 累積統計を初期化する前に、必要な基準値を保存します。初期化時刻を監視に記録し、 変化率計算や障害分析が不正確にならないようにします。 ## FLUSH PAGE_CACHE ```text ALTER SYSTEM FLUSH PAGE_CACHE; ``` ページキャッシュの消去は、後続クエリの I/O と遅延を大きく変えることがあります。コールドキャッシュの 比較や限定的な診断だけに使い、運用のピーク負荷時には実行しないでください。 ## 権限と監査 必要最小限の管理権限を持つアカウントで実行し、コマンド、対象、時刻、実行者、理由、結果を 監査記録に残します。例のセッション ID、パス、設定値をそのまま運用環境に使わないでください。 --- title: "13.5 データ保持ポリシー" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/policy-data-retention/ language: ja kind: page --- # 13.5 データ保持ポリシー Retention Policy は TAG、KV、LOG で基準時刻より古いデータを定期的に削除します。 `DURATION` は保持期間、`INTERVAL` は削除ジョブの実行周期です。 TRANSACTION、VOLATILE、LOOKUP には適用できません。 ```text ポリシー作成 → テーブルへ適用 → 実行状態確認 → テーブルから解除 → ポリシー削除 ``` ## Retention Policy 運用ポリシーを作成する前に、法的な保存義務、復旧要件、時間当たりの流入量、削除負荷を確認します。 `INTERVAL` は固定比率で決めず、運用環境で測定した削除時間より十分長い周期を使用してください。 ポリシーと適用状態は次のビューで確認します。 ```sql SELECT * FROM M$RETENTION; SELECT USER_NAME, TABLE_NAME, POLICY_NAME, STATE, LAST_DELETED_TIME FROM V$RETENTION_JOB; ``` ### Retention Policy の作成 ```sql CREATE RETENTION policy_name DURATION duration_value {MONTH|DAY|HOUR|MIN|SEC} INTERVAL interval_value {DAY|HOUR|MIN|SEC}; ``` `DURATION` は月から秒、`INTERVAL` は `DAY` から `SEC` を指定できます。`MONTH` は暦月ではなく 固定の30日です。法的保存など暦の境界が重要な場合は `DAY` に換算し、実際の削除基準を検証します。 正確な構文と対応テーブルは[RETENTION 構文](/ja/dbms/reference/sql/syntax/retention-syntax/)を参照してください。 例えば、30日保持し、1日ごとに削除対象を処理するポリシーは次のとおりです。 ```sql CREATE RETENTION policy_30d DURATION 30 DAY INTERVAL 1 DAY; SELECT * FROM M$RETENTION WHERE POLICY_NAME = 'POLICY_30D'; ``` ポリシーの作成と削除には必要な管理権限が必要です。運用アカウントで実行する前に、権限と 承認された変更範囲を確認してください。 ### テーブルへの適用 ```sql ALTER TABLE sensor_tag ADD RETENTION policy_30d; SELECT USER_NAME, TABLE_NAME, POLICY_NAME, STATE FROM V$RETENTION_JOB WHERE TABLE_NAME = 'SENSOR_TAG'; ``` 1つのテーブルには1つのポリシーだけを適用できます。TAG は `BASETIME`、LOG は `_ARRIVAL_TIME` を 基準に古いデータを判定します。適用直後に削除するのではなく、設定した周期に従って実行します。 ### テーブルからの解除 ```sql ALTER TABLE sensor_tag DROP RETENTION; ``` 解除すると自動削除は停止しますが、削除済みデータは復元されません。解除後、 `V$RETENTION_JOB` から対象テーブルがなくなったことを確認します。 ### Retention Policy の削除 ポリシーを使うすべてのテーブルから解除してから、ポリシーオブジェクトを削除します。 ```sql SELECT USER_NAME, TABLE_NAME FROM V$RETENTION_JOB WHERE POLICY_NAME = 'POLICY_30D'; -- 検索された各テーブルからポリシーを解除してから実行 DROP RETENTION policy_30d; ``` `ALTER TABLE ... DROP RETENTION` はテーブルとポリシーの関連付けを解除し、`DROP RETENTION` は ポリシーオブジェクトを削除します。適用中のポリシーは削除できません。 ### 適用範囲と権限 | テーブルタイプ | 適用可能 | |---|---| | TAG, KV, LOG | はい | | TRANSACTION, VOLATILE, LOOKUP | いいえ | ポリシー管理者とテーブル所有者が異なる場合、運用前に実際の権限構成を検証してください。 他の所有者のテーブルを対象にする場合も、必要な権限だけを明示的に付与します。 ### 実行状態の確認 ```sql SELECT USER_NAME, TABLE_NAME, POLICY_NAME, STATE, LAST_DELETED_TIME FROM V$RETENTION_JOB ORDER BY USER_NAME, TABLE_NAME; ``` `STATE` はジョブの現在状態、`LAST_DELETED_TIME` は最後の削除で使った基準時刻です。 実時間でのジョブ完了時刻として解釈してはいけません。実際に削除されたかは、対象テーブルの 最古時刻と行数の推移を併せて確認します。 --- title: "13.6 監視と診断" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/diagnosis-observability/ language: ja kind: page --- # 13.6 監視と診断 運用診断では再現時刻と症状を記録し、サーバー状態、セッション・文、ストレージ・メモリ、 関連ログを同じ時間軸で確認します。`M$` メタデータテーブルはスキーマ、`V$` 仮想テーブルは現在状態を提供します。 ## 診断とログ 1. 問題の開始・終了時刻とクライアント情報を記録します。 2. `machadmin -e` でサーバー応答を確認します。 3. `V$SESSION` と `V$STMT` から関連処理を探します。 4. 症状に応じてストレージ・メモリ・ROLLUP などの仮想テーブルを確認します。 5. 同じ時刻のサーバー・クライアント・loader ログを比較します。 6. 変更前に現在の設定と基準値を保存します。 ## トレースログ設定 トレースレベル、ファイルサイズ、保持設定は、障害分析に必要な範囲だけを調整します。 [設定リファレンス](/ja/dbms/reference/configuration/configuration/)で、現行リリースのプロパティ名、 許容値、再起動の要否を確認します。機密 SQL やデータが記録され得るため、ログのアクセス権限と保持期間を設定します。 ## サーバーログ デフォルトのトレースディレクトリは `$MACHBASE_HOME/trc` です。ファイル名が固定とは考えず、 実際のディレクトリと設定値を確認します。 ```bash ls -lh "$MACHBASE_HOME/trc" tail -n 200 "$MACHBASE_HOME/trc/machbase.trc" ``` エラー文字列を数えるだけでなく、最初のエラー、直前の警告、起動・停止、チェックポイント・ ストレージのイベントを時系列で確認します。手動コマンドでログを一括削除しないでください。 ## machsql ログ `machsql.history` には認証情報や機密 SQL が残ることがあります。運用アカウントの履歴ファイル権限を 制限し、共有前に内容を確認します。再現 SQL は、対象データベース、実行時刻、結果・エラーとともに保存します。 ## machloader ログ 大量ロードでは、終了コード、サマリー、ログ、失敗行ファイルをまとめて確認します。 - スキーマと入力列数・順序 - 区切り文字、引用符、エンコーディング - NULL と DATETIME の形式 - 最初の失敗行と繰り返すエラーコード - 最終的な成功・失敗件数 失敗行ファイル全体をそのまま再実行しないでください。原因を修正したサンプルで検証し、失敗行だけを再処理します。 ## メタデータテーブル `M$SYS_TABLES`、`M$SYS_COLUMNS`、`M$SYS_INDEXES` などで現在のデータベースのスキーマを確認します。 名前だけで結合せず、データベース ID、所有者 ID、オブジェクト ID を含めます。予約オブジェクト名や 内部テーブル構造にアプリケーションが依存しないようにします。 ## 仮想テーブル まず現行リリースの実際の列を確認します。 ```sql SELECT * FROM V$SESSION LIMIT 1; SELECT * FROM V$STMT LIMIT 1; SELECT * FROM V$PROPERTY LIMIT 1; SELECT * FROM V$STORAGE_USAGE LIMIT 1; SELECT * FROM V$SYSMEM LIMIT 1; SELECT * FROM V$ROLLUP LIMIT 1; SELECT * FROM V$LICENSE_INFO LIMIT 1; ``` 全一覧と列の意味は[システムカタログ](/ja/dbms/reference/system-catalog/virtual-table-full/)を参照してください。 ## 監視と容量管理 アラートは固定しきい値よりも、正常時の基準値、増加率、業務ピーク負荷、復旧の余裕を基準に設定します。 ファイルシステムとデータベースの使用量を併せて確認し、バックアップ・エクスポートの別領域も含めます。 ## サーバー状態 ```bash "$MACHBASE_HOME/bin/machadmin" -e ``` プロセスが存在するだけで正常とは判断しません。ネイティブ接続、軽量 SQL、直近のサーバーログも確認します。 ## セッションと実行 SQL ```sql SELECT id, user_name, user_ip, login_time, client_type FROM V$SESSION ORDER BY login_time DESC; SELECT sess_id, id AS stmt_id, state, record_size, query FROM V$STMT ORDER BY sess_id, id; ``` 長時間実行が必ずしもエラーとは限りません。処理内容、処理行数、クライアントのタイムアウト、 I/O・CPU 状態を併せて確認し、cancel・kill の必要性を判断します。 ## ディスク容量 ```bash df -h "$MACHBASE_HOME" du -sh "$MACHBASE_HOME/dbs" ``` 別の `DBS_PATH` を使用する場合は実際のパスを確認します。内部パーティションファイルを 直接編集・削除しないでください。 ## メモリ OS の利用可能メモリとスワップ、`V$SYSMEM`、キャッシュ、同時クエリ数を併せて比較します。 内部の manager 名を自動化の固定基準にしないでください。 ## バックアップ検証 コマンド成功だけでなく、パス・サイズ・完了状態を記録し、隔離環境でマウントまたはリストアして、 主要テーブル、行数、時間範囲、サンプルクエリを検証します。 ## 障害資料の収集 - リリースと Edition - 発生時刻とタイムゾーン - 再現コマンドとデータベース・ユーザー - サーバー・クライアント・loader ログ - 関連仮想テーブルの結果 - OS の CPU・I/O・メモリ・ディスク - 直近のスキーマ・設定・デプロイ変更 - 試行済みの対策と結果 認証情報、AUTH KEY、個人情報、機密の元データはサポート資料から除去します。 --- title: "13.7 スキーマ変更チェックリスト" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/checklist-schema-alter/ language: ja kind: page --- # 13.7 スキーマ変更チェックリスト 運用中のスキーマを変更する前に、次の項目を順に確認します。 ## 変更前の確認 ### 1. テーブルタイプを確認 ```sql SELECT NAME AS TABLE_NAME, TYPE AS TABLE_TYPE FROM M$SYS_TABLES WHERE NAME = 'TARGET_TABLE'; ``` ALTER TABLE のサポートはタイプごとに異なります。 [テーブルタイプ別の管理範囲](/ja/dbms/reference/support-scope-constraints/table-types-type/)を先に確認してください。 ### 2. 現在のスキーマを確認 ```sql -- 列情報を確認 DESC target_table; -- インデックスを確認 SELECT i.NAME AS INDEX_NAME, i.TYPE AS INDEX_TYPE FROM M$SYS_INDEXES i JOIN M$SYS_TABLES t ON i.DATABASE_ID = t.DATABASE_ID AND i.TABLE_ID = t.ID WHERE t.NAME = 'TARGET_TABLE'; ``` ### 3. データ量を確認 ```sql SELECT COUNT(*) FROM target_table; ``` 大規模テーブルのスキーマ変更には時間がかかる場合があります。テスト環境で所要時間とロックの影響を 測定し、サービスのメンテナンス時間に実行してください。 ### 4. Retention Policy の実行を確認 ```sql SELECT * FROM V$RETENTION_JOB WHERE TABLE_NAME = 'TARGET_TABLE'; ``` Retention Policy が実行中の場合は、完了を待ってからスキーマを変更してください。 ### 5. DDL 競合ポリシーを設定 Standard Edition は異なるオブジェクトの DDL を同時実行できます。同じオブジェクトや直接関連する オブジェクトの DDL は競合するため、運用デプロイセッションで許容する待機時間を先に設定します。 ```sql -- 競合する DDL ロックを最大10秒待機 ALTER SESSION SET DDL_LOCK_TIMEOUT = 10; -- セッション別の設定値を確認 SELECT id, user_name, ddl_lock_timeout FROM v$session WHERE closed = 0 ORDER BY id; ``` | 同時実行対象 | 判定 | |----------------|------| | 名前の異なる独立したテーブル | 並列実行可能 | | 同一オブジェクトまたは同一名 | 競合 | | テーブル変更・削除 DDL とそのテーブルのインデックス DDL | 競合 | | ビュー DDL と元テーブルの変更・削除 DDL | 競合 | | TAG テーブル変更・削除 DDL と関連 Rollup・Retention DDL | 競合 | Cluster Edition には `DDL_LOCK_TIMEOUT` がなく、従来の DDL 直列化ポリシーを使います。 詳細は [DDL の同時実行とロック](/ja/dbms/reference/sql/syntax/ddl-syntax/#ddl-concurrency)を参照してください。 --- ## 列追加チェックリスト - [ ] 追加する列の型は対象テーブルタイプでサポートされるか。 - [ ] LOG/TRANSACTION で列を追加すると、既存行の新しい列が NULL になることを確認したか。 - [ ] 列名の重複を確認したか。 ```sql ALTER TABLE sensor_log ADD COLUMN (new_col DOUBLE); ``` --- ## 列削除チェックリスト - [ ] 列がインデックスに含まれるか。含まれる場合は先にインデックスを削除する。 - [ ] アプリケーションのクエリが列を参照していないか。 - [ ] 削除した列のデータは復旧できないことを確認したか。 ```sql ALTER TABLE sensor_log DROP COLUMN (old_col); ``` --- ## インデックス変更チェックリスト - [ ] インデックスの作成・削除はクエリ性能に直接影響する。 - [ ] 作成時は既存データも索引化するため、大規模テーブルでは時間がかかる。 - [ ] 未使用インデックスは INSERT 性能を下げるため、削除を検討する。 - [ ] `IF NOT EXISTS` を使う場合、同名の既存インデックス定義を別途確認する。 ```sql -- 再デプロイで条件付き作成 CREATE INDEX IF NOT EXISTS idx_new ON sensor_log (sensor_id); -- 名前だけの一致で何もしない場合があるため、実際のマッピングを確認 SHOW INDEX idx_new; -- 不要なインデックスを削除 DROP INDEX idx_old; ``` `IF NOT EXISTS` は、同じデータベース・所有者のインデックス名だけを確認します。既存のテーブル、列、 インデックスタイプ、設定がデプロイの意図と一致するかは、 [INDEX 構文](/ja/dbms/reference/sql/syntax/index-syntax/#create-index-if-not-exists)に従って別途検証します。 --- ## Retention Policy 変更チェックリスト - [ ] 変更が必要な場合: 既存ポリシーを解除 → 新ポリシーを作成・適用。 - [ ] 保持期間を短くする場合: 次の削除対象が増える可能性があるため、データ損失を検討する。 ```sql -- 既存ポリシーを解除 ALTER TABLE sensor_tag DROP RETENTION; -- 新ポリシーを適用 ALTER TABLE sensor_tag ADD RETENTION new_policy; ``` --- ## DDL 競合の処理 デフォルトの `DDL_LOCK_TIMEOUT=0` では、競合時に `ERR-02031: Resource busy ()` が即座に返ります。 1. `ERR-02031` だけを、回数と待機間隔を制限して再試行します。 2. 再試行前に対象と依存オブジェクトの現在状態を再取得します。 3. 待機後、先行 DDL の結果により `already exists` または `table not found` が返る場合があります。 4. 構文・権限エラー、`already exists`、`table not found` に同じ SQL を繰り返し実行しないでください。 5. `machsql` 自動化では終了コードだけでなく出力内の `ERR-` も確認します。 待機時間の終了や操作のキャンセル後も再実行できますが、先行処理が反映されたかを確認してから再試行します。 --- ## 変更後の検証 ```sql -- スキーマ変更を確認 DESC target_table; -- データ整合性を確認 SELECT COUNT(*) FROM target_table; -- インデックス状態を確認 SELECT i.NAME AS INDEX_NAME, i.TYPE AS INDEX_TYPE FROM M$SYS_INDEXES i JOIN M$SYS_TABLES t ON i.DATABASE_ID = t.DATABASE_ID AND i.TABLE_ID = t.ID WHERE t.NAME = 'TARGET_TABLE'; ``` --- **次に読む文書:** - [データ保持ポリシー](/ja/dbms/operations-configuration-recovery/policy-data-retention/) - [運用と設定](/ja/dbms/operations-configuration-recovery/) --- title: "13.8 バックアップ・リストア・マウント" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/backup-restore-mount/ language: ja kind: page --- # 13.8 バックアップ・リストア・マウント バックアップは作成成功だけでなく、隔離環境でのマウント・リストアとサンプルクエリまで検証します。 パス、権限、保存領域、保持期間、暗号化、アクセス制御を併せて管理します。SQL とオプションの詳細は [バックアップ・リストア・マウント構文](/ja/dbms/reference/sql/syntax/backup-restore-mount-syntax/)を参照してください。 ## バックアップ方式の選択 | 目的 | 方式 | |------|------| | インスタンス全体の復旧基準点 | データベースのフルバックアップ | | 特定テーブルの移動・保持 | テーブルバックアップ | | 前回バックアップ以降の変更 | 増分バックアップ | | 特定時間範囲のアーカイブ | 期間バックアップ | | 稼働中にバックアップを参照 | 読み取り専用マウント | | インスタンスデータの置き換え | オフラインリストア | 方式を選ぶ前に、現行リリースの Edition、テーブルタイプ、増分チェーン、マウント・リストアの サポート範囲を確認します。 ## フルバックアップ フルバックアップは独立した復旧基準点として保持します。 - バックアップパスにアクセスするのはサーバープロセスです。 - 保存先ファイルシステムの空き容量とクォータを確認します。 - 開始・終了時刻、エラー、出力サイズを記録します。 - バックアップと元データの唯一のコピーを同じ障害ドメインに置かないでください。 - 定期的に隔離サーバーへリストアし、主要テーブルを検証します。 ## テーブルバックアップ 対応テーブルタイプと、含まれるインデックス・メタデータの範囲を確認します。1つのテーブルを復旧する 場合は、新しいデータベースまたはマウントで検証し、明示的な INSERT・export/import 経路で 移す方法を優先します。既存の運用テーブルを直ちに置き換えないでください。 ## 増分バックアップと AFTER 増分バックアップは前回バックアップ以降の変更を保存します。復旧に必要な基準バックアップと、 関連する増分バックアップを1つのチェーンとして管理します。 - 各バックアップの基準と作成順序を記録します。 - 中間ファイルが1つ欠けた場合の復旧可否を確認します。 - 最後の増分だけを単独で保持しないでください。 - チェーンが長くなったら新しいフルバックアップを作成します。 - オフラインリストアでは最後の増分パスを `machadmin -r` に1回指定します。 フルバックアップから個別に繰り返し適用しません。必要なチェーン全体を保持し、 最終時点のデータが復元されることを確認します。 ## 期間バックアップ 期間バックアップは `BACKUP DATABASE FROM ... TO ...` で開始・終了時刻を指定します。 通常クエリの `WHERE` 構文と混同しないでください。指定タイムゾーンと境界時刻のデータを含め、 バックアップの最小・最大時刻と行数を元データと比較します。 ## SQL BACKUP BACKUP 実行アカウントには必要なデータベース・テーブル権限とサーバーパスへのアクセスが必要です。 運用自動化ではパスワードをコマンドラインに固定せず、終了コードとジョブ状態を併せて確認します。 実行前後の確認事項: 1. 対象データベース・テーブルとバックアップ方式を確認。 2. 保存先がまだ存在しない一意なパスであることを確認。 3. 空き容量と想定増加量を確認。 4. ジョブの完了とエラーを確認。 5. 出力一覧、サイズ、チェックサムまたはストレージの整合性を検証。 6. マウント・リストアによるサンプル検証。 ## オフラインリストア `machadmin -r` によるオフラインリストアは、現在のインスタンスデータを置き換えます。 既存データベースがあると拒否されるため、現在のデータ保護と復旧対象の確認を済ませてから、 検証済み手順でサーバーを停止し、既存データベースを削除します。8.7.0 Standard Edition の 論理データベースのオンラインリストアは、別の SQL `RESTORE DATABASE` を使用します。 両方式の対象と前提条件を区別してください。 - サービスとすべてのクライアント・Collector を停止する計画を立てます。 - 現在データの別バックアップとロールバック経路を確保します。 - 復元する正確なバックアップとチェーンを検証します。 - リリース・Edition・設定の互換性を確認します。 - 復旧担当者2名が対象インスタンスとパスを相互確認します。 - 隔離環境の復旧訓練を通過した手順だけを本番に適用します。 - 復元後、スキーマ、行数、時間範囲、アプリケーションクエリを検証します。 ## データベースのマウント バックアップを読み取り専用データベースとして接続し、調査や選択的な復旧に使います。 ```text MOUNT DATABASE '/absolute/backup/path' TO mount_name; UMOUNT DATABASE mount_name; ``` アクティブな運用データベースと重ならないマウント名を使います。パスと権限はサーバープロセスを基準にします。 ## マウントされたデータベースのクエリ ```text SELECT * FROM mount_name.SYS.table_name WHERE _ARRIVAL_TIME >= TO_DATE('2026-01-01', 'YYYY-MM-DD'); ``` まずテーブル一覧とスキーマを確認し、時間範囲、行数、サンプル値を検証します。必要なデータは、 現在のスキーマと重複ポリシーを確認してから選択的に移動します。 ## 読み取り専用と使用中のマウント マウントされたデータベースでは DDL・DML を実行しません。開いたカーソルや文があるとアンマウントが 拒否される場合があるため、すべての参照を閉じて再試行します。先にアクティブデータベースや他の マウントと名前が衝突していないか確認します。 ## 非サポートの経路 内部構文が成功したように見えても、公開運用 API ではない `MOUNT TABLE`・`UMOUNT TABLE` に 依存しないでください。公開された `MOUNT DATABASE` と `UMOUNT DATABASE` を使用します。 ## テーブルタイプと Edition 別の範囲 LOG、TAG、TRANSACTION、LOOKUP、VOLATILE のバックアップ・マウント動作は同じではありません。 VOLATILE は再起動後にデータが残らないインメモリテーブルです。タイプ・Edition 別の範囲は [バックアップ・マウントのサポート](/ja/dbms/reference/support-scope-constraints/backup-mount/)で確認します。 ## 復旧検証チェックリスト - データベース・所有者・テーブルの数 - 主要テーブルのスキーマとインデックス - 行数、最小・最大時刻 - NULL・文字列・数値のサンプル - ユーザー・権限とアプリケーション接続 - ROLLUP・保持ポリシー・ジョブ状態 - バックアップ時点以降のデータ処理 - ロールバック可否と実所要時間 --- title: "13.9 Cluster の運用" url: https://docs.machbase.com/ja/dbms/operations-configuration-recovery/cluster/ language: ja kind: page --- # 13.9 Cluster の運用 Cluster 操作は、ノード構成、役割、複製・データ状態を確認した後、検証済みの運用手順書で行います。 このページの点検順序で変更の影響と復旧経路を確認し、インストール済みバージョンの管理コマンドを 運用手順書に反映します。 ## 構成要素 | 役割 | 確認対象 | |------|------| | Coordinator | ノード構成と状態 | | Deployer | パッケージとノードのデプロイ | | Broker | クライアント接続とクエリルーティング | | Warehouse | データ保存とクエリ処理 | | Lookup | 参照データサービス | ノード数と配置は、可用性、スループット、障害ドメインの要件を基準に設計します。 固定のノード数やハードウェア仕様をすべての環境に当てはめないでください。 ## 状態確認 変更前後に、Coordinator から見た全体のノード構成と、各ノードのプロセス・リソースを確認します。 状態文字列とコマンドオプションは、インストール済みツールのヘルプを基準にします。 ```bash machcoordinatoradmin --help machclusterctl --help ``` - 予定したノードがすべて登録されているか。 - ノードの役割、ホスト、ポート、グループがデプロイ記録と一致するか。 - サービス・複製・scrap の状態が正常か。 - ノード間で CPU・メモリ・ディスク・ネットワークの偏りがあるか。 - Broker 経由の実際の接続とクエリが成功するか。 ## 接続と設定のエクスポート `machclusterctl connect` では対象 Broker とネイティブポートを明示し、`CURRENT_DATABASE()` と サンプルクエリを確認します。設定のエクスポートにはホスト・ポート・パス・運用情報が含まれるため、 アクセスを制限し、インポート前に差分を確認します。 ## ノードの起動と停止 ノード制御の前に次を確認します。 1. 対象ノード名・別名・ホスト・役割 2. クライアント接続と進行中のクエリ・Appender 3. Warehouse グループの冗長性とデータ状態 4. ノード停止中に残る処理容量 5. 起動・停止順序とロールバック 6. メンテナンス後の正常性判定基準 強制停止は正常停止が繰り返し失敗し、データと復旧への影響を判断した場合だけ使用します。 単なるタイムアウトに対して直ちに kill しないでください。 ## Cluster 全体の制御と destroy 全体の起動・停止では、Coordinator、Deployer、Broker、Warehouse、Lookup の依存順序を 現行リリースの運用手順で確認します。`destroy` はノード構成とデータを削除し得る破壊的操作です。 - 似た名前の別クラスターでないことを確認。 - 最新バックアップとリストアの検証。 - サービス所有者の承認とクライアントの遮断。 - 外部 `DBS_PATH` を含む削除範囲の確認。 - ロールバックできない範囲の明示。 - 実行後に各ホストの残存プロセスとパスを確認。 通常の状態復旧に `destroy` を使用しないでください。 ## ノードの追加と削除 追加前にパッケージ、バージョン、ポート、パス、ファイルシステム、ネットワークを確認します。 削除前にはデータの冗長性と移行完了、対象ノードを参照する別名・グループ・監視を確認します。 ノードの remove はホームとデータパスを削除する場合があるため、正確な範囲をヘルプと検証環境で確認します。 ## 状態変更 Broker の無効化、Warehouse グループの読み取り専用化、ノードの scrap は目的が異なります。 問題のあるノードを隠すために状態を任意変更してはいけません。 | 目的 | 先に確認すること | |------|-----------| | 新規接続の遮断 | Broker のドレインと既存接続 | | 書き込み停止 | Warehouse グループと進行中の Append | | ノードの隔離 | 複製問題・データ破損の根拠 | | サービス復帰 | 正常性、データ同期、サンプルクエリ | ## Warehouse の復旧 1. 障害時刻と最初のエラーを保存します。 2. プロセス、ディスク、ネットワーク、複製状態を確認します。 3. 残存ノードの冗長性とサービス影響を評価します。 4. 再起動、reattach、rebuild から対応する経路を選びます。 5. 復旧の進捗とエラーを監視します。 6. 完了後にノード別の行数・時間範囲とクエリ結果を比較します。 データ破損を確認せず、ノードを normal に強制変更しないでください。 ## 制約とチェックリスト Edition 別の SQL、ROLLUP、バックアップ、ALTER SYSTEM の対応は [サポート範囲](/ja/dbms/reference/support-scope-constraints/)を確認してください。 - 全ノードとクライアント SDK のリリースが互換か。 - メンテナンス中に許可する読み書きの範囲が定義されているか。 - バックアップ・リストアとノード復旧の訓練を完了したか。 - ホスト・ポート・パスを2名で相互確認したか。 - 監視と通知が新しいノード構成を反映しているか。 - 変更後に Broker 接続、クエリ、Append、メタデータを検証したか。 --- title: "14. アカウント・権限・アクセス制御" url: https://docs.machbase.com/ja/dbms/security-access-control/ language: ja kind: section --- # 14. アカウント・権限・アクセス制御 運用環境のデータを保護するには、アカウント、権限、アクセス制御を体系的に設定する必要があります。 この章ではセキュリティモデル全体と、実務に合った設定方法を説明します。 ## この章の構成 | 順序 | 節 | 説明 | |-----:|------|------| | 14.1 | [セキュリティモデルの概要](./security-model/) | セキュリティ構造、初期アカウント、権限、AUTH KEY 認証 | | 14.2 | [アカウント管理](./account/) | ユーザー作成・削除・パスワード変更、ポリシー(NONE/LOW/HIGH) | | 14.3 | [権限管理](./privileges/) | GRANT/REVOKE、テーブル権限、データベース権限 | | 14.4 | [AUTH KEY 認証](./authentication-auth-key/) | 公開鍵 challenge 認証、鍵の生成・登録・管理 | | 14.5 | [アクセス制御](./access-control/) | リモート接続の許可とバインド IP | | 14.6 | [セキュリティ設定チェックリスト](./checklist-configuration/) | 運用デプロイ前の点検 | ## セキュリティの4領域 **1. セキュリティモデル** — アカウント、権限体系、認証方式の連携構造を理解します。 SYS は管理専用とし、各ユーザーには最小権限だけを付与します。 **2. アカウント管理** — データベースへアクセスする主体を管理します。ユーザーを作成・削除し、 パスワードポリシー(NONE/LOW/HIGH)と公開鍵による AUTH KEY 認証を適用します。 **3. 権限管理** — アカウントの操作を制限します。テーブル単位の DML 権限 (SELECT、INSERT、DELETE、UPDATE)と、データベース単位の DDL・運用権限 (CREATE、DROP、ALTER、BACKUP、MOUNT)を分け、最小権限の原則を適用します。 **4. アクセス制御** — 接続を許可するネットワーク経路を制御します。`GRANT_REMOTE_ACCESS` で リモート接続の可否、`BIND_IP_ADDRESS` でリスナーを開くネットワークインターフェースを指定します。 --- title: "14.1 セキュリティモデルの概要" url: https://docs.machbase.com/ja/dbms/security-access-control/security-model/ language: ja kind: page --- # 14.1 セキュリティモデルの概要 Machbase のセキュリティモデルは、**ユーザーアカウント**、**権限(GRANT/REVOKE)**、 **アクセス制御(IP/認証)**を階層的に組み合わせた構造です。 ## Machbase のセキュリティ構造 ``` クライアントの接続要求 │ ▼ ┌────────────────────────────┐ │ アクセス制御 │ BIND_IP_ADDRESS, GRANT_REMOTE_ACCESS │ (ネットワーク層) │ └────────┬───────────────────┘ │ 許可 ▼ ┌────────────────────────────┐ │ 認証 │ パスワード認証または AUTH KEY(公開鍵)認証 │ (ユーザー識別) │ └────────┬───────────────────┘ │ 認証成功 ▼ ┌────────────────────────────┐ │ 権限確認 │ GRANT/REVOKE で付与した権限を確認 │ (操作許可の判定) │ テーブル権限 + データベース権限 └────────────────────────────┘ ``` 接続要求はまずネットワークアクセス制御を通過し、次にユーザー認証を行い、最後に操作に必要な 権限が付与されているかを確認します。 ## 初期アカウント: SYS インストール時に `SYS` アカウントが自動作成されます。SYS はスーパーユーザーとしてすべての データベース操作を実行でき、他のユーザーの作成と権限付与を行います。 | 項目 | 内容 | |------|------| | アカウント名 | `SYS` | | 初期パスワード | `MANAGER` | | 権限 | 全権限(スーパーユーザー) | | 削除 | 不可 | > **運用環境で必須の対応**: インストール直後に SYS の初期パスワード(`MANAGER`)を変更してください。 > > ```sql > ALTER USER SYS IDENTIFIED BY '新しい_パスワード'; > ``` ## 関連文書 - ユーザーのライフサイクルとパスワードポリシー: [アカウント管理](../account/) - データベース・テーブル権限と GRANT/REVOKE: [権限管理](../privileges/) - 公開鍵の登録・ローテーション: [AUTH KEY 認証](../authentication-auth-key/) - リモート接続とリスナー: [アクセス制御](../access-control/) アカウント作成、権限付与、認証設定は別々の作業です。以下のアカウントとテーブルを用意し、 各アカウントで接続し直して、許可した操作と制限した操作を確認してください。 ## 最小権限の原則 運用環境では次の原則を適用します。 - **SYS は管理専用**: 日常のデータ検索や入力に SYS を使わないでください。 - **用途別アカウント**: 読み取り、入力、デプロイ(DDL)、バックアップのアカウントを分けます。 - **テーブル単位の制限**: 必要なテーブルに必要な DML 権限だけを付与します。 - **定期点検**: 不要アカウントを削除し、過剰権限のアカウントを確認します。 ```sql -- 読み取り専用アカウント CREATE USER reader IDENTIFIED BY 'Reader#Strong123'; GRANT SELECT ON sys.sensor_log TO reader; -- 入力専用アカウント CREATE USER writer IDENTIFIED BY 'Writer#Strong123'; GRANT SELECT, INSERT ON sys.sensor_log TO writer; -- DDL 専用アカウント(テーブルの作成・削除) CREATE USER deploy IDENTIFIED BY 'Deploy#Strong123'; GRANT CONNECT ON DATABASE factory_a TO deploy; GRANT DDL ON DATABASE factory_a TO deploy; ``` --- title: "14.2 アカウント管理" url: https://docs.machbase.com/ja/dbms/security-access-control/account/ language: ja kind: page --- # 14.2 アカウント管理 アプリケーションと運用作業には別々のアカウントを使います。`SYS` はユーザーと権限の管理に限定し、 日常のクエリ・ロードには必要最小限の権限を持つアカウントを使用してください。 ## ユーザーの作成と削除 ```sql CREATE USER app_user IDENTIFIED BY 'App#Strong123' PASSWORD POLICY HIGH; SELECT USER_ID, NAME, PWD_POLICY_LEVEL, VALID_BEFORE FROM M$SYS_USERS WHERE NAME = 'APP_USER'; ``` ユーザー名は大文字で保存されます。論理データベースへ接続するには、アカウント作成後に 対象データベースの `CONNECT` を別途付与します。 ```sql GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO app_user; ``` パスワード変更時は、新しいパスワードとポリシーを同時に指定できます。 ```sql ALTER USER app_user IDENTIFIED BY 'App#Changed456' PASSWORD POLICY HIGH; ``` ユーザー削除前に、実行中のセッション、付与した権限、所有オブジェクトを確認します。 オブジェクトを所有しているユーザーは削除できません。 ```sql DROP USER app_user; ``` `SYS` と現在接続中の自分のアカウントは削除できません。`machsql` で別のアカウントに切り替えるには、 `CONNECT user/password;` で新しいセッションを認証するか、クライアントを再接続します。 ### アクティブセッションを持つユーザーの削除 他の管理セッションからユーザーを削除しても、そのユーザーで認証済みのセッションは直ちに終了しません。 既存セッションはログイン時のユーザー名と内部 ID を保持しますが、削除されたユーザーは新規接続できず、 `M$SYS_USERS` にも表示されません。削除前にアクティブセッションを確認し、アプリケーション接続を先に終了します。 Machbase 8.7.0 以降では、既存セッションのユーザーコンテキストを [CURRENT_USER と SESSION_USER](../../reference/sql/functions/functions-full/#current-session-user)で確認できます。 ## パスワードポリシー | ポリシー | 主な動作 | |---|---| | `NONE` | 互換性のためのデフォルト。強度・有効期限の制約なし | | `LOW` | 長さと文字の組み合わせを検査 | | `HIGH` | LOW の検査、最近のパスワードの再利用制限、有効期間 | LOW と HIGH は10文字以上を要求します。大文字・小文字の検査は `ENABLE_CASE_SENSITIVE_PASSWORD` の 影響を受けます。HIGH は設定時点から90日後を `VALID_BEFORE` に記録します。 ```sql CREATE USER reader_user IDENTIFIED BY 'Reader#Strong123' PASSWORD POLICY HIGH; ALTER USER reader_user IDENTIFIED BY 'Reader#Changed456' PASSWORD POLICY LOW; ``` ポリシーだけを変更せず、新しいパスワードも指定します。現在のポリシーと有効期限は次で確認します。 ```sql SELECT USER_ID, NAME, PWD_POLICY_LEVEL, VALID_BEFORE FROM M$SYS_USERS ORDER BY USER_ID; ``` `PWD_POLICY_LEVEL` は `0=NONE`、`1=LOW`、`2=HIGH` です。パスワードをアプリケーションに直接 記述せず、運用環境のシークレット管理手段を使ってください。全構文は [USER/AUTH 構文](/ja/dbms/reference/sql/syntax/user-auth-syntax/#create-drop-alter-user)を参照してください。 --- title: "14.3 権限管理" url: https://docs.machbase.com/ja/dbms/security-access-control/privileges/ language: ja kind: page --- # 14.3 権限管理 Machbase の権限は、アクティブデータベース単位の管理権限と、特定テーブルの DML 権限に分かれます。 ユーザーにはデータベース接続用の `CONNECT` と、実際の操作対象に必要な権限の両方が必要です。 ```sql GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO app_user; ``` ## 権限モデル | 範囲 | 権限 | 用途 | |---|---|---| | アクティブデータベース | `CONNECT` | 接続と `USE` | | アクティブデータベース | `CREATE`, `DROP`, `ALTER` | オブジェクトの作成・削除・変更 | | アクティブデータベース | `BACKUP` | データベースのバックアップ | | アクティブデータベース | `DDL` | `CREATE` と `DROP` の組み合わせ | | アクティブデータベース | `ALL` | `CONNECT`, `CREATE`, `DROP`, `ALTER`, `BACKUP` | | マウントされたデータベース | `USAGE` | マウント内の参照 | | 管理データベース | `MOUNT` | `MOUNT DATABASE`, `UMOUNT DATABASE` | | テーブル | `SELECT`, `INSERT`, `DELETE`, `UPDATE` | 特定テーブルの DML | | テーブル | `ALL` | 4種類のテーブル DML 権限 | データベースの `ALL` にテーブル DML や `MOUNT` は含まれません。テーブルの `ALL` にも データベース管理権限は含まれません。権限があっても、テーブルタイプが非対応の DML は実行できません。 例えば LOG は `UPDATE` をサポートしません。 ## GRANT / REVOKE ```sql GRANT privilege_list ON target TO user_name; REVOKE privilege_list ON target FROM user_name; ``` 次の例は、ユーザーにデータベース接続と1テーブルの読み書きを許可します。 ```sql GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO app_user; REVOKE INSERT ON TABLE factory_a.sys.sensor_log FROM app_user; REVOKE CONNECT ON DATABASE factory_a FROM app_user; ``` テーブルは現在のデータベースの `owner.table` または `database.owner.table` で指定できます。 データベース全体に `SELECT` などの DML 権限を付与する構文はサポートされません。 現在の権限記録は `M$SYS_USER_ACCESS` で確認します。 ```sql SELECT DB_NAME, USER_NAME, OWNER_NAME, TABLE_NAME, PRIV FROM M$SYS_USER_ACCESS WHERE USER_NAME = 'APP_USER' ORDER BY DB_NAME, OWNER_NAME, TABLE_NAME; ``` `OWNER_NAME` と `TABLE_NAME` が `NULL` ならデータベース単位、値があればテーブル単位の記録です。 `PRIV` は複数権限を表すビットマスクです。表示された数値を単独の権限名と解釈したり、 運用スクリプトに固定したりしないでください。 ## データベース権限 ユーザーを作るだけでは論理データベースに接続できません。対象データベースの `CONNECT` を明示的に 付与し、必要な管理権限を最小単位で追加します。 ```sql GRANT CONNECT ON DATABASE factory_a TO deploy_user; GRANT DDL ON DATABASE factory_a TO deploy_user; GRANT ALTER ON DATABASE factory_a TO deploy_user; ``` 新規ユーザーに記録されるデフォルトの互換権限は、デフォルトデータベース `MACHBASEDB` の範囲です。 他の論理データベースへ自動的には拡張されません。 ### SELECT / INSERT / DELETE / UPDATE DML 権限は特定テーブルに対して付与します。 ```sql GRANT SELECT ON sys.sensor_log TO reader_user; GRANT INSERT ON sys.sensor_log TO writer_user; GRANT DELETE ON sys.device_config TO maint_user; GRANT UPDATE ON sys.device_config TO maint_user; ``` `DELETE` と `UPDATE` の付与前に、対象タイプの条件制約も確認します。TAG の変更にはタグと時間条件、 VOLATILE の変更には主キー条件が必要です。 ### CREATE / DROP ```sql GRANT CREATE ON DATABASE factory_a TO deploy_user; GRANT DROP ON DATABASE factory_a TO deploy_user; ``` `DROP` は復旧が難しい変更を許可するため、ロード・検索専用アカウントには付与しないでください。 オブジェクト所有権だけでは、他のデータベースへ接続できません。 ### ALTER ```sql GRANT ALTER ON DATABASE factory_a TO deploy_user; ``` `ALTER` はテーブル構造と運用設定の変更に影響します。アプリケーションとは別のデプロイ・運用アカウントに だけ付与し、変更後に現在の設定とスキーマを再取得してください。 ### BACKUP ```sql GRANT BACKUP ON DATABASE factory_a TO backup_user; ``` SQL 権限とは別に、サーバープロセスの OS アカウントにはバックアップパスへの書き込み権限と空き容量が 必要です。バックアップ用ユーザーに DML・DDL 権限を併せて付与しない構成を推奨します。 ### MOUNT ```sql GRANT MOUNT ON DATABASE MACHBASEDB TO recovery_user; ``` MOUNT/UMOUNT は管理操作です。マウントされたデータベースを参照する `USAGE` と、そのテーブルを読む `SELECT` は別の権限です。実際の復旧は [バックアップ・リストア・マウント](/ja/dbms/operations-configuration-recovery/backup-restore-mount/)に従ってください。 ### DDL / ALL の複合権限 ```sql -- CREATE + DROP GRANT DDL ON DATABASE factory_a TO deploy_user; -- アクティブデータベースの CONNECT, CREATE, DROP, ALTER, BACKUP GRANT ALL ON DATABASE factory_a TO database_admin; -- 1つのテーブルの SELECT, INSERT, DELETE, UPDATE GRANT ALL ON TABLE factory_a.sys.sensor_log TO table_admin; ``` 複合権限は便利ですが、最小権限の確認を難しくする場合があります。自動化アカウントには、 可能な限り個別の権限を付与してください。 ## デフォルト権限と対象外の権限 `CREATE USER` で作ったユーザーには、`MACHBASEDB` のデフォルト互換権限が記録されます。 論理データベースでは、次のように必要な範囲を明示する構成を基本にします。 ```sql GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO app_user; ``` `ALTER`、`BACKUP`、`MOUNT`、`USAGE` と他の論理データベースの権限は、業務上の役割を確認して 別途付与します。 ## テーブル権限 テーブル権限は必ず対象オブジェクトとともに管理します。 ```sql GRANT SELECT ON TABLE factory_a.sys.sensor_log TO reader_user; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO ingest_user; REVOKE INSERT ON TABLE factory_a.sys.sensor_log FROM ingest_user; ``` テーブルを削除すると既存の grant も削除され、同名の新オブジェクトには引き継がれません。 必要な権限を再付与し、`M$SYS_USER_ACCESS` で確認してください。 ## 権限診断チェックリスト ユーザーと権限を次の順序で確認します。 ```sql SELECT USER_ID, NAME, PWD_POLICY_LEVEL, VALID_BEFORE FROM M$SYS_USERS ORDER BY USER_ID; SELECT DB_NAME, USER_NAME, OWNER_NAME, TABLE_NAME, PRIV FROM M$SYS_USER_ACCESS ORDER BY USER_NAME, DB_NAME, OWNER_NAME, TABLE_NAME; ``` - 未使用アカウントが残っていないか確認します。 - 読み取り用アカウントに書き込み・DDL・管理権限がないか確認します。 - 承認期間が終了した一時権限を `REVOKE` し、結果を再取得します。 - ユーザー削除前に所有オブジェクトと実行中のセッションを確認します。 - `PRIV` を数値から解釈する監査ツールは、稼働バージョンの権限定義と併せて検証します。 --- title: "14.4 AUTH KEY 認証" url: https://docs.machbase.com/ja/dbms/security-access-control/authentication-auth-key/ language: ja kind: page --- # 14.4 AUTH KEY 認証 AUTH KEY 認証は、サーバーに公開鍵を登録し、クライアントの秘密鍵でサーバーの challenge に署名する方式です。 パスワードの代わりに秘密鍵を使えますが、秘密鍵の保護と交換は別途管理します。接続ごとに `AUTH_MODE=PASSWORD` または `AUTH_MODE=CHALLENGE` を選択します。 ## 準備 1. アプリケーション専用ユーザーを作成します。 2. クライアントホストで鍵ペアを生成します。 3. 公開鍵だけをサーバーに登録します。 4. 秘密鍵ファイルをクライアントのシークレットストアに保管します。 5. CHALLENGE 接続を確認し、鍵の有効期限と交換予定を記録します。 対応する鍵と AUTH KEY SQL の全構文は [USER/AUTH 構文](/ja/dbms/reference/sql/syntax/user-auth-syntax/#auth-key)を参照してください。 ## ユーザーの AUTH KEY 管理 登録状態は `V$USER_AUTH_KEYS` で確認します。 ```sql SELECT KEY_ID, USER_NAME, KEY_ALGO, KEY_PARAM, ACTIVATED, VALID_AFTER, VALID_BEFORE, COMMENT FROM V$USER_AUTH_KEYS WHERE USER_NAME = 'APP_USER' ORDER BY KEY_ID; ``` `PUBKEY` には公開鍵本文があるため、通常の運用レポートには含めないことを推奨します。 ### CREATE USER ... WITH AUTH KEY ユーザー作成と同時に公開鍵を登録できます。以下の文字列を、実際の PEM の改行を `\n` で表した値に 置き換えてください。 ```sql CREATE USER app_user IDENTIFIED BY 'App#Strong123' WITH AUTH KEY ( key='-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n', valid_before='2047-12-31', comment='initial application key' ); ``` パスワードを緊急復旧経路として使う場合もあるため、別の強力な値とポリシーで管理します。 ### ALTER USER ... ADD AUTH KEY 既存ユーザーには次のように新しい公開鍵を追加します。 ```sql ALTER USER app_user ADD AUTH KEY ( key='-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n', valid_before='2047-12-31', comment='replacement key' ); ``` 登録後、新しい `KEY_ID`、アルゴリズム、アクティブ状態、有効期限を確認します。 ### AUTH KEY の有効化と無効化 ```sql ALTER USER app_user DEACTIVATE AUTH KEY ID 3; ALTER USER app_user ACTIVATE AUTH KEY ID 3; ``` 無効化は鍵メタデータを保持したまま認証を遮断します。運用中の鍵を無効化する前に、 別の認証経路が実際に機能することを確認してください。 ### AUTH KEY の有効期限変更 ```sql ALTER USER app_user ALTER AUTH KEY ID 3 VALID_BEFORE='2048-06-30'; ``` 期限を延長する前に、利用主体と保管状態を再確認します。有効期間を延ばしても鍵自体は変わらないため、 ローテーション周期は別途管理します。 ### AUTH KEY の削除 ```sql ALTER USER app_user DROP AUTH KEY ID 3; ``` 削除は取り消せません。新しい鍵での接続成功と、古い鍵が無効であることを確認してから削除します。 ユーザーを削除すると、そのユーザーの AUTH KEY も削除されます。 ## 鍵のローテーション 1. 新しい鍵ペアを生成します。 2. 新しい公開鍵を `ADD AUTH KEY` で登録します。 3. 新しい秘密鍵で CHALLENGE 接続を検証します。 4. 古い鍵を無効化し、その鍵での接続失敗を確認します。 5. 観察期間が終わったら古い鍵を削除します。 古い鍵を一度に上書きしないことで、サービスを停止せずに交換結果を検証できます。 ## AUTH KEY challenge 認証 クライアントは、登録済み公開鍵と対になる秘密鍵ファイルを読める必要があります。秘密鍵自体は サーバーに登録しません。ファイルがない、秘密鍵が登録鍵と一致しない、登録鍵が無効または期限切れなら CHALLENGE 認証は失敗します。PASSWORD へ自動切り替えしないため、必要なら別の PASSWORD 接続を明示します。 ## SYS AS USER 認証の制約 `SYS` で CHALLENGE 認証を使う場合も、`SYS` に AUTH KEY の登録が必要です。ただしアプリケーションの 接続に `SYS` を使わず、専用アカウントへ最小権限と鍵を付与してください。`SYS` の鍵は、 別の管理経路を検証済みのメンテナンス時間に変更します。 ## AUTH_MODE=CHALLENGE `machsql` では接続文字列と秘密鍵オプションを併せて指定します。 ```bash machsql -s 127.0.0.1 -P 5656 -u app_user \ -c "AUTH_MODE=CHALLENGE" \ -K /secure/path/app_user.key ``` JDBC 接続プロパティの例は次のとおりです。 ```text jdbc:machbase://127.0.0.1:5656/machbasedb?AUTH_MODE=CHALLENGE&AUTH_KEY_FILE=/secure/path/app_user.key ``` 秘密鍵ファイルの内容、パスワード、接続文字列のシークレットをログやエラーレポートに残さないでください。 ## AUTH_KEY_FILE 秘密鍵はクライアントホストで生成し、SQL 登録には公開鍵だけを使います。ECDSA P-256 鍵ペアは 例えば次のように生成できます。 ```bash openssl ecparam -name prime256v1 -genkey -noout -out app_user.key openssl ec -in app_user.key -pubout -out app_user.pub chmod 600 app_user.key ``` `chmod 600` は秘密鍵の露出を減らすための運用上の推奨です。実行プロセスのアカウントがファイルと 親ディレクトリへアクセスできることも確認します。公開鍵を SQL のインライン文字列にする場合、 次のように改行を `\n` で表します。 ```bash awk '{printf "%s\\n", $0}' app_user.pub ``` PKCS#8 を含む実際の秘密鍵形式のサポートは、使用するクライアントと配布バージョンで検証してください。 ## AUTH_SIG_SCHEME | 公開鍵 | 利用できる署名方式 | |---|---| | ECDSA P-256, P-384, P-521 | `ECDSA` | | RSA 2048, 3072, 4096 | `RSA_PKCS1_V15`, `RSA_PSS` | 鍵に適したデフォルト方式を使用できます。RSA-PSS を明示する場合は、クライアントオプションも指定します。 ```bash machsql -s 127.0.0.1 -P 5656 -u app_user \ -c "AUTH_MODE=CHALLENGE" \ -K /secure/path/app_user_rsa.key \ --auth-sig-scheme=RSA_PSS ``` 公開鍵タイプと署名方式が一致しない場合、認証に失敗します。 ## RSA / ECDSA / RSA_PSS のサポート範囲 アルゴリズムはセキュリティポリシー、クライアントのサポート、鍵管理システムとの互換性で選びます。 速度や安全性がどの環境でも同じと決めつけないでください。登録前に、実際のクライアントで 生成・接続・ローテーション・廃棄の全手順を検証します。 --- title: "14.5 アクセス制御" url: https://docs.machbase.com/ja/dbms/security-access-control/access-control/ language: ja kind: page --- # 14.5 アクセス制御 `GRANT_REMOTE_ACCESS`、`BIND_IP_ADDRESS`、OS またはクラウドのファイアウォールを併用して、 ネットワーク接続範囲を制限します。現在値は次のように確認します。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME IN ('GRANT_REMOTE_ACCESS', 'BIND_IP_ADDRESS'); ``` リスナー設定はサーバー起動時に適用されます。稼働中のリスナーが自動的に再バインドされるとは考えず、 `machbase.conf` を変更してから承認済みの再起動手順を実施してください。 ## リモート接続設定 `GRANT_REMOTE_ACCESS` はリモートクライアント接続の可否を制御します。 ```ini # リモート接続を許可 GRANT_REMOTE_ACCESS = 1 # リモート接続を遮断 GRANT_REMOTE_ACCESS = 0 ``` 変更前に次を確認します。 1. アプリケーション、監視、バックアップクライアントの接続元 2. ローカル管理接続を維持する方法 3. 再起動後にリモート・緊急接続の両方を試験する順序 `GRANT_REMOTE_ACCESS=1` で全リモートアドレスを許可することがないよう、 ファイアウォールの許可リストも設定してください。 ## BIND_IP_ADDRESS とネットワーク公開範囲 `BIND_IP_ADDRESS` は IPv4 リスナーがバインドするアドレスです。 ```ini # すべての IPv4 インターフェース BIND_IP_ADDRESS = 0.0.0.0 # ローカル IPv4 インターフェース BIND_IP_ADDRESS = 127.0.0.1 # 指定した内部 IPv4 インターフェース BIND_IP_ADDRESS = 10.0.0.5 ``` サーバーにないアドレスを指定すると起動に失敗する場合があります。変更前に現在のインターフェースを 確認し、再起動後に OS ツールで実際の待ち受けアドレスとポートを検証します。 `0.0.0.0` が必要な場合は、ファイアウォールまたはセキュリティグループで接続元アドレスとポートを 制限します。具体的なコマンドは OS とネットワークポリシーで異なるため、本書の固定コマンドを そのまま適用しないでください。 --- title: "14.6 セキュリティ設定チェックリスト" url: https://docs.machbase.com/ja/dbms/security-access-control/checklist-configuration/ language: ja kind: page --- # 14.6 セキュリティ設定チェックリスト 運用デプロイ前と定期監査時に、次を点検します。 ## アカウントと認証 - インストール直後に、組織のシークレット管理手順で `SYS` の初期パスワードを変更します。 - アプリケーション専用アカウントを作り、通常接続に `SYS` を使わないでください。 - パスワードをソースコード、文書、コマンド履歴に保存しないでください。 - 未使用アカウントと有効期限が近いアカウントを確認します。 - AUTH KEY を使う場合、秘密鍵の保管・交換・廃棄の担当者を決めます。 ```sql SELECT USER_ID, NAME, PWD_POLICY_LEVEL, VALID_BEFORE FROM M$SYS_USERS ORDER BY USER_ID; SELECT USER_NAME, KEY_ID, KEY_ALGO, KEY_PARAM, ACTIVATED, VALID_BEFORE FROM V$USER_AUTH_KEYS ORDER BY USER_NAME, KEY_ID; ``` ## 権限 - 各論理データベースに必要な `CONNECT` だけを付与します。 - 読み取り用アカウントに書き込み・DDL・バックアップ権限がないことを確認します。 - 一時権限の期限と取り消し責任者を記録します。 - ユーザーやテーブルを再作成した後は権限を再検証します。 ```sql SELECT DB_NAME, USER_NAME, OWNER_NAME, TABLE_NAME, PRIV FROM M$SYS_USER_ACCESS ORDER BY USER_NAME, DB_NAME, OWNER_NAME, TABLE_NAME; ``` `PRIV` はビットマスクです。数値を権限名へ変換する独自ツールは、稼働中バージョンの定義と 照合して検証してください。付与・取り消しは[権限管理](../privileges/)を参照します。 ## ネットワーク接続 - リモート接続が必要かを先に決めます。 - `BIND_IP_ADDRESS` を必要な IPv4 インターフェースに限定します。 - ファイアウォールまたはセキュリティグループの接続元許可リストを確認します。 - 設定変更は、再起動と接続検証を含むメンテナンス手順で実施します。 ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME IN ('GRANT_REMOTE_ACCESS', 'BIND_IP_ADDRESS'); ``` ## 変更後の証跡 セキュリティ変更後、次の結果を変更記録に残します。 1. ユーザーと有効期限の検索結果 2. 対象ユーザーとデータベース・テーブル権限の検索結果 3. 許可したアドレスからの接続成功と、許可していないアドレスからの遮断結果 4. AUTH KEY を変更した場合、新しい鍵での接続成功と古い鍵での遮断結果 共有の運用サーバーで `SYS` パスワード、リスナー、ファイアウォールを試験目的で変更しないでください。 別の検証環境で復旧経路まで確認してから、運用変更を承認します。 --- title: "15. トラブルシューティング" url: https://docs.machbase.com/ja/dbms/troubleshooting/ language: ja kind: section --- # 15. トラブルシューティング Machbase 運用中の問題を、症状確認、原因診断、解決、再発防止の順に説明します。 {{< callout type="info" >}} 問題を分類する前に `machadmin -e` で状態を確認し、`$MACHBASE_HOME/trc/machbase.trc` の 直近のエラーとクライアントの `ERR-XXXXX` コードを記録します。 {{< /callout >}} ## この章の構成 | 順序 | 節 | 内容 | |-----:|------|------| | 15.1 | [問題解決へのアプローチ](./troubleshooting/) | 症状収集、診断コマンド、ログとエラーコードの分析 | | 15.2 | [サーバーと接続の問題](./server-connection/) | 起動、リモート接続、認証エラー | | 15.3 | [入力とロードの問題](./item/) | Append と CSV インポートのエラー | | 15.4 | [クエリと性能の問題](./performance/) | 遅いクエリ、空の結果、メモリ、トランザクション競合 | | 15.5 | [バックアップと復旧の問題](./recovery-backup/) | BACKUP、RESTORE、MOUNT、UMOUNT のエラー | | 15.6 | [Cluster の問題](./cluster/) | ノード状態と Cluster Edition のエラー | | 15.7 | [ROLLUP の問題](./rollup/) | 集計遅延、結果の不一致、再構築の判断 | TAG・LOOKUP の UPDATE・DELETE 条件エラーは、各テーブルの制約・トラブルシューティングを参照してください。 解決後は、原因、対策、確認クエリ、再発防止策を運用記録に残します。 --- title: "15.1 問題解決へのアプローチ" url: https://docs.machbase.com/ja/dbms/troubleshooting/troubleshooting/ language: ja kind: page --- # 15.1 問題解決へのアプローチ 再現する前に状態と証拠を保存し、最小範囲から原因を絞り込みます。 ## 5段階の問題解決手順 1. 失敗時刻、実行コマンド、エラーメッセージ全文、`ERR-` コードを記録します。 2. `machadmin -e` と接続試験で、サーバー・ネットワーク・認証のどの段階で失敗したかを区別します。 3. 同時刻のサーバーログとセッション・文の状態を確認します。 4. 原因を1つずつ修正し、同じ入力で再検証します。 5. 原因、対策、検証結果、再発防止策を記録します。 ## 症状の確認 | 症状 | 最初に確認 | |---|---| | サーバーが応答しない | `machadmin -e`、プロセス・ポート、サーバーログ | | 接続拒否 | サーバー状態、待ち受けアドレス、ファイアウォール、ポート | | 認証失敗 | ユーザー、認証方式、有効期限、AUTH KEY 状態 | | SQL 失敗 | SQL 全文、対象データベース・オブジェクト、正確なコード | | 遅いクエリ | 実行計画、時間範囲、スキャン行数、同時負荷 | | ロード停止 | 成功・失敗行数、bad/log ファイル、最後の成功位置 | 診断前にサーバーを再起動したり設定を変えたりすると、最初の原因を示す証拠が失われる場合があります。 ## 診断コマンド ```bash machadmin -e tail -100 "$MACHBASE_HOME/trc/machbase.trc" ``` ```sql SELECT * FROM V$VERSION; SELECT ID, USER_NAME, CLOSED FROM V$SESSION ORDER BY ID; SELECT ID, SESS_ID, STATE, QUERY FROM V$STMT ORDER BY ID; SELECT * FROM V$STORAGE_USAGE; SELECT NAME, VALUE FROM V$PROPERTY ORDER BY NAME; ``` 運用環境の結果には SQL 本文、ユーザー名、パスなどの機密情報が含まれ得るため、共有前に確認してください。 ## ログの確認 デフォルトのサーバーログは `$MACHBASE_HOME/trc/machbase.trc` です。実際のパスとローテーション設定は、 `V$PROPERTY` とインストール設定で確認します。 ```bash tail -100 "$MACHBASE_HOME/trc/machbase.trc" rg -n 'ERR-|ERROR|WARN' "$MACHBASE_HOME/trc/machbase.trc" ``` ログレベルやファイル数を変える前に、現在の `TRACE_LOG_LEVEL`、`TRACE_LOGFILE_SIZE`、 `TRACE_LOGFILE_COUNT`、`TRACE_LOGFILE_PATH` を確認します。障害時の過剰な詳細ログはディスクと性能に影響します。 ## エラーコードによる原因特定 正確なコードを記録し、[エラーコードリファレンス](/ja/dbms/reference/error-codes/)で現行の定義を確認してください。 一覧にない場合は、全文、サーバービルド、再現 SQL、ログ時刻をまとめて収集します。 --- title: "15.2 サーバーと接続の問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/server-connection/ language: ja kind: page --- # 15.2 サーバーと接続の問題 接続問題は、サーバー起動、TCP 接続、ユーザー認証の順に切り分けます。 ## サーバーが起動しない場合 ```bash machadmin -e tail -100 "$MACHBASE_HOME/trc/machbase.trc" ``` 次を順に確認します。 1. 設定ポートを別プロセスが使っていないか。 2. サーバーの OS アカウントがインストール・データ・ログのパスを読み書きできるか。 3. ファイルシステムの容量と inode が十分か。 4. ライセンスがインストールされ、有効か(`machadmin -f`)。 5. 前のプロセスや lock ファイルが残る原因は何か。 原因未確認の強制停止や lock ファイル削除は避けます。正常停止できない場合はログとプロセス状態を 保存し、承認済み復旧手順を使用します。 ## 接続できない場合 サーバーホストで、まずローカル接続を試します。 ```bash machadmin -e machsql -s 127.0.0.1 -P 5656 -u app_user ``` ローカルは成功し、リモートだけ失敗する場合は次を確認します。 - クライアントが使うアドレスとポート - `GRANT_REMOTE_ACCESS`、`BIND_IP_ADDRESS` の現在値 - OS・クラウドのファイアウォールと中間ネットワーク経路 - `MAX_SESSION_COUNT` 到達と未クローズセッション ```sql SELECT NAME, VALUE FROM V$PROPERTY WHERE NAME IN ('GRANT_REMOTE_ACCESS', 'BIND_IP_ADDRESS', 'MAX_SESSION_COUNT'); SELECT ID, USER_NAME, CLOSED FROM V$SESSION ORDER BY ID; ``` リスナー設定は起動時に適用されるため、設定ファイルの変更後にメンテナンス再起動を行い、 リモート・ローカル接続を検証します。ファイアウォール操作は対象 OS の公式文書に従います。 ## 認証が失敗する場合 まず接続で選択した認証方式を確認します。`AUTH_MODE` はサーバーの `V$PROPERTY` ではなく、 クライアントの接続オプションです。 パスワード認証ではユーザー名、パスワードポリシー、有効期限を確認します。 ```sql SELECT USER_ID, NAME, PWD_POLICY_LEVEL, VALID_BEFORE FROM M$SYS_USERS WHERE NAME = 'APP_USER'; ``` AUTH KEY 認証では登録鍵とクライアントオプションを確認します。 ```sql SELECT KEY_ID, USER_NAME, KEY_ALGO, KEY_PARAM, ACTIVATED, VALID_BEFORE FROM V$USER_AUTH_KEYS WHERE USER_NAME = 'APP_USER' ORDER BY KEY_ID; ``` ```bash machsql -s 127.0.0.1 -P 5656 -u app_user \ -c "AUTH_MODE=CHALLENGE" \ -K /secure/path/app_user.key ``` 秘密鍵ファイルが存在してクライアントプロセスが読めるか、公開鍵と対になっているか、鍵が有効で 期限内かを確認します。アカウントロック解除や `CREATE AUTH KEY` など、現行構文にない操作は使わないでください。 登録と交換は [AUTH KEY 認証](/ja/dbms/security-access-control/authentication-auth-key/)に従います。 --- title: "15.3 入力とロードの問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/item/ language: ja kind: page --- # 15.3 入力とロードの問題 ## 入力が失敗する場合 クライアントのエラー全文、対象データベース・テーブル、入力方式、最後の成功行を記録します。 コードの意味は[エラーコードリファレンス](/ja/dbms/reference/error-codes/)で確認し、 このページの固定コード表に依存しないでください。 ```sql DESC target_table; SELECT NAME, TYPE, COLCOUNT FROM M$SYS_TABLES WHERE NAME = 'TARGET_TABLE'; ``` 次を確認します。 - 入力列数・順序・型と NULL 許可 - 現在のデータベースとテーブル所有者 - ユーザーの `CONNECT` とテーブルの `INSERT` 権限 - 時刻文字列の形式と接続タイムゾーン - ファイルシステムの空き容量と `V$STORAGE_USAGE` - Append API の戻り値、失敗行、flush 結果 時刻が逆順の入力や UPDATE/DELETE 条件はタイプによって異なるため、各利用章の制約を確認します。 ## CSV インポートが失敗する場合 現在の配布版のオプションは `machloader -h` で確認します。 ```bash machloader -h machloader -s 127.0.0.1 -P 5656 -u app_user \ -t target_table -i /data/input.csv \ -b /data/input.bad -l /data/input.log ``` 小さいファイルから、次の順に再現します。 1. サーバーではなく loader 実行ホストの絶対パスとファイル権限を確認します。 2. CSV の1行の列数と `DESC target_table` を比較します。 3. エンコーディング名を現行ヘルプと比較します。配布版には `UTF8`、`MS949`、`KSC5601`、`EUCJP` などがあります。 4. 区切り文字と引用符のオプションを実ファイルに合わせます。 5. 日時形式オプションには対象列名と形式を併せて指定します。 6. bad ファイルの最初の失敗行を修正し、別の検証テーブルへロードします。 正確な `-F` 構文とオプションは [machloader コマンド・オプションリファレンス](/ja/dbms/reference/command-line-tools/machloader/)を使ってください。 部分成功後の再試行では、入力済み範囲を確認して重複を防ぎます。 --- title: "15.4 クエリと性能の問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/performance/ language: ja kind: page --- # 15.4 クエリと性能の問題 ## クエリが遅い場合 対象 SQL、バインド値の範囲、開始・終了時刻、期待行数と実際の行数を記録します。 ```sql SELECT ID, SESS_ID, STATE, QUERY FROM V$STMT ORDER BY ID; EXPLAIN SELECT ...; ``` 実行計画で次を確認します。 - 時間・タグ条件が十分早い段階で適用されるか。 - 大きなテーブルを不必要に繰り返しスキャンしていないか。 - 結合キーの型と値の形式が一致するか。 - 必要なインデックスや ROLLUP が実際に使われているか。 - 不要な列や行を読んでいないか。 MINMAX キャッシュの現在のプロパティ名は `DISK_COLUMNAR_TABLE_COLUMN_MINMAX_CACHE_SIZE` です。 変更前に現在値と実行計画を記録し、隔離環境で比較してください。詳細は [性能チューニング](/ja/dbms/performance-tuning/)に従います。 ## 検索結果が期待と異なる場合 ```sql SELECT COUNT(*), MIN(_ARRIVAL_TIME), MAX(_ARRIVAL_TIME) FROM target_log; ``` 1. 対象データベース、所有者、テーブル名を確認します。 2. フィルターなしで少量を読み、データの存在と実際の時刻を確認します。 3. 接続タイムゾーンと入力文字列の時刻解釈を確認します。 4. タグ名、大文字・小文字、境界演算子(`>`、`>=`、`<`、`<=`)を確認します。 5. ROLLUP なら gap と更新状態を確認します。 サーバープロパティ `DEFAULT_TIMEZONE` を探さないでください。タイムゾーンはクライアント接続と セッションで明示し、元データの基準タイムゾーンも記録します。 ```sql SHOW ROLLUPGAP; SELECT * FROM V$ROLLUP; ``` ## メモリ不足 ```sql SELECT * FROM V$SYSMEM; SELECT ID, SESS_ID, STATE, QUERY FROM V$STMT ORDER BY ID; ``` OS メモリ、スワップ、OOM 記録と、同時刻の Machbase ログを併せて確認します。大量結果の一括取得、 大きな結合・ソート、過剰な同時実行、大きなクライアント fetch・Append バッファを個別に再現します。 現在値は `V$PROPERTY` で確認します。許容範囲と変更方法は [設定リファレンス](/ja/dbms/reference/configuration/configuration/)で調べ、1項目ずつ負荷試験して適用します。 --- title: "15.5 バックアップと復旧の問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/recovery-backup/ language: ja kind: page --- # 15.5 バックアップと復旧の問題 ## バックアップ・リストアが失敗する場合 バックアップ失敗時は、サーバープロセスの OS アカウントのパス権限、空き容量、 同じパスの既存バックアップ、サーバーログを確認します。 ```sql SELECT * FROM V$STORAGE_USAGE; ``` ```bash machadmin -e tail -100 "$MACHBASE_HOME/trc/machbase.trc" ``` リストアは既存の物理データベースを置き換える破壊的操作です。サーバーを停止するだけでは不十分で、 既存データベースがあると拒否されます。次は概念的な点検手順であり、そのまま運用コマンドとしてコピーしないでください。 ```text 1. 復旧対象・バックアップパス・バージョン・チェックサムを確認する。 2. 現在のデータベースの保護方法とロールバック条件の承認を得る。 3. サーバーを正常停止する。 4. 承認済み手順で現在の物理データベースを削除する。 5. machadmin restore を実行する。 6. サーバーを起動し、業務検証クエリを実行する。 ``` `machadmin -d` は現在のデータベースを破棄するため、バックアップと明示的な承認なしに実行してはいけません。 正確な構文と制約は[BACKUP/RESTORE/MOUNT 構文](/ja/dbms/reference/sql/syntax/backup-restore-mount-syntax/) を参照してください。 バックアップイメージ確認や MOUNT 成功は初期検証にすぎず、完全な復旧可能性を保証しません。 別環境でのリストアとアプリケーション検証まで定期的に実施します。 ## マウントが失敗する場合 現在の MOUNT 一覧、一意な別名、バックアップパス、サーバープロセスの読み取り権限を確認します。 ```sql SELECT * FROM V$STORAGE_MOUNT_DATABASES; ``` 現行構文ではバックアップパスの後に別名を指定します。 ```sql MOUNT DATABASE '/backup/sc15_snapshot' TO backup_check; SELECT COUNT(*) FROM backup_check.sys.target_table; UMOUNT DATABASE backup_check; ``` 別名の衝突、非対応 Edition、非互換バックアップ、使用中のマウントを区別して対応します。 ファイルを強制削除したり、サーバーメタデータを編集したりしないでください。 --- title: "15.6 Cluster の問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/cluster/ language: ja kind: page --- # 15.6 Cluster の問題 ## Cluster ノードの状態が異常な場合 トポロジー変更や再起動の前に、全体状態と最初のエラーを収集します。 ```bash machcoordinatoradmin --cluster-status machclusterctl status ``` 1. Coordinator、Broker、Warehouse のどの役割が最初に異常となったか確認します。 2. 対象ノードと先行する役割のログ時刻を合わせて比較します。 3. ホスト、プロセス、ディスク、ネットワーク、設定変更履歴を確認します。 4. 複製・再配置の状態とクライアントへの影響を記録します。 5. 13章の承認済み復旧手順で1ノードずつ対応し、全体状態を再検証します。 ノード名やサービス・ノード間ポートを推測して start/add/remove を実行しないでください。 実際の `cluster.yaml` とデプロイツールのヘルプを使います。詳細な制約は [Cluster の運用](/ja/dbms/operations-configuration-recovery/cluster/)を参照してください。 ## Cluster Edition の制限エラー ```sql SELECT * FROM V$VERSION; ``` Edition の制限か判断する際は、現行 Edition と [Edition 別サポート範囲](/ja/dbms/reference/support-scope-constraints/)を比較します。Standard 専用機能の 非公式な回避手順は使わず、同じ要件を満たす Cluster 対応機能や別の Standard 環境を検討してください。 --- title: "15.7 ROLLUP の問題" url: https://docs.machbase.com/ja/dbms/troubleshooting/rollup/ language: ja kind: page --- # 15.7 ROLLUP の問題 ROLLUP の結果が遅れたり元データと異なったりする場合は、処理遅延と集計の意味の違いを区別します。 例の名前を実際の対象テーブル・ジョブへ置き換え、最初の対策として削除・再作成を行わないでください。 ## 1. 状態と範囲の確認 ```sql SELECT ROLLUP_NAME, ROLLUP_TABLE, ROOT_TABLE, EXT_TYPE, INTERVAL_TIME, WAKEUP_INTERVAL, ENABLED, RUN_STATE, LAST_ELAPSED_MSEC FROM V$ROLLUP ORDER BY ROLLUP_NAME; SHOW ROLLUPGAP; ``` SHOW ROLLUPGAP は machsql コマンドであり、SDK の SQL API へ送信しません。gap は RID の処理差で、 時間遅延や元データ補正の完了を直接表す値ではありません。各階層・Cluster ノードの状態、 サーバービルド、データベース、所有者を併せて記録します。 ## 2. 同じデータセットを比較 | 症状 | 確認事項 | |---|---| | 一部サンプルがない | 条件付き ROLLUP 候補と元データのフィルターが一致するか | | FIRST/LAST エラー | 選択された候補が EXTENSION か | | 月・日クエリに候補がない | 保存間隔の選択規則とクエリバケットを混同していないか | | 平均が異なる | NULL、有効件数、部分平均の再集計、タグ単位が同じか | | 元データ修正後も値が変わらない | FORCE で過去に戻そうとしていないか、REBUILD の対象か | | JSON 件数が異なる | 元文書、SQL NULL、パス別件数、文書集計件数を区別したか | 元データは DATE_TRUNC/DATE_BIN と GROUP BY、保存集計は rollup() で取得し、比較します。 タグ、時刻、origin、終了境界、集計関数を固定します。対応 ROLLUP がない場合に、 rollup() が元データのスキャンへ自動で切り替わるとは考えないでください。 ## 3. 新しい入力への追従 対象ジョブが有効か確認し、必要なジョブを名前で指定します。 ```sql ALTER ROLLUP rollup_name FORCE; SHOW ROLLUPGAP; ``` WAKEUP は起床させるだけで、FORCE は処理範囲に追いつくまで待ちます。停止中のジョブは状態を確認して START し、複数階層は下位から処理します。`ALTER SYSTEM FLUSH ROLLUP` は非サポートなので 診断コマンドとして使用しないでください。 ## 4. 過去データの補正と再構築 Standard Edition でも、すべての ROLLUP 構成が REBUILD 対象ではありません。完全な自動階層か、 Custom 間隔・バケットが対応するか、元データが残っているかを先に確認します。時間引数には 対応する定数文字列または TO_DATE を使います。指定時刻を含むバケット全体が再計算されます。 関連ジョブの停止・再起動と部分失敗を考慮します。成功・失敗の後も結果と実際の有効状態を確認し、 [REBUILD 演習](../../tag-rollup-usage/rollup-rebuild/)と [引数の仕様](../../reference/sql/syntax/rollup-rebuild-syntax/)に従います。 ## 5. サポート依頼の資料 - サーバービルド、Edition、クライアント、接続先 - TAG スキーマ、ROLLUP 定義、条件、依存関係 - 状態・gap と観測時刻 - 比較した元データ/ROLLUP SQL、タイムゾーン・origin、期待値・実測値 - 最初のエラーと直近の元データ補正・削除・大量入力・設定変更 --- title: "16. リファレンス" url: https://docs.machbase.com/ja/dbms/reference/ language: ja kind: section --- # 16. リファレンス 構文、関数、設定、システムカタログの正確な定義を確認するための総合リファレンスです。 SDK/APIドキュメントは第11章「開発とアプリケーション連携」を、概念や使用例は各機能の章を参照してください。 ## 構成 | セクション | 説明 | |------|------| | [SQLリファレンス](./sql/) | SQL構文辞典、関数辞典、データ型、ヒント、相対時間式 | | [設定リファレンス](./configuration/) | machbase.confのプロパティ、動的に変更できるプロパティ一覧 | | [コマンドラインツール](./command-line-tools/) | machsql、machadmin、machloaderなどのCLIツールのオプション | | [開発ツール連携](../development-tools-integration/) | Go、Python、Java、CのクライアントSDK/API(第11章) | | [システムカタログ](./system-catalog/) | V$、M$SYSビュー一覧と列の説明 | | [エラーコード](./error-codes/) | エラー番号、メッセージ、原因、対処方法 | | [サポート範囲と制約](./support-scope-constraints/) | テーブルタイプ別の機能サポート可否と既知の制約 | | [AI Agent Reference](./ai-agent-reference/) | AI・RAG向けの案内、正式な参照先のマップ、LLM出力 | ## 活用方法 - **構文の確認** → [SQL構文辞典](./sql/syntax/) - **関数の引数と戻り値** → [SQL関数辞典](./sql/functions/) - **データ型の範囲とデフォルト値** → [データ型辞典](./sql/types/) - **設定値の意味と許容範囲** → [設定リファレンス](./configuration/) - **エラー原因の特定** → [エラーコード](./error-codes/) > 動作の仕組み、選択基準、運用ガイドは、該当機能の章を参照してください。 --- title: "16.1 SQLリファレンス" url: https://docs.machbase.com/ja/dbms/reference/sql/ language: ja kind: section --- # 16.1 SQLリファレンス SQL構文、関数、データ型、クエリヒント、相対時間式の正確な定義を提供します。 ## 下位セクション | セクション | 説明 | |------|------| | [SQL構文辞典](./syntax/) | CREATE、DROP、ALTER、SELECT、WITH/CTE、INSERT、DELETE、UPDATE、BACKUP、MOUNTなど全SQL文のBNF構文と例 | | [関数辞典](./functions/) | 集約、数学、文字列、日付/時刻、型変換、TAG専用関数の一覧と説明 | | [データ型辞典](./types/) | 対応するデータ型のサイズ、範囲、デフォルト値、テーブルタイプ別の使用可否 | | [SELECT hint syntax](./syntax/select-hint-syntax/) | SELECTヒントの構文、使用方法、適用対象 | | [相対時間式辞典](./relative-time/) | `now - 1h`形式の相対時間リテラルと接尾辞 | | [ROWID](./rowid/) | テーブル別のROWIDの意味、参照条件、INSERT結果 | ## SQLの特徴 ANSI SQLを基に、時系列データ処理に最適化した拡張構文を提供します。 - **TAG時系列機能**: BASETIME, METADATA, `FIRST`/`LAST`, `SERIES BY`, ROLLUP - **時間範囲の参照**: `DURATION`、`BEFORE`、`AFTER`、`RANGE`句 - **共通テーブル式**: Standard Editionの非再帰`WITH`/CTE - **大量取り込みの連携**: クライアントSDKのAppend API(SQL文とは別の取り込みAPI) - **テキスト検索**: `SEARCH`、`ESEARCH`、`REGEXP`演算子 - **集合演算**: `UNION ALL`(UNION、INTERSECT、EXCEPTは非対応) --- title: "16.1.1 SQL構文リファレンス" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/ language: ja kind: section --- # 16.1.1 SQL構文リファレンス SQL構文リファレンスは、MachbaseがサポートするすべてのSQL構文のBNF表記と最小限の例を提供します。 ## サポートするSQL構文の一覧 | 構文 | 分類 | 説明 | |------|------|------| | [CREATE TABLE](./ddl-syntax/#create-table) | DDL | LOG/TAG/LOOKUP/VOLATILE/TRANSACTIONテーブルの作成 | | [DROP TABLE](./ddl-syntax/#drop-table) | DDL | テーブルの削除 | | [ALTER TABLE](./ddl-syntax/#alter-table) | DDL | テーブルスキーマの変更(列の追加・削除・変更・名前変更) | | [TRUNCATE TABLE](./ddl-syntax/#truncate-table) | DDL | テーブルの全データを削除 | | [CREATE INDEX](./index-syntax/#create-index) | DDL | 条件付き作成とテーブルタイプ別のインデックス対応 | | [DROP INDEX](./index-syntax/#drop-index) | DDL | インデックスの削除 | | [CREATE ROLLUP](./rollup-syntax/#create-rollup) | DDL | TAGテーブルのROLLUP定義を作成 | | [DROP ROLLUP / ALTER ROLLUP](./rollup-syntax/#drop-rollup) | DDL | ROLLUPの削除と制御 | | [CREATE RETENTION](./retention-syntax/#create-retention) | DDL | データ保持ポリシーの作成 | | [CREATE VIEW / DROP VIEW](./view-syntax/) | DDL | 保存ビューの作成と削除 | | [CREATE TABLESPACE](./ddl-syntax/#create-tablespace) | DDL | テーブルスペースの作成 | | [INSERT INTO](./dml-syntax/#insert-into) | DML | 単一行・複数行のデータ挿入 | | [INSERT SELECT](./dml-syntax/#insert-select) | DML | クエリ結果を別のテーブルへ挿入 | | [UPDATE](./dml-syntax/#update) | DML | TRANSACTION/LOOKUP/VOLATILEの行更新と、条件を制限したTAGデータの補正 | | [DELETE](./dml-syntax/#delete) | DML | テーブルデータの削除 | | [LOAD DATA INFILE](./load-data-infile-syntax/) | DML | CSVファイルから直接データを取り込み | | [SELECT](./select-syntax/) | SELECT | データ検索(JOIN、GROUP BY、ORDER BY、LIMITを含む) | | [WITH / CTE](./cte-syntax/) | SELECT | Standard Editionの非再帰共通テーブル式 | | [Named Bind Parameter](./named-bind-parameter-syntax/) | SQL共通 | `:name`形式の値パラメーター | | [CAST](../functions/functions-full/#cast) | SQL式 | 値を指定したデータ型へ明示的に変換 | | [SAVE DATA INTO](./save-data-into-syntax/) | SELECT | クエリ結果をCSVファイルに保存 | | [BACKUP](./backup-restore-mount-syntax/#backup) | 運用 | データベースまたはテーブルのバックアップ | | [RESTORE](./backup-restore-mount-syntax/#restore) | 運用 | 論理データベースのリストアと、`machadmin -r`によるオフライン復旧 | | [MOUNT / UMOUNT DATABASE](./backup-restore-mount-syntax/#mount-database) | 運用 | バックアップデータベースのマウント・アンマウント | | [CREATE USER / DROP USER / ALTER USER](./user-auth-syntax/#create-drop-alter-user) | ユーザー | ユーザーの作成・削除・パスワード変更 | | [GRANT / REVOKE](./user-auth-syntax/#grant-revoke) | ユーザー | 権限の付与と取り消し | | [AUTH KEY管理](./user-auth-syntax/#auth-key) | ユーザー | 公開鍵ベースの認証キーの登録・管理 | | [ALTER SYSTEM](./system-session-alter-syntax/#alter-system) | システム | セッション制御、PVO Cacheのflush、ライセンス導入など | | [ALTER SESSION](./system-session-alter-syntax/#alter-session) | セッション | セッション別のパラメーター設定 | | [PIVOT](./pivot-syntax/) | 分析 | 行を列へ変換するピボットクエリ | | [WINDOW FUNCTION (OVER)](./window-function-over-syntax/) | 分析 | ウィンドウ関数とOVER句 | | [SERIES BY](./series-syntax/) | 分析 | 連続して条件を満たすレコードのグループ化 | | [SEARCH / ESEARCH / REGEXP](./search-esearch-regexp-syntax/) | 検索 | キーワードインデックスによるテキスト検索 | | [ROLLUP REBUILD](./rollup-rebuild-syntax/) | 運用 | ROLLUP結果の再計算 | | [DATABASE](./database-syntax/) | DDL/セッション | 論理データベースの作成・選択・削除と状態確認 | | [AUTO_INCREMENT](./auto-increment-syntax/) | DDL | 64ビットPRIMARY KEYの自動値生成 | | [EXEC procedure / SHOW ROLLUPGAP](./execute-procedure-syntax/) | 制御 | テーブルのflush・refreshとROLLUPの制御・状態確認 | ## BNF表記規則 このリファレンスで使用するBNF(Backus-Naur Form)表記は、次の規則に従います。 | 表記 | 意味 | |------|------| | `'keyword'` | SQL予約語(大文字・小文字は区別しない) | | `name` | ユーザー定義名 | | `( A \| B )` | AまたはBのどちらか | | `[ ... ]` | 任意の要素(省略可能) | | `( ... )*` | 0回以上の繰り返し | | `( ... )+` | 1回以上の繰り返し | | `( ... )?` | 0回または1回 | --- title: "SELECT" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/select-syntax/ language: ja kind: page --- # SELECT `SELECT`はMachbaseの各種テーブルからデータを参照・絞り込み・集計する構文です。 ## SELECTの完全な構文 ```sql query_stmt ::= [ with_clause ] select_stmt select_stmt ::= 'SELECT' [ hint_clause ] target_list [ 'FROM' table_reference_list ] [ 'WHERE' condition_expr ] [ 'DURATION' duration_expr ] [ 'GROUP BY' expr_list [ 'HAVING' condition_expr ] ] [ 'ORDER BY' expr_list [ 'ASC' | 'DESC' ] ] [ 'SERIES BY' condition_expr ] [ 'LIMIT' [ offset ',' ] row_count ] -- 集合演算子 select_stmt 'UNION ALL' select_stmt ``` `DURATION`は`WHERE`の後、`GROUP BY`・`HAVING`・`ORDER BY`・`SERIES BY`・`LIMIT`の前に記述します。 上記はSQL句の記述順序であり、内部の実行順序ではありません。 `with_clause`はStandard Editionで非再帰CTEを宣言します。構文と制約の詳細は [WITH / CTE構文](../cte-syntax/)を参照してください。 ### 選択リスト(target_list) ```sql target_list ::= '*' | target_expr ( ',' target_expr )* target_expr ::= column_name [ 'AS' alias ] | expr [ 'AS' alias ] | '(' subquery ')' [ 'AS' alias ] ``` ### FROM句 ```sql table_reference_list ::= table_reference ( ',' table_reference )* table_reference ::= table_name [ alias ] | '(' subquery ')' [ alias ] | table_name [ alias ] join_clause | view_name [ alias ] join_clause ::= [ 'INNER' | 'LEFT OUTER' | 'RIGHT OUTER' ] 'JOIN' table_reference 'ON' condition_expr | 'CROSS JOIN' table_reference ``` --- ## FROM句のないSELECT テーブルを参照せず、定数、算術式、単純な関数の結果を1行で返します。 ```sql SELECT 1; SELECT 'alive'; SELECT 1 + 2; SELECT ABS(-7); SELECT SYSDATE; ``` --- ## WHERE句 ```sql condition_expr ::= expr comparison_op expr | expr [ 'NOT' ] 'BETWEEN' expr 'AND' expr | column_name [ 'NOT' ] 'IN' '(' value_list | subquery ')' | column_name 'RANGE' duration_spec | column_name [ 'NOT' ] 'SEARCH' string_literal | column_name 'ESEARCH' pattern_literal | column_name [ 'NOT' ] 'REGEXP' pattern_literal | expr 'IS' [ 'NOT' ] 'NULL' | condition_expr ( 'AND' | 'OR' ) condition_expr | 'NOT' condition_expr | '(' condition_expr ')' | '(' subquery ')' ``` ### 主なWHERE演算子 | 演算子 | 説明 | |--------|------| | `=`, `<>`, `<`, `<=`, `>`, `>=` | 比較演算子 | | `BETWEEN value1 AND value2` | 範囲条件 | | `IN (value_list)` | 値リスト条件 | | `IN (subquery)` | サブクエリIN | | `RANGE n unit` | 現在時刻を基準とする時間範囲条件 | | `SEARCH 'keyword'` | キーワードインデックスを使用するテキスト検索 | | `ESEARCH 'pattern%'` | 拡張テキスト検索(%ワイルドカード) | | `REGEXP 'pattern'` | 正規表現検索(インデックスを使用しない) | | `IS NULL` / `IS NOT NULL` | NULL条件 | ```sql -- BETWEEN SELECT * FROM sensor_log WHERE value BETWEEN 10.0 AND 20.0; -- IN SELECT * FROM sensor_log WHERE status IN ('OK', 'WARN'); -- RANGE (現在時刻を基準とする直近1時間) SELECT * FROM sensor_log WHERE _arrival_time RANGE 1 HOUR; -- SEARCH (キーワードインデックスを使用) SELECT * FROM log_table WHERE message SEARCH 'error'; -- ESEARCH (ワイルドカードパターン) SELECT * FROM log_table WHERE message ESEARCH 'timeout%'; -- REGEXP (正規表現) SELECT * FROM log_table WHERE message REGEXP 'error[0-9]+'; ``` --- ## GROUP BY / HAVING ```sql 'GROUP BY' expr_list [ 'HAVING' condition_expr ] ``` ```sql SELECT name, AVG(value), MAX(value), COUNT(*) FROM sensor_log GROUP BY name HAVING AVG(value) > 50.0; ``` --- ## ORDER BY ```sql 'ORDER BY' expr_list [ 'ASC' | 'DESC' ] ``` ```sql SELECT name, value FROM sensor_log ORDER BY value DESC; SELECT name, value FROM sensor_log ORDER BY name ASC, value DESC; ``` --- ## LIMIT ```sql 'LIMIT' [ offset ',' ] row_count ``` ```sql -- 先頭10件のみ参照 SELECT * FROM sensor_log LIMIT 10; -- 11件目から10件を参照 SELECT * FROM sensor_log LIMIT 10, 10; ``` --- ## DURATION `_arrival_time`列を基準に参照する時間範囲を指定します。 ```sql duration_expr ::= number time_unit [ ( 'BEFORE' | 'AFTER' ) number time_unit ] | 'FROM' datetime_expr 'TO' datetime_expr time_unit ::= 'YEAR' | 'MONTH' | 'WEEK' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ``` ```sql -- 直近1時間のデータ SELECT * FROM sensor_log DURATION 1 HOUR; -- 1日前を基準とする1時間の範囲 SELECT * FROM sensor_log DURATION 1 HOUR BEFORE 1 DAY; -- 明示的な範囲 SELECT * FROM sensor_log DURATION FROM TO_DATE('2024-01-01','YYYY-MM-DD') TO TO_DATE('2024-01-31','YYYY-MM-DD'); ``` --- ## JOIN ### INNER JOIN (カンマ形式) ```sql SELECT t1.id, t2.name FROM sensor_log t1, devices t2 WHERE t1.id = t2.device_id AND t1.value > 50; ``` ### ANSI JOIN ```sql -- INNER JOIN SELECT t1.id, t2.name FROM sensor_log t1 INNER JOIN devices t2 ON (t1.id = t2.device_id) WHERE t1.value > 50; -- LEFT OUTER JOIN SELECT t1.id, t2.location FROM sensor_log t1 LEFT OUTER JOIN devices t2 ON (t1.name = t2.name); -- RIGHT OUTER JOIN SELECT t1.value, t2.name FROM sensor_log t1 RIGHT OUTER JOIN devices t2 ON (t1.name = t2.name); ``` > FULL OUTER JOINはサポートしません。 --- ## SERIES BY ソート済みの結果から、条件を連続して満たすレコードのグループを抽出します。 ```sql 'ORDER BY' expr 'SERIES BY' condition_expr ``` ```sql -- C2 > 1を連続して満たすレコード群を参照 SELECT c1, c2, SERIESNUM() AS grp FROM t1 ORDER BY c1 SERIES BY c2 > 1; ``` --- ## SUBQUERY ```sql -- FROM句のサブクエリ(インラインビュー) SELECT a.name, a.avg_val FROM (SELECT name, AVG(value) AS avg_val FROM sensor_log GROUP BY name) a WHERE a.avg_val > 50; -- WHERE句のサブクエリ SELECT * FROM sensor_log WHERE value > (SELECT AVG(value) FROM sensor_log); -- IN句のサブクエリ SELECT * FROM sensor_log WHERE name IN (SELECT name FROM devices WHERE status = 'ACTIVE'); ``` > 相関サブクエリ(外側のクエリの列を参照するサブクエリ)はサポートしません。 --- ## CASE式 ```sql -- simple CASE CASE expr WHEN value1 THEN result1 [ WHEN value2 THEN result2 ... ] [ ELSE default_result ] END -- searched CASE CASE WHEN condition1 THEN result1 [ WHEN condition2 THEN result2 ... ] [ ELSE default_result ] END ``` ```sql SELECT name, value, CASE WHEN value >= 80 THEN 'HIGH' WHEN value >= 40 THEN 'MID' ELSE 'LOW' END AS level FROM sensor_log; ``` --- ## PIVOT インラインビューの集計結果を行から列へ変換します。 ```sql 'PIVOT' '(' aggregate_func '(' column ')' 'FOR' pivot_column 'IN' '(' value_list ')' ')' ``` ```sql SELECT * FROM (SELECT regtime, tagid, dvalue FROM result_d) PIVOT (SUM(dvalue) FOR tagid IN ('AXIS_X', 'AXIS_Y', 'AXIS_Z')); ``` --- ## UNION ALL ```sql select_stmt 'UNION ALL' select_stmt ``` 2つのSELECT結果を結合します。列数と型に互換性が必要です。重複を除去する`UNION`、`INTERSECT`、`EXCEPT`はサポートしません。 ```sql SELECT id, name FROM table_a UNION ALL SELECT id, name FROM table_b; ``` --- ## SAVE DATA INTO SELECT結果をCSVファイルに保存します。 ```sql 'SAVE DATA INTO' 'file_path' [ 'HEADER' ( 'ON' | 'OFF' ) ] [ ( 'FIELDS' | 'COLUMNS' ) [ 'TERMINATED BY' char ] [ 'ENCLOSED BY' char ] ] [ 'ENCODED BY' encoding ] 'AS' select_stmt ``` ```sql SAVE DATA INTO '/tmp/sensor_data.csv' HEADER ON AS SELECT * FROM sensor_log; ``` --- ## 関連ドキュメント - [WITH / CTE syntax](../cte-syntax/) - 非再帰の共通テーブル式 - [ヒント辞典](../select-hint-syntax/) - SELECTクエリの性能最適化ヒント - [SERIES BY](../series-syntax/) - 連続条件によるグループ化の詳細 - [PIVOT](../pivot-syntax/) - 行から列への変換の詳細例 - [SEARCH/ESEARCH/REGEXP](../search-esearch-regexp-syntax/) - テキスト検索の詳細 - [DURATION相対時間式](../../relative-time/) - 時間範囲式の全一覧 --- title: "WITH / CTE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/cte-syntax/ language: ja kind: page --- # WITH / CTE 共通テーブル式(Common Table Expression、CTE)は、1つのSQL文内で`SELECT`結果に名前を付けて 使用する機能です。複雑なインラインビューの段階分けや、集計結果と他のテーブルとの結合に使用します。 Machbase 8.7.0 Standard Editionは非再帰SELECT CTEをサポートします。CTEは現在のSQL文内だけで有効であり、 独立したデータベースオブジェクトとしては保存されません。 ## サポート範囲 | 機能 | サポート | 説明 | |---|:---:|---| | 単一の非再帰CTE | O | CTE本文と主クエリは`SELECT`です。 | | 複数のCTE | O | カンマで区切り、後のCTEから前のCTEを参照できます。 | | 明示的な結果列名 | O | CTE名の後に結果列リストを指定します。 | | 入れ子のCTE | O | 外側のCTEは下位の`SELECT`から参照できます。 | | `INSERT SELECT` | O | `INSERT INTO ... WITH ... SELECT`の順で記述します。 | | VIEW定義 | O | `CREATE VIEW ... AS WITH ... SELECT`を使用します。 | | プリペアドステートメント | O | CTE本文と主`SELECT`で`?`または`:name`を使用できます。 | | EXPLAIN | O | `EXPLAIN`、`EXPLAIN FULL`、`EXPLAIN TRACE`に対応します。 | | `UNION ALL`、PIVOT | O | 既存の`SELECT`のサポート範囲と制約に従います。 | | テーブルタイプ | O | LOG、TAG、LOOKUP、VOLATILE、TRANSACTIONを参照できます。 | | 再帰CTE | X | `WITH RECURSIVE`、自己参照、相互再帰は非対応です。 | | 実体化の制御 | X | `MATERIALIZED`、`NOT MATERIALIZED`は非対応です。 | | データ変更CTE | X | CTE本文にDMLやDDLは使用できません。 | CTE本文ではJOIN、集約関数、`GROUP BY`、`HAVING`、`ORDER BY`、`LIMIT`、`UNION ALL`、PIVOTを 既存の`SELECT`規則に従って使用できます。LOGテーブルの`DURATION`、`SERIES BY`、ウィンドウ関数、 TAGテーブルのROLLUPも既存の規則に従います。 名前付きパラメーターの命名規則とSDK別のバインド方法は、[Named Bind Parameter構文](../named-bind-parameter-syntax/)を参照してください。 ## 基本構文 ### SELECT ```sql WITH cte_name [(column_name [, ...])] AS ( select_statement ) [, cte_name [(column_name [, ...])] AS (select_statement) ...] select_statement; ``` ### INSERT SELECT ```sql INSERT INTO target_table [(target_column [, ...])] WITH cte_name [(column_name [, ...])] AS ( select_statement ) [, cte_name [(column_name [, ...])] AS (select_statement) ...] select_statement; ``` `INSERT SELECT`では、対象テーブルと対象列リストの後に`WITH`句を記述します。 他のDBMSの文頭に置く`WITH ... INSERT INTO ...`形式はサポートしません。 ### VIEW ```sql CREATE [OR REPLACE] VIEW view_name AS WITH cte_name [(column_name [, ...])] AS ( select_statement ) [, cte_name [(column_name [, ...])] AS (select_statement) ...] select_statement; ``` ### EXPLAIN ```sql EXPLAIN [FULL | TRACE] WITH cte_name [(column_name [, ...])] AS ( select_statement ) [, cte_name [(column_name [, ...])] AS (select_statement) ...] select_statement; ``` ## 基本的な使用方法 次の例は、現在のユーザーが以下のテーブルを所有することを前提とします。 | テーブル | タイプ | 使用列 | |---|---|---| | `sensor_data` | LOG | `name`, `device_id`, `time`, `value` | | `device_info` | TRANSACTION | `device_id`, `device_name` | | `device_summary` | LOG | `device_id`, `sample_count`, `avg_value` | ### クエリ結果に名前を付ける ```sql WITH recent_data AS ( SELECT name, time, value FROM sensor_data WHERE time >= NOW - 10m ) SELECT name, time, value FROM recent_data ORDER BY time DESC; ``` 最終出力の順序を保証するには、主`SELECT`に`ORDER BY`を指定します。CTE本文の`ORDER BY`だけでは 外側の結果順序は保証されません。 ### 集計結果の結合 ```sql WITH top_devices AS ( SELECT device_id, AVG(value) AS avg_value FROM sensor_data WHERE time >= NOW - 1h GROUP BY device_id ORDER BY avg_value DESC LIMIT 10 ) SELECT d.device_id, d.device_name, t.avg_value FROM device_info d JOIN top_devices t ON d.device_id = t.device_id ORDER BY t.avg_value DESC; ``` 大量の時系列データを先に集計し、結果件数を制限してから参照データと結合する場合に使用できます。 ### 複数のCTEの連結 ```sql WITH recent_data AS ( SELECT device_id, value FROM sensor_data WHERE time >= NOW - 30m ), device_avg AS ( SELECT device_id, AVG(value) AS avg_value FROM recent_data GROUP BY device_id ) SELECT device_id, avg_value FROM device_avg WHERE avg_value >= 80; ``` `device_avg`は先に宣言した`recent_data`を参照できます。前のCTEから後のCTEを参照する前方参照は非対応です。 ### 結果列名の指定 ```sql WITH device_stat (id, sample_count, average_value) AS ( SELECT device_id, COUNT(*), AVG(value) FROM sensor_data GROUP BY device_id ) SELECT id, sample_count, average_value FROM device_stat; ``` 明示した列数はCTE本文の結果列数と一致する必要があり、列名の重複は許可しません。 列リストを省略すると、`SELECT`の別名とインラインビューの列命名規則に従います。 ## 使用できるSQLの文脈 ### 下位SELECT ```sql WITH active_devices AS ( SELECT device_id FROM sensor_data WHERE time >= NOW - 1m ) SELECT d.device_id, d.device_name FROM device_info d WHERE d.device_id IN ( SELECT device_id FROM active_devices ); ``` 外側の`SELECT`で宣言したCTEは、スカラーサブクエリ、`IN (subquery)`、インラインビューなどの 下位`SELECT`から参照できます。JOIN `ON`条件のスカラーサブクエリや`IN (subquery)`など、 既存の`SELECT`の制約はCTEを使用しても変わりません。 ### INSERT SELECT ```sql INSERT INTO device_summary WITH hourly_summary AS ( SELECT device_id, COUNT(*) AS sample_count, AVG(value) AS avg_value FROM sensor_data WHERE time >= NOW - 1h GROUP BY device_id ) SELECT device_id, sample_count, avg_value FROM hourly_summary; ``` CTEは結果行を生成し、実際の取り込み可否と重複キー処理は対象テーブルの既存の`INSERT SELECT`規則に従います。 CTEを使用しても、対象テーブルの制約や原子性の範囲は変わりません。 ### VIEW定義 ```sql CREATE VIEW active_device_summary AS WITH recent_data AS ( SELECT device_id, value FROM sensor_data WHERE time >= NOW - 10m ) SELECT device_id, COUNT(*) AS sample_count, AVG(value) AS avg_value FROM recent_data GROUP BY device_id; ``` VIEWにはCTEを含む`SELECT`定義が保存され、参照時にその定義を再解釈します。 `CREATE OR REPLACE VIEW`でも同じ構文を使用できます。 VIEW定義にバインドパラメーター(`?`)は使用できません。実行ごとに変わる条件は、VIEWを参照する`SELECT`に記述します。 ### EXPLAIN ```sql EXPLAIN FULL WITH recent_data AS ( SELECT name, time, value FROM sensor_data WHERE time >= NOW - 5m ) SELECT * FROM recent_data WHERE name = 'sensor-01'; ``` `EXPLAIN`、`EXPLAIN FULL`、`EXPLAIN TRACE`で、CTE展開後に実際のテーブルへ適用されるスキャン、 フィルター、JOIN計画を確認します。 ### プリペアドステートメント CTE本文と主`SELECT`でバインドパラメーター(`?`)を使用できます。 ```sql WITH selected_data AS ( SELECT device_id, time, value FROM sensor_data WHERE device_id = ? ) SELECT device_id, time, value FROM selected_data WHERE value >= ?; ``` 参照しないCTEのバインドパラメーターも文のパラメーターとして登録されるため、値をバインドしてください。 同じCTEを複数回参照しても、元のCTE本文のパラメーター数が参照回数分に増えることはありません。 ## 名前と有効範囲 ### 宣言順序 後のCTEは前のCTEを参照できます。前方参照、自己参照、CTE間の相互参照はサポートしません。 ### 実テーブルと名前が同じ場合 修飾のない名前がCTEと実際のTABLEまたはVIEWの両方に存在する場合、現在の有効範囲のCTEを優先します。 ```sql WITH device_info AS ( SELECT device_id FROM sensor_data ) SELECT * FROM device_info; ``` 実テーブルを選択するには、`user_name.device_info`のように所有者を明示します。 所有者で修飾した名前は、CTEではなく実際のTABLEまたはVIEWを検索します。 ### 入れ子の範囲 外側のCTEは内側の`SELECT`から参照できます。内側の`SELECT`に宣言したCTEは外側から参照できません。 内側のCTEと外側のCTEが同名の場合は、内側を優先します。 ## 実行特性と性能 MachbaseはCTE参照を既存のインラインビュー形式に展開して計画します。CTE結果の一時テーブルへの実体化や、 1回だけの評価は保証しません。 同じCTEへの複数の参照は、それぞれ個別に計画・実行される場合があります。 ```sql WITH recent_data AS ( SELECT device_id, time, value FROM sensor_data WHERE time >= NOW - 1d ) SELECT a.device_id, a.value, b.value FROM recent_data a JOIN recent_data b ON a.device_id = b.device_id AND a.time = b.time; ``` 性能管理には次の基準を適用してください。 - 大量のテーブルを読み取るCTEの繰り返し参照を避けます。 - 時刻、TAG名、キー条件など選択性を高める条件を、CTE本文でできるだけ早く適用します。 - フィルターのプッシュダウンやCTE結果の自動再利用を前提に性能を予測しません。 - 繰り返し参照が必要な場合は、クエリの分割や実際に保存するオブジェクトの使用を検討します。 - `EXPLAIN`で各参照の実際の実行計画を確認します。 `MATERIALIZED`と`NOT MATERIALIZED`は非対応のため、ユーザーがCTEの評価方式を強制することはできません。 ### CTEの展開上限 1つのSQL文のCTE展開で生成される`SELECT`単位は最大1,024個です。宣言できるCTE名の数ではなく、 複数参照と連鎖参照をすべて展開した`SELECT`単位の合計です。 上限を超えると次のエラーになります。 ```text CTE expansion limit exceeded ``` エラーが発生したら、繰り返し参照の連鎖を減らすか、中間結果を別のテーブルまたはVIEWに分離してください。 ## 制約 次の機能はサポートしません。 - `WITH RECURSIVE`と再帰CTE - `RECURSIVE`を省略した自己参照とCTE間の相互再帰 - 前方参照 - `MATERIALIZED`、`NOT MATERIALIZED` - 再帰CTE構文の`SEARCH DEPTH FIRST`、`SEARCH BREADTH FIRST`、`CYCLE` - 文頭の`WITH ... INSERT`、`WITH ... UPDATE`、`WITH ... DELETE`、`WITH ... MERGE` - CTE本文のINSERT、UPDATE、DELETE、MERGE、DDL - `UNION`、`INTERSECT`、`EXCEPT` - `FROM`句のないリテラル`SELECT`同士の`UNION ALL` - `EXISTS`式 - CTE本文の`FREQUENCY` - ユーザー定義の`CREATE ROLLUP ... AS (...)`クエリのCTE CTEはテーブルタイプ別のDML機能を拡張しません。LOG、TAG、LOOKUP、VOLATILE、TRANSACTIONの 参照と取り込みは、それぞれの既存規則に従います。 ## エラーの確認 | 状況 | 確認内容 | |---|---| | CTE名の重複 | 同じ`WITH`句で各名前を1回だけ宣言しているか確認します。 | | 列数の不一致 | 明示したCTE列数と`SELECT`結果列数をそろえます。 | | 列名の重複 | 明示的な列リストから重複名を削除します。 | | 前方参照 | 参照先のCTEを先に宣言します。 | | 自己参照 | 再帰構造を削除するか、深さが固定されたSQLやアプリケーションの繰り返しへ変更します。 | | テーブルが見つからない | 修飾名がCTEではなく実際のTABLE/VIEWを検索しているか確認します。 | | 展開上限の超過 | 繰り返し参照の連鎖を減らすか、中間結果を別オブジェクトへ分離します。 | | VIEWのバインドエラー | VIEW定義とCTEから`?`を削除し、参照時の条件へ移します。 | | 構文エラー | 非対応の再帰、実体化、文頭の`WITH ... DML`構文を使用していないか確認します。 | ## 他のDBMSからの移行 | 移行元DBMSの機能 | Machbaseでの対応 | |---|---| | PostgreSQL/MySQLの`WITH RECURSIVE` | 深さが固定されたSQL、またはアプリケーションの繰り返しへ変更します。 | | PostgreSQL/SQLiteの`MATERIALIZED` | キーワードを削除し、1回だけ評価されると仮定しないでください。 | | PostgreSQL/SQLiteの`NOT MATERIALIZED` | キーワードを削除し、`EXPLAIN`で実際の計画を確認します。 | | Oracleの再帰subquery factoring | 自己参照を除いた非再帰CTEのみ移行します。 | | SQL Serverの`WITH ... UPDATE/DELETE/MERGE` | CTEとDMLを分離し、テーブル別のDML規則を適用します。 | | 再帰CTEの`SEARCH`または`CYCLE` | 経路と循環検出はアプリケーションや保存列で処理します。 | ## 関連ドキュメント - [SELECT構文](../select-syntax/) - [DML構文](../dml-syntax/) - [VIEW構文](../view-syntax/) - [集合演算子](../set-operator-syntax/) - [PIVOT構文](../pivot-syntax/) - [ウィンドウ関数とOVER](../window-function-over-syntax/) - [クエリ分析とEXPLAIN](/ja/dbms/performance-tuning/performance-query-tuning/) --- title: "Named Bind Parameter" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/named-bind-parameter-syntax/ language: ja kind: page --- # Named Bind Parameter Named Bind Parameterは、SQLの値の位置に`:name`形式の名前を指定し、実行時に値をバインドする機能です。 繰り返すパラメーターの意味を名前で表せるため、SQLとアプリケーションコードの対応関係を明確に保てます。 ```sql SELECT ID, NAME FROM SENSOR_DATA WHERE ID = :id; ``` ## 名前の構文 名前付きマーカーは次の形式を使用します。 ```text :[A-Za-z_$][A-Za-z0-9_$]* ``` | 区分 | 例 | |---|---| | 有効な名前 | `:id`, `:sensor_id`, `:value2`, `:_from_time`, `:select` | | 無効な名前 | `:1id`, `:`, `::id` | 複数のSDKで同じSQLを共有する場合は、`[A-Za-z][A-Za-z0-9_]*`形式の名前を推奨します。 パラメーター名は大文字と小文字を区別します。`:VALUE`、`:value`、`:VaLuE`は異なる名前です。 .NETの`MachParameterCollection`は、既存プロバイダーとの互換性のため、大文字と小文字を区別せず名前を検索します。 ## 使用できる位置 名前付きマーカーは、値や式を指定する位置で使用します。 ```sql SELECT ID, NAME, VALUE FROM SENSOR_DATA WHERE CREATED_AT >= :from_time AND CREATED_AT < :to_time AND VALUE >= :minimum_value ORDER BY CREATED_AT LIMIT :row_count OFFSET :start_row; ``` 次のような識別子やSQL構造は、パラメーターに置き換えられません。 ```sql SELECT * FROM :table_name; -- 使用不可 SELECT :column_name FROM SENSOR_DATA; -- 列識別子の置き換えではない SELECT * FROM SENSOR_DATA ORDER BY ID :direction; -- 使用不可 ``` 動的な識別子が必要なら、アプリケーションで許可リストを検査してからSQLを構成します。 文字列とSQLコメント内のコロンは、パラメーターとして認識されません。 ```sql SELECT ':not_a_parameter' FROM SENSOR_DATA WHERE ID = :id /* :ignored */; ``` ## パラメーターの出現順序 パラメーター数は一意な名前の数ではなく、SQL内の出現回数で数えます。 次のSQLには`target`が2回現れるため、パラメーターは2つです。 ```sql SELECT ID, NAME FROM SENSOR_DATA WHERE ID = :target OR PARENT_ID = :target; ``` - `SQLNumParams()`は`2`を返します。 - 位置指定APIは、1番目と2番目の位置を個別にバインドします。 - 名前指定APIは、1つの`target`値を同名の両方の位置に適用します。 - パラメーターメタデータには、各位置が別の項目として現れます。 1つのSQL文で使用できるパラメーターの出現回数は、最大256です。 ## 位置指定マーカーとの関係 低レベルの位置指定APIは、`?`と`:name`をSQLの出現順にバインドできます。 名前・オブジェクト・マッピングによるAPIは、匿名マーカー`?`と名前付きマーカーを併用するとエラーを返します。 1つのSQL文では1種類のマーカーを使用してください。 | 方式 | SQLマーカー | バインド | |---|---|---| | 位置指定 | `?` | SQL出現順の1始まりの位置番号 | | 名前付きSQLと位置指定API | `:name` | SQL出現順の1始まりの位置番号 | | 名前指定API | `:name` | パラメーター名 | ## DMLでの使用例 Named Bind Parameterは、既存のプリペアドステートメントと同じ型規則を使用します。 ```sql INSERT INTO SENSOR_DATA (ID, PARENT_ID, NAME, VALUE, CREATED_AT) VALUES (:id, :parent_id, :name, :value, :created_at); ``` Named Bind Parameterは、テーブルごとのDMLポリシーやEdition制約を変更しません。 サポートされるDMLと条件は、[DML構文](../dml-syntax/)および [サポート範囲と制約](../../../support-scope-constraints/)を参照してください。 Standard EditionとCluster Editionは、同じ`:name`構文と位置番号規則を使用します。 実行可能なSQLとテーブルタイプは、各Editionの既存のサポート範囲に従います。 ### TAGデータUPDATEでの使用 Machbase 8.7.0から、Standard EditionのTAGデータUPDATEでは、`WHERE`句のNAMEとBASETIME条件値に名前付きマーカーを使用できます。 ```sql UPDATE sensor_tag SET value = :value, status = :status, note = :note WHERE name = :name AND time = :time; ``` 同じプリペアドステートメントの再実行時に、SET、NAME、TIMEの値を新しくバインドできます。 一致する行がなければ、影響行数`0`で成功します。 バインドの使用にかかわらずタグ選択条件とBASETIME条件は両方必要で、SET対象列の制約も変わりません。 サポートされる条件形式とパラメーターメタデータは、 [TAGデータUPDATE](../dml-syntax/tag-data-update-syntax/#tag-data-update-predicate-bind)を参照してください。 ## CTEでの使用 Standard Editionでは、CTE本文とメインの`SELECT`でNamed Bind Parameterを使用できます。 ```sql WITH FILTERED AS ( SELECT ID, NAME, VALUE FROM SENSOR_DATA WHERE ID > :minimum_id AND NAME = :label ) SELECT ID, NAME, VALUE FROM FILTERED WHERE ID = :target_id ORDER BY ID; ``` 上のSQLのパラメーターの位置番号は、`minimum_id`、`label`、`target_id`の順です。 CTEのサポート範囲とStandard Edition制約は、[WITH / CTE構文](../cte-syntax/)を参照してください。 ## NULLとデータ型 NULLは、各SDKの標準のNULL値またはインジケーターで渡します。 | SDK | NULL値 | |---|---| | Machbase SQLCLI | インジケーターの`SQL_NULL_DATA` | | ODBC | インジケーターの`SQL_NULL_DATA` | | JDBC | `null` | | Node.js/TypeScript | `null` | | Python | `None` | | .NET | `DBNull.Value` | `column = :value`にNULLをバインドしても、`column IS NULL`と同じ条件にはなりません。 NULLを検索するには、SQLのNULL比較規則に従って`IS NULL`を使用します。 `INTEGER`、`VARCHAR`、`DOUBLE`、`DECIMAL`、`NUMERIC`、`DATETIME`など、既存のプリペアドステートメントのデータ型を使用できます。 `DECIMAL`や`NUMERIC`の精度を保持するには、SDKのdecimal型または文字列表現を使用してください。 ## SDK別のバインド方法 | SDKまたはツール | 名前による使用方法 | |---|---| | Machbase SQLCLI | `SQLBindParameterByName()`, `SQLBindParameterByNameW()` | | ODBC | `:name`のSQLを`SQLBindParameter()`の位置番号でバインド | | JDBC | `MachPreparedStatement.setObject(String name, Object value)` | | Node.js/TypeScript | 配列は位置指定、オブジェクトは名前指定入力 | | Python DB-API | mappingを渡す。2.4のprepared cursorは、呼び出し間で`:name`と`%(name)s`を再使用 | | .NET | `MachCommand.Parameters.AddWithValue(":name", value)` | | Go native | `api.Named("name", value)` | | Go `database/sql` | `sql.Named("name", value)` | | machsql | SQLは`:name`、値は`$1`、`$2`の順で指定 | 詳細なAPIとエラー処理は、[開発ツール連携](../../../../development-tools-integration/)と [machsqlコマンド・オプションリファレンス](../../../command-line-tools/machsql/)を参照してください。 ## 互換性とエラー Machbase 8.7.0の名前指定SDK APIには、この機能に対応するクライアントとサーバーの両方が必要です。 旧バージョンと併用する必要がある場合は、`?`と位置指定APIを使用してください。 | 状況 | 代表的なエラー | |---|---| | 必要な名前がない | missing parameter | | SQLにない名前を渡す | unknownまたはextra parameter | | 名前指定と位置指定を混在 | sequenceまたはmixed error | | 値の型がSQL型と合わない | typeまたはconversion error | | 名前指定APIを旧サーバーに使用 | unsupported | 本番コードでは、エラー文字列よりSQLSTATE、エラーコード、例外型を優先して確認してください。 バージョンの組み合わせごとの動作とSDK別のエラーコードは、 [クライアント・サーバープロトコル互換性](../../../support-scope-constraints/compatibility-xma-protocol/)を参照してください。 --- title: "SELECTヒント" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/select-hint-syntax/ language: ja kind: section --- # SELECTヒント SELECTヒントは`/*+ ... */`形式のコメントブロックで、オプティマイザーの動作を制御したり、サンプリングなどのデータ処理を指定したりします。 ## ヒント構文 ```sql SELECT /*+ hint_clause */ ... SELECT /*+ hint1 hint2 */ ... ``` ヒントは`SELECT`キーワードの直後の`/*+ ... */`ブロックに記述します。 ## 主なヒント一覧 ### 実行計画を制御するヒント | ヒント | 構文 | 説明 | |------|------|------| | `PARALLEL` | `/*+ PARALLEL(table, n) */` | 並列処理係数を指定 | | `NOPARALLEL` | `/*+ NOPARALLEL(table) */` | 並列処理を無効化 | | `FULL` | `/*+ FULL(table) */` | インデックススキャンの代わりにフルスキャンを強制 | | `NO_INDEX` | `/*+ NO_INDEX(table, index) */` | 特定インデックスの使用を無効化 | | `ROLLUP_TABLE` | `/*+ ROLLUP_TABLE(rollup_table) */` | 特定ROLLUPテーブルを強制選択 | | `RID_RANGE` | `/*+ RID_RANGE(table, start, end) */` | RID範囲を指定 | | `SCAN_FORWARD` | `/*+ SCAN_FORWARD(table) */` | 古いレコードからスキャン(LOGテーブル) | | `SCAN_BACKWARD` | `/*+ SCAN_BACKWARD(table) */` | 新しいレコードからスキャン(LOGテーブル) | ### データ処理ヒント | ヒント | 構文 | 説明 | |------|------|------| | `SAMPLING` | `/*+ SAMPLING(SamplingRate) */` | 実数値で指定した割合に従ってデータを抽出 | ## 例 ```sql -- 8スレッドで並列処理 SELECT /*+ PARALLEL(sensor_log, 8) */ sensor, AVG(value) FROM sensor_log WHERE ts BETWEEN TO_DATE('2024-01-01', 'YYYY-MM-DD') AND TO_DATE('2024-01-31', 'YYYY-MM-DD') GROUP BY sensor; -- 特定インデックスを使用しない SELECT /*+ NO_INDEX(sensor_log, idx_ts) */ * FROM sensor_log WHERE ts > TO_DATE('2024-01-01', 'YYYY-MM-DD'); -- ROLLUPテーブルを強制選択 SELECT /*+ ROLLUP_TABLE(_rollup_tag_value_min) */ name, rollup('min', 5, time) AS t, AVG(value) FROM tag WHERE name = 'TEMP-01' GROUP BY name, t; -- 条件に一致する行を最大100,000行に制限した範囲から1%を抽出 SELECT /*+ SAMPLING(0.01) */ t_name, time, value FROM tag WHERE t_name = 'TAG_99' LIMIT 100000; ``` ## 下位項目 - [SAMPLING hint](./sampling-hint/) — 割合を指定するサンプリングヒントの詳細 ## 関連ドキュメント - [クエリのパフォーマンスチューニング](/ja/dbms/performance-tuning/performance-query-tuning/) — 実行計画とヒントの適用基準 --- title: "SAMPLINGヒント" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/select-hint-syntax/sampling-hint/ language: ja kind: page --- # SAMPLINGヒント `SAMPLING`ヒントは指定した割合に従ってデータを抽出します。抽出割合は実数値の`SamplingRate`で指定し、 `1`は全データの100%を意味します。 ## 構文 ```sql SELECT /*+ SAMPLING(SamplingRate) */ col1, col2, ... FROM table_name WHERE ...; ``` | パラメーター | 説明 | |----------|------| | `SamplingRate` | データの抽出割合を表す実数値 | 抽出割合をパーセントで表すには、`SamplingRate`に100を掛けます。 | SamplingRate | 抽出割合 | |--------------|-----------| | `1` | 100% (全データ) | | `0.01` | 1% | | `0.0001` | 0.01% | | `0.00001` | 0.001% | ## 例 ```sql -- 条件に一致する行を最大100,000行に制限した範囲から1%を抽出 SELECT /*+ SAMPLING(0.01) */ t_name, time, value FROM tag WHERE t_name = 'TAG_99' LIMIT 100000; ``` ## 注意事項 - `SamplingRate`は時間間隔や返却行数ではなく、抽出割合です。 - 返却行数は実行ごとに変わる場合があり、指定割合に対応する正確な行数は保証しません。 - データが少ない場合や抽出割合が低い場合、結果が0行になることがあります。 - 上記の例のように`LIMIT`を併用すると、`LIMIT`で制限した行の範囲からサンプリングします。例えば`SAMPLING(0.5)`と`LIMIT 1000`では、一致するデータが十分にある場合、最大1,000行の範囲から約50%を抽出します。サンプリング結果を1,000行まで埋めて返す意味ではありません。 ## 関連ドキュメント - [SELECT hint syntax](../) — 全ヒント一覧 - [ROLLUP syntax](../../rollup-syntax/) — 正確な時間単位の集計 --- title: "SEARCH / ESEARCH / REGEXP" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/search-esearch-regexp-syntax/ language: ja kind: page --- # SEARCH / ESEARCH / REGEXP 検索演算子は構文が似ていても検査対象が異なります。SEARCH・ESEARCHはKEYWORDインデックスの トークンを使用し、LIKE・REGEXPは元のテキストに対して条件を評価します。 性能のために演算子を変更する前に、結果の意味が同じであることを確認してください。 ## SEARCH ```text column_name SEARCH 'search_term' column_name NOT SEARCH 'search_term' ``` LOGのVARCHAR・TEXT列にKEYWORDインデックスが必要です。複数の単語はANDの意味で検索し、語順や 隣接性を保証するフレーズ検索ではありません。デフォルトモードでは一般的なASCII単語を小文字に正規化し、 ハングルなどは2-gramに分割します。すべての言語の形態素解析やUnicodeの大文字小文字処理を保証する機能ではありません。 次の独立した演習用テーブルを、このページ全体で使用します。 ```sql CREATE LOG TABLE ch7_ref_search ( event_id INTEGER, message VARCHAR(200), detail VARCHAR(200) ); CREATE INDEX ch7_ref_msg ON ch7_ref_search(message) INDEX_TYPE KEYWORD; CREATE INDEX ch7_ref_detail ON ch7_ref_search(detail) INDEX_TYPE KEYWORD; INSERT INTO ch7_ref_search VALUES (1, 'ERROR timeout occurred', 'connection reset'); INSERT INTO ch7_ref_search VALUES (2, 'pretimeout normal', 'port 8080'); INSERT INTO ch7_ref_search VALUES (3, NULL, NULL); EXEC TABLE_FLUSH(ch7_ref_search); EXEC INDEX_FLUSH(ch7_ref_search); SELECT event_id FROM ch7_ref_search WHERE message SEARCH 'timeout' ORDER BY event_id; SELECT event_id FROM ch7_ref_search WHERE message SEARCH 'error' AND detail SEARCH 'reset' ORDER BY event_id; SELECT event_id FROM ch7_ref_search WHERE message NOT SEARCH 'timeout' ORDER BY event_id; ``` 最初の2つのクエリは1番、最後のクエリは2番を選択します。NOT SEARCHはmessageがNULLの3番を含みません。 複数列を検索する場合は、各対象列に必要なインデックスを作成してください。 ## ESEARCH ```text column_name ESEARCH 'pattern%' column_name ESEARCH '%pattern%' ``` インデックス化された単語にパターンを適用します。`pattern%`は単語の接頭辞、`%pattern%`は単語内の部分パターンです。 `%`が元テキスト全体の単語境界を自由に越えると解釈しないでください。次の例はASCIIキーワードパターンを使用します。 ```sql SELECT event_id FROM ch7_ref_search WHERE message ESEARCH 'time%' ORDER BY event_id; SELECT event_id FROM ch7_ref_search WHERE message ESEARCH '%time%' ORDER BY event_id; ``` 結果はそれぞれ1番、1・2番です。現在のESEARCHのASCIIパターン比較は大文字小文字を区別しません。 元テキストのLIKEを完全に代替する機能ではなく、パターンに一致するトークン数・行数によってコストが変わります。 `NOT ESEARCH`構文は非対応です。NOT SEARCH・NOT LIKEへ変更すると除外する行も変わる場合があるため、 結果とNULL処理を確認してください。 ## LIKEとの比較 ```sql SELECT event_id FROM ch7_ref_search WHERE message LIKE '%TIMEOUT%' ORDER BY event_id; SELECT event_id FROM ch7_ref_search WHERE message NOT LIKE '%timeout%' ORDER BY event_id; ``` 最初のクエリは1・2番、2つ目は0件です。NULL行はNOT LIKEにも含まれません。 LIKEは現在のASCII比較では大文字小文字を区別しません。`%`は0文字以上、`_`は1文字を表します。 LIKE自体はKEYWORDインデックスを使用しません。ただし、常にテーブルのフルスキャンになるとは限りません。 時刻条件や他のインデックス条件によって先に対象行が制限される場合があります。 ## REGEXP ```text column_name REGEXP 'pattern' column_name NOT REGEXP 'pattern' ``` 正規表現パターンに一致する部分を検査します。デフォルトでは大文字小文字を区別します。 先頭・末尾を制限するには`^`・`$`を使用してください。 ```sql SELECT event_id FROM ch7_ref_search WHERE message REGEXP '^ERROR.*timeout' ORDER BY event_id; SELECT event_id FROM ch7_ref_search WHERE message NOT REGEXP 'timeout' ORDER BY event_id; ``` 最初のクエリは1番、2つ目は0件です。REGEXPはKEYWORDインデックスを直接使用しません。 SEARCHで先に対象を絞る場合は、その条件で必要な結果を除外しないことを確認してください。 ### 関数形式のREGEXP スカラー式でもREGEXP結果を使用できます。 ```sql SELECT 'abcde' REGEXP 'a[bcd]{1,10}e' FROM dual; ``` 結果は1です。関数形式のREGEXP_LIKEは比較オプションも受け取ります。現在、関数の入力はVARCHAR、 パターンとオプションは定数のVARCHARである必要があります。TEXT列を受け取るREGEXP演算子と 入力型の制約が同じであると仮定しないでください。 ```sql SELECT event_id, REGEXP_LIKE(message, 'error') AS case_sensitive, REGEXP_LIKE(message, 'error', 'i') AS case_insensitive FROM ch7_ref_search WHERE event_id IN (1, 3) ORDER BY event_id; ``` 1番の結果は0・1、3番はNULL・NULLです。`i`は大文字小文字を区別せず、`c`は区別します。 オプションを省略すると区別します。 ## 性能上の推奨事項 | 目的 | 選択基準 | |---|---| | 単語の存在確認 | SEARCH | | インデックス化された単語の接頭辞・部分パターン | ESEARCH | | 元テキストの部分パターン | LIKE | | 元テキストの形式・位置・複雑なパターン | REGEXP・REGEXP_LIKE | インデックスの存在と構築完了は区別し、同じデータと時間範囲で比較してください。 演習が終わったらテーブルを削除します。 ```sql DROP TABLE ch7_ref_search; ``` ## 関連ドキュメント - [テキスト検索の演習](/ja/dbms/log-table-usage/text-search-keyword-index/) — 複数単語・ハングル・NULL・TEXTの制約 - [INDEX構文](../index-syntax/) — KEYWORDインデックスの作成 --- title: "集合演算子" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/set-operator-syntax/ language: ja kind: page --- # 集合演算子 集合演算子は2つ以上の`SELECT`クエリ結果を結合したり、共通集合や差集合を求めたりする演算子です。 > Machbaseは現在、集合演算子`UNION ALL`のみをサポートします。重複を除去する`UNION`、 > `INTERSECT`、`EXCEPT`はサポートしません。 ## UNION ALL 2つのクエリ結果を重複除去せずに結合します。 ```sql select_stmt UNION ALL select_stmt ``` ```sql SELECT i1, i2 FROM table_1 UNION ALL SELECT c1, c2 FROM table_2; ``` ## 使用条件 2つの`SELECT`文は次の条件をすべて満たす必要があります。 1. **列数が同じ**であること。 2. **列の型が同じか互換性がある**こと。 1つでも条件を満たさなければエラーを返します。 ### 型の互換規則 | 組み合わせ | 互換性 | 結果の型 | |------|-----------|-----------| | 符号付き整数 ↔ 符号なし整数 | X | エラー | | 整数 ↔ 実数 | O | 実数型 | | 文字型(異なる長さ) | O | 処理可能 | | IPv6 ↔ IPv4 | X | エラー | - 結果列名は左側のクエリの列名に従います。 ## 例 ```sql -- 2つのテーブルのデータを結合 SELECT id, name FROM active_devices UNION ALL SELECT id, name FROM inactive_devices; -- 異なる期間の統計を結合 SELECT 'Q1' AS quarter, SUM(value) AS total FROM sales WHERE month BETWEEN 1 AND 3 UNION ALL SELECT 'Q2' AS quarter, SUM(value) AS total FROM sales WHERE month BETWEEN 4 AND 6; -- 3つのクエリを結合 SELECT name, time, value FROM sensor_a WHERE time > TO_DATE('2024-01-01', 'YYYY-MM-DD') UNION ALL SELECT name, time, value FROM sensor_b WHERE time > TO_DATE('2024-01-01', 'YYYY-MM-DD') UNION ALL SELECT name, time, value FROM sensor_c WHERE time > TO_DATE('2024-01-01', 'YYYY-MM-DD'); ``` ## 注意事項 - `UNION ALL`は重複行を削除しません。重複除去が必要な場合は`UNION ALL`結果をサブクエリにし、`DISTINCT`や`GROUP BY`を適用します。 - `FROM`句のないリテラル`SELECT`同士の`UNION ALL`はサポートしません。 - 結果行の順序は保証しません。ソートが必要な場合は全体をインラインビューにし、外側で`ORDER BY`を適用します。 ```sql -- ソートが必要な場合 SELECT * FROM ( SELECT id, name, time FROM log_a UNION ALL SELECT id, name, time FROM log_b ) ORDER BY time DESC; ``` ## 関連ドキュメント - [SELECT syntax](../select-syntax/) — SELECTの基本構文 - [WITH / CTE syntax](../cte-syntax/) — CTEでUNION ALLを使用 - [VIEW syntax](../view-syntax/) — UNION ALLを含むVIEWの作成 --- title: "PIVOT" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/pivot-syntax/ language: ja kind: page --- # PIVOT `PIVOT`は行方向のデータを列方向へ変換する構文です。GROUP BYの集計結果を列に並べ替え、読みやすいレポート形式で表示する場合に使用します。 > PIVOT構文はMachbase 5.6以降でサポートします。 ## 構文 ```sql SELECT * FROM (inline_view) PIVOT (aggregate_function(value_col) FOR category_col IN ('val1', 'val2', ...)) [WHERE ...] ``` - `inline_view`でPIVOT句に使用されない列をGROUP BYします。 - `FOR category_col IN (...)`: ピボットの基準列と、出力列へ変換する値の一覧を指定します。 - 結果列名はIN句に指定した文字列値になります。 ## 例 ### センサー別集計を列へ変換 ```sql -- インラインビューを使用したPIVOT SELECT * FROM ( SELECT regtime, tagid, dvalue FROM result_d WHERE regtime BETWEEN TO_DATE('2024-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2024-01-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS') ) PIVOT ( SUM(dvalue) FOR tagid IN ('FRONT_AXIS_TORQUE', 'REAR_AXIS_TORQUE', 'HOIST_AXIS_TORQUE', 'SLIDE_AXIS_TORQUE') ) WHERE FRONT_AXIS_TORQUE >= 40 AND REAR_AXIS_TORQUE >= 20; ``` ### CASE文より簡潔な表現 ```sql -- PIVOTを使わずCASEを使用 SELECT regtime, SUM(CASE WHEN tagid = 'SENSOR_A' THEN dvalue ELSE 0 END) AS sensor_a, SUM(CASE WHEN tagid = 'SENSOR_B' THEN dvalue ELSE 0 END) AS sensor_b FROM result_d GROUP BY regtime; -- PIVOTで簡潔に表現 SELECT * FROM ( SELECT regtime, tagid, dvalue FROM result_d ) PIVOT (SUM(dvalue) FOR tagid IN ('SENSOR_A', 'SENSOR_B')); ``` ### TAGテーブルとPIVOTの組み合わせ ```sql SELECT * FROM ( SELECT name, time, value FROM sensor_tag WHERE time BETWEEN TO_DATE('2024-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2024-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS') ) PIVOT ( AVG(value) FOR name IN ('sensor-01', 'sensor-02', 'sensor-03') ); ``` ## 制約 - PIVOTは必ずインラインビュー(サブクエリ)と併用してください。 - インラインビューではPIVOT集計列(`value_col`)と基準列(`category_col`)以外の全列が自動的にGROUP BYの対象になります。 - IN句の値はコンパイル時に確定するリテラルである必要があります(動的な列一覧は不可)。 ## 関連ドキュメント - [SELECT hint syntax](../select-hint-syntax/) — SELECTヒントの構文と使用例 --- title: "ウィンドウ関数 / OVER" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/window-function-over-syntax/ language: ja kind: page --- # ウィンドウ関数 / OVER Machbaseの`LAG()`と`LEAD()`は、クエリ結果の各行から前または後の行の値を参照します。 例えばセンサー別の測定値を時刻順に比較し、直前の測定値との差を求められます。 `GROUP BY`集計と異なり、複数行を1行に集約しません。 ## 構文 ```sql LAG(value_expression, offset) OVER ( [PARTITION BY partition_expression] [ORDER BY order_expression] ) LEAD(value_expression, offset) OVER ( [PARTITION BY partition_expression] [ORDER BY order_expression] ) ``` | 要素 | 説明 | |------|------| | `value_expression` | 前または後の行から取得する値 | | `offset` | 現在行から離れた行数。1以上の整数を指定 | | `PARTITION BY` | 比較する行をグループに分ける単一の式。省略すると全結果を1グループとして処理 | | `ORDER BY` | グループ内の比較順序を決める単一の式 | `OVER`は必須ですが、括弧内の`PARTITION BY`と`ORDER BY`は省略できます。時刻順の比較には `ORDER BY time`などの基準を明示してください。ソートキーが同じ行の順序は、この式だけでは区別できません。 最終結果の出力順序が必要な場合は、SELECT文の末尾にも`ORDER BY`を指定します。 ## 対応するウィンドウ関数 | 関数 | 説明 | |------|------| | `LAG(value, n)` | 同じグループで現在行のn行前の値 | | `LEAD(value, n)` | 同じグループで現在行のn行後の値 | 参照する行がなければNULLを返します。`offset`は時間間隔ではなく行数です。測定間隔が不規則な場合、 直前の行が必ず1秒前や1分前の測定値とは限りません。 ### 他のDBMSのウィンドウ構文との違い 次の構文をMachbaseの`LAG`/`LEAD`構文と混同しないでください。 - `ROW_NUMBER()`、`RANK()`、`DENSE_RANK()`、`FIRST_VALUE()`、`LAST_VALUE()`はサポートしません。 - `SUM(...) OVER (...)`や`AVG(...) OVER (...)`などの集約ウィンドウ関数はサポートしません。 - `ROWS`/`RANGE`フレームと`UNBOUNDED PRECEDING`、`CURRENT ROW`などのフレーム境界は指定できません。 - `OVER`内の`PARTITION BY`と`ORDER BY`には、それぞれ1つの式のみ指定できます。`ORDER BY`の後に`ASC`/`DESC`を指定する構文もサポートしません。 結果行に番号を付ける`ROWNUM()`と連続区間番号を求める`SERIESNUM()`は、 [ウィンドウ/系列関数](../../functions/series/)で説明します。 ## 例 ### LAG / LEAD: 前後の値の比較 次の例は、`name`、`time`、`value`列を持つ`sensor_tag`テーブルを使用します。 ```sql SELECT name, time, value, LAG(value, 1) OVER (PARTITION BY name ORDER BY time) AS prev_value, LEAD(value, 1) OVER (PARTITION BY name ORDER BY time) AS next_value, value - LAG(value, 1) OVER (PARTITION BY name ORDER BY time) AS delta FROM sensor_tag WHERE name = 'TEMP-01' AND time >= TO_DATE('2024-01-01', 'YYYY-MM-DD') ORDER BY name, time; ``` `prev_value`と`next_value`は参照範囲内の前・次の値です。先頭行の`prev_value`と最終行の`next_value`は NULLです。`WHERE`で除外した過去の行は比較対象に含まれないため、先頭行の差も必要な場合は参照範囲を過去へ広げます。 ### 集計結果の前の値との比較 タグ別の時間区間を先に集計し、集計値間の変化を比較できます。次の例は、時間単位のROLLUPを参照できる `sensor_tag`テーブルを前提とします。 ```sql SELECT name, bucket, avg_val, LAG(avg_val, 1) OVER (PARTITION BY name ORDER BY bucket) AS prev_avg FROM ( SELECT name, rollup('hour', 1, time) AS bucket, AVG(value) AS avg_val FROM sensor_tag WHERE time BETWEEN TO_DATE('2024-01-01', 'YYYY-MM-DD') AND TO_DATE('2024-07-01', 'YYYY-MM-DD') GROUP BY name, bucket ) t ORDER BY name, bucket; ``` このクエリは、区間別の平均と直前区間の平均を比較します。移動平均や累積合計を計算するクエリではありません。 データのない区間は自動補完しません。 ## 性能上の注意 ウィンドウ計算にはグループ分割、ソート、前後の行値の保持が必要です。時間範囲とタグ条件で対象行を減らし、 長期傾向の比較は集計結果に適用すると処理行数を減らせます。 `LAG`/`LEAD`はSELECTの結果式で使用します。`WHERE`、`HAVING`、`GROUP BY`、`ORDER BY`、JOINの`ON`条件で 直接呼び出さないでください。計算値で絞り込むには、外側のSELECTからインラインビューの結果列を参照します。 ## 関連ドキュメント - [ウィンドウ/系列関数](../../functions/series/) — `ROWNUM()`と`SERIESNUM()` - [PIVOT構文](../pivot-syntax/) — 行を列へ変換 - [SERIES BY構文](../series-syntax/) — 連続区間の抽出 --- title: "SERIES BY" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/series-syntax/ language: ja kind: page --- # SERIES BY `SERIES BY`句はソート済みの結果集合から、特定条件を満たす連続した行の区間(series)を抽出します。連続区間の開始/終了時刻やパターンの分析に使用します。 ## 構文 ```sql SELECT ... FROM table_name [WHERE ...] ORDER BY col [ASC | DESC] SERIES BY condition_expr ``` - `ORDER BY`句がなければ、`_ARRIVAL_TIME`列でソートします。 - `GROUP BY`を使用する場合や、`_ARRIVAL_TIME`列がないVOLATILE / LOOKUPテーブルでは、必ず`ORDER BY`を明示してください。 - `SERIES BY`条件を連続して満たす同一区間の行は、同じ`SERIESNUM()`値を持ちます。 ## 例 ### 基本的な使用方法 ```sql CREATE LOG TABLE t1 (c1 INTEGER, c2 INTEGER); INSERT INTO t1 VALUES (0, 1); INSERT INTO t1 VALUES (1, 2); INSERT INTO t1 VALUES (2, 3); INSERT INTO t1 VALUES (3, 2); INSERT INTO t1 VALUES (4, 1); INSERT INTO t1 VALUES (5, 2); INSERT INTO t1 VALUES (6, 3); INSERT INTO t1 VALUES (7, 1); SELECT c1, c2 FROM t1 ORDER BY c1 SERIES BY c2 > 1; ``` 結果: ``` C1 C2 --------------------------- 1 2 2 3 3 2 5 2 6 3 ``` ### SERIESNUM()で区間番号を確認 ```sql SELECT c1, c2, SERIESNUM() AS grp FROM t1 ORDER BY c1 SERIES BY c2 > 1; ``` 結果: ``` C1 C2 GRP ----------------------------------- 1 2 1 2 3 1 3 2 1 5 2 2 6 3 2 ``` ### TAGテーブルで連続区間を分析 内側のクエリで連続区間別の番号を生成し、外側のクエリで区間番号を基準に集計します。 ```sql -- 100を超える連続区間ごとの開始/終了時刻と最大値を参照 SELECT MIN(time) AS start_time, MAX(time) AS end_time, MAX(value) AS peak_value, series_id FROM ( SELECT time, value, SERIESNUM() AS series_id FROM tag WHERE name = 'PRESSURE-01' AND time >= TO_DATE('2024-01-01', 'YYYY-MM-DD') ORDER BY time SERIES BY value > 100.0 ) GROUP BY series_id ORDER BY series_id; ``` ## 関連ドキュメント - [SELECT hint syntax](../select-hint-syntax/) — SELECTヒントの構文と使用例 - [window function / OVER syntax](../window-function-over-syntax/) — ウィンドウを使った分析との違い --- title: "SAVE DATA INTO" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/save-data-into-syntax/ language: ja kind: page --- # SAVE DATA INTO `SAVE DATA INTO`は`SELECT`クエリの結果をCSVファイルに保存する構文です。 ## 構文 ```sql SAVE DATA INTO 'file_path' [HEADER { ON | OFF }] [{ FIELDS | COLUMNS } [TERMINATED BY 'char'] [ENCLOSED BY 'char'] ] [ENCODED BY coding_name] AS select_query ``` ## オプション | オプション | デフォルト値 | 説明 | |------|--------|------| | `HEADER { ON \| OFF }` | OFF | 先頭行に列名を出力するかどうか | | `TERMINATED BY 'char'` | `,` | フィールド区切り文字 | | `ENCLOSED BY 'char'` | `"` | フィールドの引用文字 | | `ENCODED BY coding_name` | UTF8 | 出力ファイルのエンコーディング | 対応するエンコーディング: `UTF8`, `MS949`, `KSC5601`, `EUCJP`, `SHIFTJIS`, `BIG5`, `GB231280` ## 例 ```sql -- 基本的なCSV保存 SAVE DATA INTO '/tmp/result.csv' AS SELECT * FROM sensor_log; -- ヘッダーを含め、セミコロンで区切る SAVE DATA INTO '/tmp/output.csv' HEADER ON FIELDS TERMINATED BY ';' AS SELECT name, time, value FROM sensor_log WHERE time > TO_DATE('2024-01-01', 'YYYY-MM-DD'); -- 区切り文字と引用文字を指定 SAVE DATA INTO '/tmp/export.csv' HEADER ON FIELDS TERMINATED BY ';' ENCLOSED BY '\'' ENCODED BY MS949 AS SELECT * FROM t1 WHERE i1 > 100; -- TAGテーブルのデータをエクスポート SAVE DATA INTO '/tmp/tag_export.csv' HEADER ON AS SELECT name, time, value FROM sensor_tag WHERE name = 'TEMP-01' AND time BETWEEN TO_DATE('2024-01-01', 'YYYY-MM-DD') AND TO_DATE('2024-01-02', 'YYYY-MM-DD') ORDER BY time; ``` ## 注意事項 - ファイルパスはMachbaseサーバープロセスが書き込める場所を指定してください。 - 出力先にファイルが存在するとエラーになり、既存ファイルは変更しません。別のファイル名を指定するか、既存ファイルを移動してから再実行してください。 - SELECT結果がない場合、空のファイルやヘッダーのみのファイルが生成される場合があります。 - ファイルパスへのアクセス権がなければエラーを返します。 ## 関連ドキュメント - [LOAD DATA INFILE syntax](../load-data-infile-syntax/) — ファイルからテーブルへのデータ取り込み --- title: "DDL" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/ddl-syntax/ language: ja kind: page --- # DDL DDL(Data Definition Language)は、テーブル、インデックス、ビュー、ROLLUPなどのデータベースオブジェクトを作成・変更・削除する構文です。 > **権限**: 一般ユーザーがアクティブなデータベースでDDLを実行するには、`GRANT DDL ON DATABASE database_name TO user_name;`または`GRANT CREATE ON DATABASE database_name TO user_name;`が必要です。詳細は[GRANT/REVOKE](../user-auth-syntax/#grant-revoke)を参照してください。 ## CREATE TABLE ```sql create_table_stmt ::= 'CREATE' table_type? 'TABLE' ['IF NOT EXISTS'] table_name '(' column_def ( ',' column_def )* ')' [ 'METADATA' '(' column_def ( ',' column_def )* ')' ] [ table_property_list ] [ 'TABLESPACE' tablespace_name ] [ 'WITH ROLLUP' rollup_interval_spec ] table_type ::= 'LOG' | 'TAG' | 'VOLATILE' | 'LOOKUP' | 'TRANSACTION' | 'TXN' -- table_typeを省略するとTRANSACTIONテーブルが作成されます。 column_def ::= column_name column_type [ 'PRIMARY KEY' ] [ 'NOT NULL' ] [ column_axis ] [ 'SUMMARIZED' ] [ 'DEFAULT' value ] [ 'PROPERTY' '(' column_property_list ')' ] decimal_type ::= ( 'DECIMAL' | 'NUMERIC' | 'DEC' | 'FIXED' | 'NUMBER' ) [ '(' precision [ ',' scale ] ')' ] array_type ::= ( 'SHORT' | 'INT16' | 'USHORT' | 'UINT16' | 'INTEGER' | 'INT' | 'INT32' | 'UINTEGER' | 'UINT32' | 'LONG' | 'INT64' | 'ULONG' | 'UINT64' | 'FLOAT' | 'DOUBLE' | decimal_type ) '[' cardinality ']' column_axis ::= 'BASETIME' | 'BASE TIME' | 'BASE DISTANCE' | 'BASEDISTANCE' column_property_list ::= ( 'MINMAX_CACHE_SIZE' '=' number | 'PART_PAGE_COUNT' '=' number | 'PAGE_VALUE_COUNT' '=' number | 'MAX_CACHE_PART_COUNT' '=' number | 'SEQUENCE' '=' number ) ( ',' column_property_list )* table_property_list ::= ( 'TAG_PARTITION_COUNT' '=' number | 'TAG_DATA_PART_SIZE' '=' number | 'TAG_STAT_ENABLE' '=' ( '0' | '1' ) | 'TAG_DUPLICATE_CHECK_DURATION' '=' number | 'VARCHAR_FIXED_LENGTH_MAX' '=' number ) ( ',' table_property_list )* ``` ### テーブルタイプ | キーワード | 説明 | |--------|------| | (なし) | **TRANSACTIONテーブル** - リレーショナルデータとトランザクションに対応 | | `LOG` | **LOGテーブル** - 時系列ログデータ。追加(INSERT)中心で、一般的なUPDATEは不可 | | `TAG` | **TAGテーブル** - タグ名・時刻・値の構造の時系列データ。BASETIME列が必須 | | `LOOKUP` | **LOOKUPテーブル** - メモリ常駐。PRIMARY KEYが必須。DML全体に対応 | | `VOLATILE` | **VOLATILEテーブル** - メモリ常駐。サーバー再起動時にデータが消失。PRIMARY KEYは任意 | | `TRANSACTION`, `TXN` | **TRANSACTIONテーブル** - 正式名と短縮形は同じテーブルを作成 | タイプ指定のない`CREATE TABLE`、`CREATE TRANSACTION TABLE`、`CREATE TXN TABLE`は、すべてTRANSACTIONテーブルを作成します。 LOGテーブルの作成には`CREATE LOG TABLE`を使用します。 以前の公開名称`RDB`と`TRX`は、テーブルタイプの別名としてサポートしていません。 TRANSACTIONはStandard Edition専用のため、Cluster Editionでは3つの作成構文がすべて拒否されます。 `DECIMAL`はすべてのテーブルタイプで使用できます。精度は`1~65`、小数桁数は`0~30`で、小数桁数は精度を超えられません。 詳細は[DECIMALとNUMERIC固定小数点型](/ja/dbms/reference/sql/types/decimal-numeric-fixed-point/)を参照してください。 Machbase DBMS 8.7.0の`ARRAY`は、数値要素型の後に`1..1024`範囲の要素数を指定します。 サポート型とテーブル別の制約は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ### 例 ```sql -- LOGテーブルの作成: LOGキーワードを明示します。 CREATE LOG TABLE sensor_log ( id INTEGER, name VARCHAR(64), value DOUBLE, status VARCHAR(20) ); -- TAGテーブルの作成(BASETIME必須。SUMMARIZEDはROLLUP対象列に指定) CREATE TAG TABLE tag ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); -- TAGテーブル + メタデータ + プロパティ CREATE TAG TABLE sensors ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ) METADATA ( location VARCHAR(100), unit VARCHAR(20) ) TAG_PARTITION_COUNT = 4; -- LOOKUPテーブル(PRIMARY KEY必須) CREATE LOOKUP TABLE devices ( device_id VARCHAR(40) PRIMARY KEY, ip IPV4, status VARCHAR(20) ); -- VOLATILEテーブル CREATE VOLATILE TABLE cache_data ( id INTEGER PRIMARY KEY, value DOUBLE ); -- TRANSACTIONテーブルの正確な固定小数点列 CREATE TRANSACTION TABLE invoice ( id LONG PRIMARY KEY, amount DECIMAL(18,2), tax NUMERIC(18,4) ); -- IF NOT EXISTSの使用 CREATE TAG TABLE IF NOT EXISTS tag ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); -- NOT NULL制約 CREATE TABLE t1 ( c1 INTEGER NOT NULL, c2 VARCHAR(200) ); ``` ### 定義済みシステム列 次のシステム列が提供されます。 | 列 | 型 | 説明 | |------|------|------| | `_ARRIVAL_TIME` | DATETIME | LOGテーブルだけで提供。レコードの挿入時刻で、`DURATION`クエリの基準 | | `_RID` | LONG | LOGテーブルとTAGテーブルの内部データテーブルで提供。レコードの一意識別子で、ユーザーによる直接指定は不可 | --- ## DROP TABLE ```sql drop_table_stmt ::= 'DROP TABLE' table_name ``` 指定テーブルと、そのすべてのデータ・インデックスを削除します。 他のセッションがそのテーブルを検索中の場合はエラーになります。 ```sql DROP TABLE sensor_log; ``` --- ## ALTER TABLE `ALTER TABLE`はテーブルのスキーマを変更します。使用可能なサブ構文はテーブルタイプによって異なります。 TRANSACTIONは`ADD COLUMN`、`DROP COLUMN`、`RENAME COLUMN`、`RENAME TO`に対応します。 TAGのメタデータ列には、`METADATA ADD COLUMN`と`METADATA DROP COLUMN`を使用します。 ### ADD COLUMN ```sql alter_table_add_stmt ::= 'ALTER TABLE' table_name [ 'METADATA' ] 'ADD COLUMN' '(' column_name column_type [ 'DEFAULT' value ] ')' ``` ```sql -- 列の追加 ALTER TABLE sensor_log ADD COLUMN (quality FLOAT); -- TRANSACTION列の追加 ALTER TABLE product_master ADD COLUMN (stock_qty INTEGER DEFAULT 0); -- デフォルト値とともに追加 ALTER TABLE sensor_log ADD COLUMN (flag INTEGER DEFAULT 0); ALTER TABLE sensor_log ADD COLUMN (tag_ip IPV4 DEFAULT '192.168.0.1'); -- ARRAY列とDEFAULTの追加 ALTER TABLE sensor_log ADD COLUMN (channels INT32[3] DEFAULT [1, NULL, 3]); -- TAG METADATA ARRAY列の追加 ALTER TABLE sensor_tag METADATA ADD COLUMN (limits DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); ``` `DECIMAL(p)[n]`のARRAYで小数桁数を省略すると、0として処理します。 ARRAY DEFAULTの要素数は、宣言した要素数と正確に一致する必要があります。 不正な要素型、要素数、精度、小数桁数、ネスト・多次元宣言、長さの異なるDEFAULTでは、列を部分的に作成せず文全体が失敗します。 #### ARRAY ADD COLUMNのサポート範囲 | Edition | テーブルまたは列領域 | 対応 | 既存行の明示的DEFAULT | |---|---|:---:|---| | Standard | LOG | O | 適用 | | Standard | VOLATILE | O | 適用せず、列全体のNULLを保持 | | Standard | LOOKUP | O | 適用 | | Standard | TRANSACTION | O | 適用 | | Standard | TAG METADATA | O | 適用 | | Standard | TAG DATAの一般列 | X | - | | Cluster | LOG | O | 適用 | | Cluster | その他のテーブルまたはTAG METADATA | X | - | DEFAULTがなければ、対応するすべてのテーブルで、ALTER前から存在する行の新しいARRAY列は列全体がNULLになります。 TAG DATAの一般ARRAY列は`CREATE TABLE`で宣言できますが、ALTERで追加できません。 型とNULLの仕様は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ### DROP COLUMN ```sql alter_table_drop_stmt ::= 'ALTER TABLE' table_name [ 'METADATA' ] 'DROP COLUMN' '(' column_name ')' ``` ```sql ALTER TABLE sensor_log DROP COLUMN (quality); ALTER TABLE product_master DROP COLUMN (stock_qty); ALTER TABLE sensor_log DROP COLUMN (channels); ALTER TABLE sensor_tag METADATA DROP COLUMN (limits); ``` ### RENAME COLUMN ```sql alter_table_column_rename_stmt ::= 'ALTER TABLE' table_name 'RENAME COLUMN' old_column_name 'TO' new_column_name ``` ```sql ALTER TABLE sensor_log RENAME COLUMN status TO device_status; ALTER TABLE product_master RENAME COLUMN name TO product_name; ``` ### MODIFY COLUMN ```sql alter_table_modify_stmt ::= 'ALTER TABLE' table_name 'MODIFY COLUMN' ( '(' column_name 'VARCHAR' '(' new_size ')' ')' | column_name ( 'NOT NULL' [ 'NOCHECK' ] | 'NULL' | 'SET' 'MINMAX_CACHE_SIZE' '=' value ) ) ``` 次の長さ拡張とMINMAXの例は、LOGテーブルを対象にします。 既存VARCHARの長さは拡張できますが、縮小や他の型からVARCHARへの変換はできません。 LOGの新しい長さは最大32,767バイトです。 MINMAX_CACHE_SIZEは、LOGのサポートされる固定長列に適用し、VARCHAR・TEXTなどの可変長列には適用できません。 LOGでオプションなしのNOT NULLは既存行も検査します。 NOCHECKはその検査を省略するだけで、既存NULLを埋めるオプションではありません。 NULLはその制約を解除します。 TAGにはこの範囲を一括で適用せず、[TAG列の変更](/ja/dbms/tag-table-usage/create-alter-drop/)の別の制約を確認してください。 TRANSACTIONテーブルは`MODIFY COLUMN`をサポートしていません。 ```sql -- VARCHARの長さ拡張(縮小は不可) ALTER TABLE sensor_log MODIFY COLUMN (name VARCHAR(128)); -- NOT NULLの追加 ALTER TABLE sensor_log MODIFY COLUMN id NOT NULL; -- NOT NULLの解除 ALTER TABLE sensor_log MODIFY COLUMN id NULL; -- MINMAX_CACHE_SIZEの変更 ALTER TABLE sensor_log MODIFY COLUMN id SET MINMAX_CACHE_SIZE = 10240; ``` ### RENAME TO ```sql alter_table_rename_stmt ::= 'ALTER TABLE' table_name 'RENAME TO' new_name ``` ```sql -- TRANSACTIONテーブルでサポート ALTER TABLE product_master RENAME TO product_catalog; ``` ### ADD / DROP RETENTION Retentionの適用・解除構文は、[RETENTION構文](../retention-syntax/)を参照してください。 --- ## TRUNCATE TABLE ```sql truncate_table_stmt ::= 'TRUNCATE TABLE' table_name ``` テーブルの全データを削除します。他のセッションがそのテーブルを検索中の場合はエラーになります。 ```sql TRUNCATE TABLE sensor_log; ``` --- ## CREATE INDEX インデックスタイプ、テーブル別のサポート範囲、JSONパス、属性は、[INDEX構文](../index-syntax/)を参照してください。 --- ## DROP INDEX 削除構文と制約は、[INDEX構文](../index-syntax/#drop-index)を参照してください。 --- ## CREATE TABLESPACE ```sql create_tablespace_stmt ::= 'CREATE TABLESPACE' tablespace_name 'DATADISK' datadisk_list datadisk_list ::= data_disk ( ',' data_disk )* data_disk ::= disk_name '(' 'DISK_PATH' '=' '"' path '"' [ ',' 'PARALLEL_IO' '=' number ] ')' ``` ```sql -- 単一ディスクのテーブルスペース CREATE TABLESPACE tbs1 DATADISK disk1 (DISK_PATH="tbs1_disk1"); -- 並列I/O設定 CREATE TABLESPACE tbs2 DATADISK disk1 (DISK_PATH="tbs2_disk1", PARALLEL_IO = 5); -- 複数ディスク CREATE TABLESPACE tbs3 DATADISK disk1 (DISK_PATH="tbs3_d1", PARALLEL_IO = 10), disk2 (DISK_PATH="tbs3_d2"), disk3 (DISK_PATH="tbs3_d3"); ``` --- ## DROP TABLESPACE ```sql drop_tablespace_stmt ::= 'DROP TABLESPACE' tablespace_name ``` ```sql DROP TABLESPACE tbs1; ``` テーブルスペースに作成されたオブジェクトがある場合は、削除できません。 --- ## CREATE ROLLUP 基本・条件付き・Custom ROLLUPの構文は、[ROLLUP構文](../rollup-syntax/)を参照してください。 --- ## DROP ROLLUP 削除構文は、[ROLLUP構文](../rollup-syntax/#drop-rollup)を参照してください。 --- ## ALTER ROLLUP 開始・停止・強制実行・周期変更は、[ROLLUP構文](../rollup-syntax/#alter-rollup)を参照してください。 --- ## CREATE RETENTION 作成構文とテーブルへの適用は、[RETENTION構文](../retention-syntax/)を参照してください。 --- ## DROP RETENTION 削除構文と解除順序は、[RETENTION構文](../retention-syntax/#drop-retention)を参照してください。 --- ## DDLの同時実行性とロック {#ddl-concurrency} Machbase 8.7.0 Standard Editionは、独立したオブジェクトのDDLをオブジェクト単位で調整します。 したがって、同じデータベースで異なる名前のLOG、TAG、VOLATILE、LOOKUP、TRANSACTIONテーブルを作成・変更するDDLは、同時に進行できます。 | Edition | 独立オブジェクトのDDL | 競合範囲 | 競合時の待機設定 | |---------|-----------------|-----------|-------------------| | Standard | 同時に進行可能 | 同じオブジェクトと直接関連するオブジェクト | `DDL_LOCK_TIMEOUT` | | Cluster | 既存ポリシーに従って直列化 | カタログ範囲 | `DDL_LOCK_TIMEOUT`は提供しない | 独立したオブジェクトのDDLが同時に開始しても、メタデータ処理やストレージI/Oなどの共通処理を共有する場合があります。 そのため、クライアント数に比例したスループット向上や、すべてのDDLの同時完了は保証しません。 ### 競合するオブジェクト | 同時実行の状況 | 動作 | |----------------|------| | 名前が異なる独立テーブル | テーブルタイプに関係なく同時に進行可能 | | 同じオブジェクト、または同名オブジェクト | 1つのDDLだけが進み、他は待機またはエラー | | テーブルの変更・削除DDLと、そのテーブルのインデックスDDL | 関連するオブジェクトとして処理 | | ビューDDLと、ビューが参照するテーブルの変更・削除DDL | 関連するオブジェクトとして処理 | | TAGテーブルの変更・削除DDLと、そのROLLUPまたはRetentionのDDL | 関連するオブジェクトとして処理 | | `DROP VIEW`、`CREATE OR REPLACE VIEW`、システム範囲のDDL | より広い範囲で直列化される場合がある | テーブルタイプが異なっても、同じテーブル名は1つの名前空間を使用します。 例えば、同名のLOGとTAGテーブルを同時に作成すると、どちらか1つだけが作成されます。 ### DDLロックの待機時間 Standard Editionでは、`DDL_LOCK_TIMEOUT`で競合するDDLロックの待機時間を秒単位で設定します。 | 値 | 動作 | |---:|------| | `0` | 待機せず直ちに`ERR-02031: Resource busy ()`を返す | | 正数 | 指定時間まで待機し、ロックを取得できなければ`ERR-02031`を返す | エラーメッセージの括弧内には、代表的な競合オブジェクトが表示されます。 広い範囲で競合したDDLは、オブジェクト名の代わりに`DDL`と表示される場合があります。 デフォルトは`0`、設定範囲は`0`~`1000000`です。 現在のセッションの値を変更するには、次の文を実行します。 ```sql ALTER SESSION SET DDL_LOCK_TIMEOUT = 10; ``` 1つのDDLが複数のロック段階を経ても、待機時間は段階ごとに再開始されません。 ロック取得後にオブジェクトと依存関係を再確認するため、先行DDLの結果に応じて、 `already exists`、`table not found`などの一般的なSQLエラーが返される場合があります。 `DDL_LOCK_TIMEOUT`はDDLロックの待機時間だけを制限し、SQL全体の実行時間は制限しません。 実行中のDDLは開始時点の値を継続して使用し、`ALTER SESSION`で変更した値は次のDDLから適用されます。 DDLのコミットと復旧動作は以前のバージョンと同じで、新たな暗黙的コミットは行いません。 | 設定 | 単位 | 制限対象 | |------|------|-----------| | `DDL_LOCK_TIMEOUT` | 秒 | Standard EditionのDDLロック待機 | | `SESSION_QUERY_TIMEOUT_SEC` / `QUERY_TIMEOUT` | 秒 | クエリ実行と応答待機 | | `TRANSACTION_BUSY_TIMEOUT_MS` | ミリ秒 | TRANSACTIONテーブルの同時書き込み競合待機 | --- ## 関連文書 - [テーブルタイプ](/ja/dbms/data-modeling-table-design/) - LOG、TAG、LOOKUP、VOLATILE、TRANSACTIONの特性と使用ガイド - [TAGテーブルのROLLUP](/ja/dbms/tag-table-usage/create-alter-drop/#original-85-creating-tag-tables) - ROLLUPの作成と運用ガイド - [GRANT/REVOKE](../user-auth-syntax/#grant-revoke) - DDL実行に必要な権限の付与 - [ALTER SESSION](../system-session-alter-syntax/#alter-session) - 現在のセッションのDDLロック待機時間の設定 - [スキーマ変更チェックリスト](/ja/dbms/operations-configuration-recovery/checklist-schema-alter/) - 運用中のDDL実行と競合対応 --- title: "DML" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/dml-syntax/ language: ja kind: section --- # DML DML(Data Manipulation Language)は、テーブルのデータを挿入・更新・削除する構文です。 ## テーブルタイプ別のDML対応 | 構文 | LOG | TAG | LOOKUP | VOLATILE | TRANSACTION | |------|:---:|:---:|:------:|:--------:|:---:| | INSERT | O | O | O | O | O | | INSERT SELECT | O | O | O | O | O | | UPDATE | - | O(タグ・軸条件またはメタデータ) | O(一般条件式) | O(PK条件) | O | | DELETE | O(保持条件・全件) | O(時間・名前条件) | O(一般条件式・全件) | O(PK条件) | O | | DELETE WHERE | - | O(タグ・軸条件) | O(一般条件式) | O(PK等価条件) | O | | TRUNCATE | O | - | - | - | O | > LOGテーブルのUPDATEは未サポートです。データ更新が必要なら、LOOKUPまたはVOLATILEを使用するか、TRANSACTIONテーブルを選択してください。 --- ## INSERT INTO ```sql insert_stmt ::= 'INSERT INTO' table_name [ 'METADATA' ] [ '(' insert_column_list ')' ] 'VALUES' '(' value_list ')' [ 'ON DUPLICATE KEY UPDATE' [ 'SET' set_list ] ] insert_column_list ::= insert_target ( ',' insert_target )* insert_target ::= column_name | array_column_name '[' position ']' value_list ::= value ( ',' value )* set_list ::= column_name '=' value ( ',' column_name '=' value )* ``` 指定しない列にはNULLが入力されます。`METADATA`は、TAGテーブルのメタデータ列に挿入する場合に使用します。 ```sql -- 基本の挿入 INSERT INTO sensor_log VALUES (1, 'sensor-01', 23.5, 'OK'); -- 列を指定して挿入 INSERT INTO sensor_log (name, value) VALUES ('sensor-01', 23.5); -- TAGテーブルのメタデータ挿入 INSERT INTO sensors METADATA (name, location, unit) VALUES ('sensor-01', 'building-A', 'celsius'); ``` ### ARRAY要素の指定 Machbase DBMS 8.7.0では、`INSERT ... VALUES`の列リストに固定長`ARRAY`の位置を指定できます。 位置は0始まりで、指定しない要素は要素のNULLとして保存されます。 ```sql CREATE LOG TABLE array_input ( id INTEGER, channels INT32[4] ); INSERT INTO array_input (id, channels[0], channels[3]) VALUES (1, 10, 40); ``` 同じ文で配列全体と要素を同時に対象にしたり、同じ位置を2回指定したりすることはできません。 スカラー列や範囲外の位置も、要素の対象として使用できません。 添字付き対象は、`INSERT ... SELECT`と`UPDATE SET`ではサポートしていません。 ARRAY値の生成、疎な入力、Appendの選択対象は、 [数値ARRAY型](/ja/dbms/reference/sql/types/array/)と [Sparse ARRAYと選択列Append API](/ja/dbms/development-tools-integration/data-input-load-export/array-append/)を参照してください。 ### ON DUPLICATE KEY UPDATE `INSERT ... VALUES`でキーが重複した場合、既存行をUPDATEします。 `INSERT ... SELECT`とは組み合わせられません。 | テーブルタイプ | 重複判定キー | サポート範囲 | |---|---|---| | TRANSACTION | PRIMARY KEY、単一・複合UNIQUE INDEX | Standard Edition | | LOOKUP | PRIMARY KEY | サポート | | VOLATILE | PRIMARY KEY | サポート | | TAG METADATA | タグ名PRIMARY KEY | サポート | | TAG DATA、LOG | - | 未サポート | `SET`を省略すると、INSERT入力値で既存の非キー列を更新します。 `SET`がある場合は、右辺の式を重複した既存行を基準に評価します。 LOOKUP・VOLATILE・TRANSACTIONではPRIMARY KEY自体を更新できません。 TAG METADATAのタグ名とシステム管理列は、[TAGメタデータ](/ja/dbms/tag-table-usage/tag-metadata/)の変更規則に従います。 ```sql -- キー重複時にvalue列だけを更新 INSERT INTO devices (device_id, ip, status) VALUES ('dev-001', '192.168.1.1', 'ONLINE') ON DUPLICATE KEY UPDATE SET status = 'ONLINE'; -- SET句なしでは全列を挿入値で更新 INSERT INTO devices (device_id, ip, status) VALUES ('dev-001', '192.168.1.2', 'ONLINE') ON DUPLICATE KEY UPDATE; ``` 重複判定キーのないテーブルのUPSERT、キー変更、`VALUES(col)`・`EXCLUDED.col`など他のDBMS専用の式はエラーです。 TRANSACTIONのUNIQUE競合・トランザクションの例は、[TRANSACTIONのUPSERT](/ja/dbms/rdb-table-usage/insert-on-duplicate-key-update/)を参照してください。 --- ## INSERT SELECT ```sql insert_select_stmt ::= 'INSERT INTO' table_name [ '(' insert_column_list ')' ] [ with_clause ] select_stmt ``` SELECT結果をテーブルに挿入します。 Standard Editionでは、対象テーブルと列リストの後に`WITH`句を置けます。 文頭の`WITH ... INSERT INTO ...`形式はサポートしていません。 ```sql -- クエリ結果を別のテーブルへコピー INSERT INTO sensor_log_copy SELECT * FROM sensor_log; -- _arrival_timeを明示して挿入(時間順序の保証が必要) INSERT INTO sensor_log_copy (_arrival_time, id, name, value) SELECT _arrival_time, id, name, value FROM sensor_log ORDER BY _arrival_time; -- CTE結果の挿入 INSERT INTO sensor_log_copy (id, name, value) WITH filtered AS ( SELECT id, name, value FROM sensor_log WHERE value >= 80 ) SELECT id, name, value FROM filtered; ``` 注意事項: - `_ARRIVAL_TIME`を明示しなければ、INSERT実行時点の時刻が自動入力されます。 - LOGの明示時刻のコピーは、空の対象に昇順で入力し、他の入力処理と分離してください。 対象により新しい時刻があれば、元データをソートしていても時刻逆転になります。 デフォルトの`DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE=1`では逆転値を直前の保存時刻+1nsに補正し、0では拒否します。 したがって、明示入力は元の時刻の保持を無条件に保証しません。 - VARCHAR列で挿入値が最大長を超えると、自動的に切り詰めて入力します。 - LOG/TAGへの入力は、TRANSACTIONテーブルのトランザクションのROLLBACK対象ではありません。 --- ## UPDATE ```sql update_stmt ::= 'UPDATE' table_name [ 'METADATA' ] 'SET' update_expr_list [ 'WHERE' predicate ] update_expr_list ::= column_name '=' value ( ',' column_name '=' value )* ``` TRANSACTIONテーブルは、WHERE句を省略すると全行を更新します。 LOOKUPは主キーまたは一般条件式、VOLATILEは主キーの一致条件を使用します。 TAGデータUPDATEは、タグ選択子と時間軸条件を併用します。 ```sql -- LOOKUPテーブルのレコード更新 UPDATE devices SET status = 'OFFLINE' WHERE device_id = 'dev-001'; -- 複数列を同時に更新 UPDATE devices SET ip = '10.0.0.1', status = 'ONLINE' WHERE device_id = 'dev-002'; -- LOOKUPの一般条件式で複数行を更新 UPDATE devices SET status = 'OFFLINE' WHERE site = 'SEOUL' AND status = 'READY'; ``` ### TAGデータのUPDATE TAGテーブルの実際の時系列データは、タグ選択条件とBASETIME条件を併せて指定して更新します。 ```sql UPDATE sensors SET value = 101, status = 1 WHERE name = 'sensor-01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); ``` `name`(PRIMARY KEY)、`time`(BASETIME)、メタデータ列は、データUPDATEのSET対象ではありません。 ### UPDATE METADATA(TAGテーブル) TAGテーブルのメタデータ列は、別の`UPDATE ... METADATA`構文で更新します。 ```sql -- メタデータ条件で複数行を更新 UPDATE sensors METADATA SET status = 'DONE' WHERE status = 'READY'; -- タグ名を基準に更新 UPDATE sensors METADATA SET location = 'building-B' WHERE name = 'sensor-01'; ``` --- ## DELETE ```sql -- LOGテーブルの削除(時間・行数基準) delete_stmt ::= 'DELETE FROM' table_name [ 'OLDEST' number 'ROWS' | 'EXCEPT' number ( 'ROWS' | time_unit ) | 'BEFORE' datetime_expression ] [ 'NO WAIT' ] time_unit ::= 'YEAR' | 'MONTH' | 'WEEK' | 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND' ``` LOGテーブルは任意の位置の削除をサポートせず、最も古いデータから連続してだけ削除できます。 現在のLOGの`BEFORE t`は、`_arrival_time <= t`の行を削除します。 名前だけで境界を除外すると考えがちなため、事前検索にも同じ比較条件を使用してください。 `EXCEPT n DAY`などの期間は、最後の入力時刻ではなくサーバーの現在時刻を基準に計算します。 一般のユーザー定義DATETIME列の値は、この削除の基準ではありません。 実際の前後の結果は、[LOGの保持期間に基づく削除](/ja/dbms/log-table-usage/operations-lifecycle/)で確認できます。 ```sql -- 全データの削除 DELETE FROM sensor_log; -- 最も古いN件を削除 DELETE FROM sensor_log OLDEST 1000 ROWS; -- 最新のN件以外をすべて削除 DELETE FROM sensor_log EXCEPT 10000 ROWS; -- 直近N日間のデータ以外をすべて削除 DELETE FROM sensor_log EXCEPT 7 DAY; -- 特定時刻までのデータを削除(境界時刻を含む) DELETE FROM sensor_log BEFORE TO_DATE('2024-01-01', 'YYYY-MM-DD'); ``` ### DELETE WHERE(LOOKUP/VOLATILEテーブル) ```sql delete_where_stmt ::= 'DELETE FROM' table_name 'WHERE' predicate ``` LOOKUPは主キーまたは一般条件式、VOLATILEは主キーの一致条件を使用します。 LOOKUPはWHERE句を省略して全行を削除することもできます。 ```sql DELETE FROM devices WHERE device_id = 'dev-001'; -- LOOKUPの一般条件式で複数行を削除 DELETE FROM devices WHERE status = 'EXPIRED' OR site = 'RETIRED'; -- LOOKUPの全件削除 DELETE FROM devices; ``` ### DELETE(TAGテーブル) ```sql -- TAGテーブル: 名前または時間条件で削除 delete_from_tag_where_stmt ::= 'DELETE FROM' table_name [ 'ROLLUP' ] 'WHERE' predicate -- predicate: tag_name条件、tag_time条件、または両方のAND結合 ``` 時間条件には、`=`、`<`、`<=`、`BETWEEN`を使用できます。 ```sql -- TAG名を基準に削除 DELETE FROM tag WHERE name = 'sensor-01'; -- TAG名 + 時刻を基準に削除 DELETE FROM tag WHERE name = 'sensor-01' AND time < TO_DATE('2024-01-01', 'YYYY-MM-DD'); -- 時間条件だけで削除 DELETE FROM tag WHERE time <= TO_DATE('2024-01-01', 'YYYY-MM-DD'); -- ROLLUPデータの削除 DELETE FROM tag ROLLUP WHERE name = 'sensor-01'; DELETE FROM tag ROLLUP WHERE time BETWEEN TO_DATE('2024-01-01','YYYY-MM-DD') AND TO_DATE('2024-02-01','YYYY-MM-DD'); ``` ### DELETE FROM TAG METADATA ```sql DELETE FROM table_name METADATA [ WHERE predicate ] ``` TAGテーブルのメタデータ行を削除します。 WHEREを省略すると、すべてのメタデータを削除します。 実際のデータが存在するタグのメタデータは削除できません。 ```sql DELETE FROM sensors METADATA WHERE name = 'sensor-01'; DELETE FROM sensors METADATA WHERE status = 'STOP'; DELETE FROM sensors METADATA; -- 全メタデータを削除(実データがないタグのみ) ``` --- ## UPDATE/DELETEの影響行数 `UPDATE`と`DELETE`を実行したクライアントは、その文の影響行数(affected rows)を確認できます。 直接実行とプリペアドステートメントは、同じ基準を使用します。 `UPDATE`は、実際に値が変わった行数ではなく、`WHERE`条件に一致した行数を返します。 そのため、既存値と同じ値を再設定しても、対象行が条件に一致すれば影響行数に含まれます。 `WHERE`句を省略できるテーブルでは、すべての対象行が一致したものとして数えます。 `DELETE`は、条件に一致して実際に削除された行数を返します。 同じ`DELETE`を繰り返すと、初回に行が削除されているため、次の実行は`0`を返します。 ```sql CREATE LOOKUP TABLE device_state ( id INTEGER PRIMARY KEY, value INTEGER ); INSERT INTO device_state VALUES (1, 10); INSERT INTO device_state VALUES (2, 10); UPDATE device_state SET value = 20 WHERE id >= 1 AND id <= 2; -- 2 row(s) updated. UPDATE device_state SET value = 20 WHERE id >= 1 AND id <= 2; -- 2 row(s) updated. (同じ値で繰り返しUPDATE) UPDATE device_state SET value = 20 WHERE id = 999; -- No row updated. DELETE FROM device_state WHERE id = 1; -- 1 row(s) deleted. DELETE FROM device_state WHERE id = 1; -- No row deleted. ``` `No row updated.`または影響行数`0`は、設定値が既存値と同じという意味ではなく、条件に一致する行がなかったことを意味します。 トランザクション内で返された影響行数は、各文の実行時点の結果です。 後で`ROLLBACK`しても、すでに返された影響行数の意味は変わりません。 --- ## 関連文書 - [DDL構文リファレンス](../ddl-syntax/) - テーブルの作成とスキーマ変更 - [SELECT構文リファレンス](../select-syntax/) - データ検索 - [WITH / CTE構文](../cte-syntax/) - CTEを使用するINSERT SELECT - [LOOKUPの述語UPDATE](./lookup-predicate-update-syntax/) - 一般条件式による更新 - [LOOKUPの述語DELETE](./lookup-predicate-delete-syntax/) - 一般条件式による削除 - [LOAD DATA INFILE](../load-data-infile-syntax/) - CSVファイルの一括取り込み --- title: "TAGデータのUPDATE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/ language: ja kind: page --- # TAGデータのUPDATE TAGテーブルの時系列データは、通常の`UPDATE`文で変更します。 `UPDATE TAG TABLE`という別のキーワードは使用しません。 Machbase 8.7.0からサポートする機能 TAGデータのUPDATEは、Standard Editionの論理TAGテーブルだけでサポートします。 ## 構文 ```sql UPDATE table_name SET data_column = expression [, data_column = expression ...] WHERE tag_selector AND time_condition [AND data_predicate ...]; ``` `tag_selector`には、`name = ...`、`name IN (...)`、`name LIKE ...`条件を使用できます。 `time_condition`には、BASETIME列の等価、`BETWEEN`、両側範囲、片側範囲条件を使用できます。 ## 例 ### 単一タグと時間範囲 ```sql UPDATE sensor_tag SET value = 110, status = 1 WHERE name = 'TEMP-01' AND time >= TO_DATE('2026-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2026-07-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS'); ``` ### 複数タグ ```sql UPDATE sensor_tag SET note = 'corrected' WHERE name IN ('TEMP-01', 'TEMP-02') AND time BETWEEN TO_DATE('2026-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND TO_DATE('2026-07-01 23:59:59', 'YYYY-MM-DD HH24:MI:SS'); ``` ### LIKEとデータ列の述語 ```sql UPDATE sensor_tag SET status = 7 WHERE name LIKE 'TEMP-%' AND time >= TO_DATE('2026-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND value > 100; ``` ### CASE式 ```sql UPDATE sensor_tag SET grade = CASE WHEN 1 = 1 THEN 'HIGH' ELSE 'LOW' END WHERE name = 'TEMP-01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); ``` ### NAMEとTIME条件でのバインドパラメーター `WHERE`句のタグ名とBASETIME条件値には、位置指定マーカー`?`または名前付きマーカー`:name`を使用できます。 1つのSQL文でマーカー方式を混在させないでください。 位置指定マーカーは、SQLの出現順にSET値、タグ名、基準時刻をバインドします。 ```sql UPDATE sensor_tag SET value = ?, status = ?, note = ? WHERE name = ? AND time = ?; ``` 名前付きマーカーは、SDKの名前指定APIでSQLの出現順に関係なく値を渡せます。 ```sql UPDATE sensor_tag SET value = :value, status = :status, note = :note WHERE name = :name AND time = :time; ``` 同じプリペアドステートメントを再実行すると、新しくバインドしたSET、NAME、TIMEの値で対象行を選択します。 NAMEパラメーターは`VARCHAR`、TIMEパラメーターは`DATETIME`の型情報を保持します。 条件に一致する行がなければ、エラーなしで影響行数`0`を返します。 `? = name`、`:name = name`、`? = time`、`:time = time`のように、列が右側にある等価条件もサポートします。 ただし、読みやすさのため列を左側に書く形式を推奨します。 既存の許可されたBASETIME範囲条件の値の位置にも、マーカーを使用できます。 SDK別の名前指定APIと位置番号規則は、[Named Bind Parameter](../../named-bind-parameter-syntax/)を参照してください。 ## メタデータのUPDATE TAGのメタデータ列は、TAGデータUPDATEのSET対象ではありません。 メタデータは`UPDATE ... METADATA`構文で変更します。 ```sql UPDATE sensor_tag METADATA SET location = 'zone-2', owner = 'ops' WHERE name = 'TEMP-01'; ``` ## 制約 - WHERE句には、1つのタグ選択条件と1つ以上のBASETIME条件が必要です。 `name =`、`name IN (...)`、`name LIKE ...`と、等価・BETWEEN・両側/片側の時間範囲を使用でき、データ列条件は`AND`で追加できます。 - `OR`、サブクエリ、集計式、タグ・軸の列をそのまま参照しない式は、UPDATE対象条件に使用できません。 - `name`(PRIMARY KEY)、`time`(BASETIME)、メタデータ列、隠し列・システム列は、データUPDATEのSET対象にできません。 - SET右辺は、定数、バインド変数、既存行の列を参照しない関数・演算式・`CASE`・NULLだけを使用できます。 `value = value + 1`のように既存行の列を参照する式は許可されません。 - バインドパラメーターは値だけを置き換え、タグ選択条件、BASETIME条件、SET対象列の制約を変更しません。 - UPDATEは、すでに具体化されたROLLUP行を自動補正しません。 ROLLUPの検索前に、影響を受けた区間を`ROLLUP_REBUILD`で再構築します。 ## 関連文書 - [TAGデータUPDATEのWHERE/SET制約](../tag-data-update-where-set-constraints/) - [Named Bind Parameter](../../named-bind-parameter-syntax/) - [ROLLUP_REBUILD構文](../../rollup-rebuild-syntax/) --- title: "TAGデータUPDATEのWHERE/SET制約" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-where-set-constraints/ language: ja kind: page --- # TAGデータUPDATEのWHERE/SET制約 TAGデータのUPDATEでは、対象範囲を明確にする必要があります。 WHERE句にはタグ選択条件とBASETIME条件が両方必要で、SET句は実際のデータ列だけを対象にします。 Machbase 8.7.0からサポートする機能 ## SET句の制約 | 列の役割 | SET可否 | 説明 | |-----------|:------------:|------| | データ列 | O | `value`、補助の数値・文字列列など | | `SUMMARIZED`データ列 | O | 元のTAG行の値が変わる | | BASETIME列 | X | 時間軸列は変更不可 | | PRIMARY KEY列(`name`) | X | タグ名は変更不可 | | メタデータ列 | X | `UPDATE ... METADATA`で別途処理 | | 隠し列・システム列 | X | 内部列はSET対象外 | SET式には、定数、バインド変数、既存行の列を参照しない算術式・文字列式・`CASE`、許可された型変換関数、NULLを使用できます。 既存行の列を参照する式、サブクエリ、集計式はSET右辺に使用できません。 ## WHERE句の制約 ```sql UPDATE table_name SET col = expr WHERE name = 'tag-name' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); ``` | WHERE条件 | 対応 | |-----------|:---------:| | `name = '...'` | O | | `name = ?`, `name = :tag_name` | O | | `? = name`, `:tag_name = name` | O | | `name IN ('...', '...')` | O | | `name LIKE '...'` | O | | `time = t1` | O | | `time = ?`, `time = :base_time` | O | | `? = time`, `:base_time = time` | O | | `time BETWEEN t1 AND t2` | O | | `time >= t1 AND time < t2` | O | | `time >= ? AND time < ?` | O | | 片側の時間条件 | O | | データ列条件 | O | | タグ選択のない条件 | X | | 時間条件のない条件 | X | | `OR`条件 | X | | `IN (SELECT ...)` | X | | タグ・軸列を関数・演算式で包んだ式 | X | バインドパラメーターは、条件の値の位置だけに使用します。 タグ名列とBASETIME列をマーカーに置き換えることはできず、バインドを使ってもタグ選択条件と時間条件は両方必要です。 同じプリペアドステートメントを再実行すると、新しくバインドした値で対象を選択し、一致行がなければ影響行数`0`で成功します。 NAMEとTIMEパラメーターの型情報とSDK別APIは、 [TAGデータUPDATEのバインドパラメーター](../tag-data-update-syntax/#tag-data-update-predicate-bind)および [Named Bind Parameter](../../named-bind-parameter-syntax/)を参照してください。 ## メタデータのUPDATE ```sql UPDATE table_name METADATA SET meta_col = value WHERE condition; ``` メタデータUPDATEは、タグ属性領域を変更します。 実際の時系列行のデータ列を変更するTAGデータUPDATEとは、構文と対象が異なります。 ## 列の役割の確認 `DESC`コマンドで列属性を確認します。 ```sql DESC sensor_tag; ``` または、システムテーブルから列のFLAGを検索します。 ```sql SELECT NAME, TYPE, FLAG FROM M$SYS_COLUMNS WHERE TABLE_ID = ( SELECT ID FROM M$SYS_TABLES WHERE NAME = 'SENSOR_TAG' ); ``` | FLAG値 | 意味 | |---------|------| | 134217728 | Tag Name | | 16777216 | Base Time / Base Distance | | 33554432 | Summarized | | 67108864 | Metadata | ## エラー例 ```sql -- エラー: BASETIME列をSET対象に指定 UPDATE sensor_tag SET time = TO_DATE('2026-07-01', 'YYYY-MM-DD') WHERE name = 'TEMP-01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); -- エラー: 時間条件がない UPDATE sensor_tag SET value = 0.0 WHERE name = 'TEMP-01'; -- エラー: OR条件の使用 UPDATE sensor_tag SET value = 0.0 WHERE name = 'TEMP-01' OR name = 'TEMP-02'; ``` ## 関連文書 - [TAGデータUPDATE構文](../tag-data-update-syntax/) - [Named Bind Parameter](../../named-bind-parameter-syntax/) - [ROLLUP_REBUILD構文](../../rollup-rebuild-syntax/) --- title: "LOOKUPの述語UPDATE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-update-syntax/ language: ja kind: page --- # LOOKUPの述語UPDATE LOOKUPテーブルの`UPDATE`は、主キーの等価条件だけでなく、一般の述語を`WHERE`句で使用できます。 条件に一致するすべての行が更新されます。 ## 構文 ```sql UPDATE table_name SET column_name = expression [, column_name = expression ...] WHERE predicate; ``` ## サポートする条件の例 ```sql -- 一般列の条件 UPDATE device_lookup SET status = 'ACTIVE' WHERE site = 'SEOUL' AND status = 'READY'; -- 範囲と文字列の条件 UPDATE device_lookup SET score = score + 10 WHERE score BETWEEN 10 AND 80 AND note LIKE 'sensor-%'; -- JSONパス条件 UPDATE device_lookup SET meta = JSON_SET(meta, '$.state', 'active') WHERE meta->'$.region' = 'kr' AND JSON_EXTRACT_INTEGER(meta, '$.level') >= 3; ``` `SET`句の右辺の式は、現在の行の値を参照できます。 ```sql UPDATE device_lookup SET score = score + 1 WHERE group_name IN ('A', 'B'); ``` ## 条件のサポート範囲 | 条件 | 対応 | |------|:---:| | `pk_col = value` | O | | `non_pk_col = value` | O | | `<`, `<=`, `>`, `>=`, `<>` | O | | `BETWEEN` | O | | `IN`, `NOT IN` | O | | `LIKE`, `NOT LIKE` | O | | `AND`, `OR`, `NOT` | O | | `IS NULL`, `IS NOT NULL` | O | | `TO_DATE(...)`による日付条件 | O | | JSONの`->`, `JSON_EXTRACT_*`, `JSON_IS_VALID` | O | ## 制約 - 主キー列自体は`SET`句で変更できません。 - 条件に一致する行が複数あれば、複数行が更新されます。 - JSONパス文字列は単一引用符(`'$.key'`)で記述します。二重引用符はSQL識別子として解釈されます。 - 数値のJSON値を比較する場合は、`JSON_EXTRACT_INTEGER`、`JSON_EXTRACT_DOUBLE`などの型別関数を推奨します。 ## 関連文書 - [LOOKUPの述語DELETE構文](../lookup-predicate-delete-syntax/) - [LOOKUP SQL/JSON対応表](../../../../support-scope-constraints/lookup-sql-json/) --- title: "LOOKUPの述語DELETE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/dml-syntax/lookup-predicate-delete-syntax/ language: ja kind: page --- # LOOKUPの述語DELETE LOOKUPテーブルの`DELETE`は、主キーの等価条件だけでなく、一般の述語を`WHERE`句で使用できます。 条件に一致するすべての行が削除されます。 ## 構文 ```sql DELETE FROM table_name WHERE predicate; ``` `WHERE`句なしで実行すると、LOOKUPテーブルの全行が削除されます。 ## サポートする条件の例 ```sql -- 一般列の条件 DELETE FROM device_lookup WHERE status = 'EXPIRED'; -- 日付と範囲の条件 DELETE FROM device_lookup WHERE updated_at < TO_DATE('2026-01-01 00:00:00') OR score < 10; -- JSONパス条件 DELETE FROM device_lookup WHERE meta->'$.region' = 'kr' AND JSON_EXTRACT_INTEGER(meta, '$.level') < 2; ``` ## 条件のサポート範囲 | 条件 | 対応 | |------|:---:| | `pk_col = value` | O | | `non_pk_col = value` | O | | `<`, `<=`, `>`, `>=`, `<>` | O | | `BETWEEN` | O | | `IN`, `NOT IN` | O | | `LIKE`, `NOT LIKE` | O | | `AND`, `OR`, `NOT` | O | | `IS NULL`, `IS NOT NULL` | O | | `TO_DATE(...)`による日付条件 | O | | JSONの`->`, `JSON_EXTRACT_*`, `JSON_IS_VALID` | O | | WHERE句なしの全件削除 | O | ## 運用上の注意事項 一般述語の`DELETE`は、条件に一致するすべての行を削除します。 本番データでは、先に同じ条件で対象範囲を確認してから実行します。 ```sql SELECT COUNT(*) FROM device_lookup WHERE status = 'EXPIRED'; DELETE FROM device_lookup WHERE status = 'EXPIRED'; ``` ## 関連文書 - [LOOKUPの述語UPDATE構文](../lookup-predicate-update-syntax/) - [LOOKUP SQL/JSON対応表](../../../../support-scope-constraints/lookup-sql-json/) --- title: "LOAD DATA INFILE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/load-data-infile-syntax/ language: ja kind: page --- # LOAD DATA INFILE `LOAD DATA INFILE`は、CSV形式のデータファイルをサーバーが直接読み取り、テーブルへ入力する構文です。 > 大量データの取り込みには`machloader`ユーティリティを推奨します。 > `machloader`は並列処理と多様なオプションを提供し、より高速に取り込めます。 ## 構文 ```sql LOAD DATA INFILE 'file_path' INTO TABLE table_name [TABLESPACE tablespace_name] [AUTO { BULKLOAD | HEADUSE | HEADUSE_ESCAPE }] [{ FIELDS | COLUMNS } [TERMINATED BY 'char'] [ENCLOSED BY 'char']] [LINES TERMINATED BY 'char'] [TRIM { ON | OFF }] [IGNORE number LINES] [MAX_LINE_LENGTH number] [ENCODED BY coding_name] [ON ERROR { STOP | IGNORE }] ``` ## オプション | オプション | 説明 | |------|------| | `AUTO BULKLOAD` | 行全体を1つの列に入力 | | `AUTO HEADUSE` | 最初の行の列名でテーブルを自動作成して入力 | | `AUTO HEADUSE_ESCAPE` | `HEADUSE`と同じ。ただし予約語・特殊文字を`_`に置換 | | `TERMINATED BY 'char'` | フィールド区切り文字(デフォルト: `,`) | | `ENCLOSED BY 'char'` | フィールド引用符(デフォルト: `"`) | | `LINES TERMINATED BY 'char'` | レコード区切り文字 | | `TRIM { ON \| OFF }` | 列の前後の空白を除去するか(デフォルト: ON) | | `IGNORE number LINES` | 最初のN行を無視(ヘッダーのスキップなど) | | `MAX_LINE_LENGTH number` | 1行の最大長(デフォルト: 512KB) | | `ENCODED BY coding_name` | ファイルのエンコーディング(デフォルト: UTF8) | | `ON ERROR STOP\|IGNORE` | エラー時に停止または無視(デフォルト: STOP) | サポートするエンコーディング: `UTF8`、`MS949`、`KSC5601`、`EUCJP`、`SHIFTJIS`、`BIG5`、`GB231280` ## 例 ```sql -- 基本のCSVファイル入力(区切り: , 引用符: ") LOAD DATA INFILE '/tmp/sensor_data.csv' INTO TABLE sensor_log; -- ヘッダー1行を無視し、;区切りのファイルを入力 LOAD DATA INFILE '/tmp/data.csv' INTO TABLE sample_data FIELDS TERMINATED BY ';' ENCLOSED BY '\'' IGNORE 1 LINES ON ERROR IGNORE; -- AUTO BULKLOAD: 各行を単一列に入力(テーブルを自動作成) LOAD DATA INFILE '/tmp/raw.txt' INTO TABLE raw_table AUTO BULKLOAD; -- AUTO HEADUSE: 最初の行を列名としてテーブルを自動作成し、入力 LOAD DATA INFILE '/tmp/data_with_header.csv' INTO TABLE auto_table AUTO HEADUSE; -- エンコーディングの指定 LOAD DATA INFILE '/tmp/korean_data.csv' INTO TABLE Korean_table ENCODED BY MS949; ``` ## 注意事項 - `AUTO`オプションを使用しない場合、対象テーブルのすべての列は`VARCHAR`または`TEXT`型である必要があります。 - ファイルパスは、Machbaseサーバープロセスがアクセスできるパスである必要があります。 - 取り込み中にエラーが発生しても、入力済みの行はロールバックされません。 - 大容量ファイルでは、`machloader`の使用が性能面で有利です。 ## machloaderとの比較 | 項目 | LOAD DATA INFILE | machloader | |------|-----------------|------------| | 並列処理 | 未サポート | サポート | | 使用方法 | SQL文 | CLIユーティリティ | | 用途 | 少量データ、スクリプト内での使用 | 大量の一括取り込み | ## 関連文書 - [SAVE DATA INTO構文](../save-data-into-syntax/) — SELECT結果をファイルに保存 --- title: "VIEW" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/view-syntax/ language: ja kind: page --- # VIEW VIEWは`SELECT`を名前付き論理オブジェクトとして保存し、再利用する機能です。データは別途保存せず、参照時に保存された定義SQLを内部で再展開して実行します。 ## CREATE VIEW ```sql CREATE VIEW view_name AS SELECT ... FROM ...; ``` ```sql CREATE VIEW view_name (col1, col2, ...) AS SELECT ... FROM ...; ``` ```sql CREATE OR REPLACE VIEW view_name AS SELECT ... FROM ...; ``` Standard Editionでは、VIEW定義の`SELECT`の前に非再帰CTEを宣言できます。 ```sql CREATE VIEW view_name AS WITH cte_name AS ( SELECT ... FROM ... ) SELECT ... FROM cte_name; ``` - `CREATE OR REPLACE VIEW`は既存のVIEW定義を置き換えます。対象がVIEW以外のオブジェクトならエラーを返します。 - 列リストを明示すると、その名前がVIEWの正式な列名になります。省略すると別名または元の列名を使用します。 - `view_name`には`db.user.view_name`形式のスキーマ修飾名も使用できます。 ### 基本例 ```sql CREATE LOOKUP TABLE customer ( id INTEGER PRIMARY KEY, name VARCHAR(20), city VARCHAR(20), amount INTEGER ); CREATE VIEW v_customer AS SELECT id, name, city, amount FROM customer; SELECT name, city FROM v_customer WHERE id = 100; ``` ### 列名を明示 ```sql CREATE VIEW v_customer_short (cust_id, cust_name) AS SELECT id, name FROM customer; ``` ### 既存VIEW定義の置き換え ```sql CREATE OR REPLACE VIEW v_customer_amount AS SELECT id, amount * 10 AS amount FROM customer WHERE id <= 10; ``` ### CTEを含むVIEW ```sql CREATE VIEW v_customer_city_summary AS WITH city_summary AS ( SELECT city, COUNT(*) AS customer_count, SUM(amount) AS total_amount FROM customer GROUP BY city ) SELECT city, customer_count, total_amount FROM city_summary; ``` VIEW定義にバインドパラメーター(`?`)は使用できません。実行ごとに変わる条件はVIEWを参照する`SELECT`に記述します。 ## VIEWのユーザーコンテキスト Machbase 8.7.0以降では、VIEW内の`CURRENT_*`と`SESSION_*`関数で定義者と呼び出し元を区別できます。 次の例では`VIEW_OWNER`がVIEWを作成し、`VIEW_CALLER`が付与された権限で参照します。 ```sql CONNECT sys/manager; CREATE USER view_owner IDENTIFIED BY 'VIEW_OWNER'; CREATE USER view_caller IDENTIFIED BY 'VIEW_CALLER'; CONNECT view_owner/VIEW_OWNER; CREATE LOOKUP TABLE user_context_source (id INTEGER PRIMARY KEY); INSERT INTO user_context_source VALUES (1); CREATE VIEW v_user_context AS SELECT CURRENT_USER() AS current_name, SESSION_USER() AS session_name, CURRENT_USER_ID() AS current_id, SESSION_USER_ID() AS session_id FROM user_context_source; CONNECT sys/manager; GRANT SELECT ON view_owner.v_user_context TO view_caller; CONNECT view_caller/VIEW_CALLER; SELECT current_name, session_name, CASE WHEN current_id <> session_id THEN 'DIFF' ELSE 'SAME' END AS id_context FROM view_owner.v_user_context; ``` ```text CURRENT_NAME SESSION_NAME ID_CONTEXT VIEW_OWNER VIEW_CALLER DIFF ``` VIEW内の`CURRENT_*`はVIEW所有者を、`SESSION_*`は接続した呼び出し元を返します。通常のSQLでは 両方が同じユーザーを返します。関数の仕様は[ユーザーコンテキスト関数](../../functions/functions-full/#current-session-user)を参照してください。 ```sql CONNECT view_owner/VIEW_OWNER; DROP VIEW v_user_context; DROP TABLE user_context_source; CONNECT sys/manager; DROP USER view_caller; DROP USER view_owner; ``` ## DROP VIEW ```sql DROP VIEW view_name; DROP VIEW IF EXISTS view_name; ``` - `DROP VIEW IF EXISTS`は対象がなくてもエラーなしで成功します。 - 別のVIEWが対象VIEWを参照している場合は削除を拒否します。 - `DROP TABLE view_name`ではVIEWを削除できません。 ## メタデータの確認 ```sql SHOW VIEWS; DESC view_name; SELECT USER_NAME, DB_NAME, VIEW_NAME, VIEW_SQL FROM M$SYS_VIEWS WHERE VIEW_NAME = 'V_CUSTOMER'; ``` - `M$SYS_TABLES`ではVIEWは`TYPE = 7`で確認できます。 ## 対応するVIEWの形式 | 形式 | サポート | |------|-----------| | 単純な射影と述語 | O | | 式、関数、定数、CASE | O | | JOIN | O | | サブクエリを含む | O | | 入れ子のVIEW | O | | GROUP BY, HAVING | O | | DISTINCT | O | | UNION ALL | O | ## Tag / BINARY列の使用例 TAGテーブルの`BINARY`列を`extract_*()`関数で解析し、論理列として公開するパターンです。 ```sql CREATE TAG TABLE dam ( name VARCHAR(20) PRIMARY KEY, time DATETIME BASETIME, frame BINARY(16) ); CREATE VIEW damdata AS SELECT name, time, extract_bit(frame, 0) AS bit0, extract_ulong(frame, 0, 16) AS u16, extract_float(frame, 0) AS f32, extract_scaled_double(frame, 0, 12, 0, 0.5, 0.5) AS sd12 FROM dam; SELECT name, time, bit0, u16, f32, sd12 FROM damdata WHERE name = 'main' AND time >= TO_DATE('2024-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND time < TO_DATE('2024-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY time; ``` ## 制約 - VIEW定義SQL(`SELECT`本文)は最大256KBをサポートします。 - VIEWはデータを別途保存しないため、性能は元のクエリとオプティマイザーの判断に依存します。 - `DISTINCT`や計算列に対する述語はフルスキャンになる場合があるため、`EXPLAIN`で確認してください。 - 再帰VIEW(自分自身を参照するVIEW)はサポートしません。 ## 関連ドキュメント - [SELECT syntax](../select-syntax/) — FROM句でVIEWを使用 - [WITH / CTE syntax](../cte-syntax/) — CTEを含むVIEW定義 --- title: "INDEX" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/index-syntax/ language: ja kind: page --- # INDEX インデックス構文とテーブルタイプ別のサポート範囲を説明します。 インデックスは検索コストを減らす一方、入力・変更時の維持コストが発生するため、実際の条件と実行計画を確認してから追加してください。 ## CREATE INDEX Machbase 8.7.0からサポートする機能 ```sql create_index_stmt ::= 'CREATE' index_modifier? 'INDEX' [ 'IF NOT EXISTS' ] index_name 'ON' index_target '(' index_column_list ')' [ 'INDEX_TYPE' ( 'LSM' | 'KEYWORD' | 'BITMAP' | 'REDBLACK' | 'TAG' ) ] [ 'TABLESPACE' tablespace_name ] [ index_property_list ] index_modifier ::= 'UNIQUE' | 'PRIMARY KEY' index_target ::= table_name | table_name 'METADATA' index_column_list ::= column_name ( ',' column_name )* | column_name json_path index_property_list ::= ( 'MAX_LEVEL' '=' number | 'PAGE_SIZE' '=' number | 'BITMAP_ENCODE' '=' ( 'EQUAL' | 'RANGE' ) | 'PART_VALUE_COUNT' '=' number ) ( ',' index_property_list )* ``` ### IF NOT EXISTS `IF NOT EXISTS`を指定すると、同じデータベースと所有者に同名のインデックスがある場合、エラーなしで成功し、既存のインデックスを保持します。 - 同名のインデックスがなければ、テーブル、列、インデックスタイプ、プロパティ、権限を通常のCREATE INDEXと同様に検証して作成します。 - 同名のインデックスがあれば、テーブル、列、インデックスタイプ、JSONパス、プロパティを比較・変更しません。 - 重複判定の名前空間は`database + owner + index name`です。別のデータベースや所有者の同名インデックスは別物です。 - オプションを省略したCREATE INDEXは、従来の名前重複エラーを返します。 {{< callout type="warning" >}} `IF NOT EXISTS`はインデックス定義を一致させる機能ではありません。 同名のインデックスがあれば、文の対象テーブルや列が存在しない場合や定義が異なる場合も、no-opとして成功します。 繰り返しデプロイした後は、`SHOW INDEX`またはシステムカタログで実際のテーブル、列、タイプ、プロパティを確認してください。 {{< /callout >}} ```sql CREATE LOG TABLE sensor_log_ifne ( sensor_id INTEGER, value DOUBLE ); CREATE INDEX IF NOT EXISTS sensor_log_ifne_idx ON sensor_log_ifne(sensor_id); -- 同名のインデックスがあるため成功し、既存のSENSOR_IDマッピングを保持します。 CREATE INDEX IF NOT EXISTS sensor_log_ifne_idx ON sensor_log_ifne(value); SHOW INDEX sensor_log_ifne_idx; DROP TABLE sensor_log_ifne; ``` ### 条件付き作成に対応する形式 | 形式 | サポート範囲 | |---|---| | 一般の`CREATE INDEX IF NOT EXISTS` | 対象テーブルタイプがサポートする一般インデックス | | `CREATE UNIQUE INDEX IF NOT EXISTS` | Standard EditionのTRANSACTIONテーブル | | `CREATE PRIMARY KEY INDEX IF NOT EXISTS` | Standard EditionのTRANSACTIONテーブル | | TAG DATAのJSONパス / TAG METADATAインデックス | Standard Edition、Cluster Edition | | 一般構文の`INDEX_TYPE`句 | 対象テーブルタイプとインデックスタイプの既存サポート範囲 | 非推奨の専用構文`CREATE BITMAP INDEX`、`CREATE KEYWORD INDEX`、`CREATE REDBLACK INDEX`では、`IF NOT EXISTS`を使用できません。 一般構文を使用してください。 ```sql CREATE INDEX IF NOT EXISTS idx_message ON app_log(message) INDEX_TYPE KEYWORD; ``` ## テーブルタイプ別のサポート範囲 | テーブルタイプ | インデックス | 主な用途 | |------------|--------|-----------| | LOG | LSM、KEYWORD、BITMAP | 範囲検索、テキスト検索、分析条件 | | TAG | TAG/KVセカンダリ、JSONパス | 値列とJSONメンバーの条件 | | TAG METADATA | 自動列インデックス、JSONパス | タグ属性の条件 | | TRANSACTION | PRIMARY KEY、UNIQUE、一般BTREE | リレーショナルキーと複合条件 | | VOLATILE | REDBLACK | メモリテーブルのキー・条件検索 | | LOOKUP | REDBLACK | メモリテーブルのキー・条件検索 | タイプを省略した場合の内部インデックスは、テーブルタイプによって異なります。 他のテーブルタイプのインデックス名を指定しても、同じ構造が作成されるとは考えないでください。 ## LOGのインデックス ```sql CREATE INDEX idx_ts ON sensor_log (ts); CREATE INDEX idx_msg ON app_log (message) INDEX_TYPE KEYWORD; CREATE INDEX idx_status ON sensor_log (status) INDEX_TYPE BITMAP BITMAP_ENCODE = RANGE; ``` | タイプ | 対象と特性 | |------|-------------| | LSM | LOGの標準の範囲インデックス | | KEYWORD | VARCHAR/TEXTの`SEARCH`、`ESEARCH` | | BITMAP | 繰り返し値の分析。VARCHAR、TEXT、BINARYには使用しない | LSMの`MAX_LEVEL`、`PAGE_SIZE`、BITMAPの`BITMAP_ENCODE`などの属性は、データ分布とクエリ条件に基づいて測定し、決定してください。 ## TAGのインデックス タグ名と時間軸の基本アクセス構造は自動管理されます。 値列を単独条件として頻繁に使用する場合は、TAG/KVセカンダリインデックスを検討します。 ```sql CREATE INDEX idx_value ON sensor_tag (value) INDEX_TYPE TAG; ``` JSON値列は、パスごとのインデックスを作成できます。 ```sql CREATE INDEX idx_sensor ON tag_json (value.sensor.name); CREATE INDEX idx_metric ON tag_json (value->'$.metric'); CREATE INDEX idx_item ON tag_json (value.items[0]."product-id"); ``` TAG METADATAの一般列にはインデックスが自動作成されます。 METADATAのJSON列のパスを追加する場合は、次の形式を使用します。 ```sql CREATE INDEX idx_ship_owner ON ships METADATA (info->'$.owner'); ``` サポート範囲と実行計画の例は、[TAGのインデックスとパフォーマンス](/ja/dbms/tag-table-usage/index-performance/)を参照してください。 ## TRANSACTIONのインデックス TRANSACTIONは、PRIMARY KEY、UNIQUE INDEX、一般の単一・複合インデックスをサポートします。 ```sql CREATE PRIMARY KEY INDEX idx_pk_order ON orders (order_id); CREATE UNIQUE INDEX uidx_account_email ON account (email); CREATE UNIQUE INDEX uidx_tenant_login ON account (tenant_id, login_name); CREATE INDEX idx_category_name ON product (category, product_name); ``` PRIMARY KEYはテーブルごとに1つで、単一列です。 `CREATE UNIQUE INDEX`は複合列をサポートし、NULLを含むキーは他のNULLを含むキーと重複とは判定しません。 詳細な動作は、[TRANSACTIONのインデックスとパフォーマンス](/ja/dbms/rdb-table-usage/index-performance/)を参照してください。 ## VOLATILEとLOOKUPのインデックス VOLATILEとLOOKUPはREDBLACKメモリインデックスを使用します。 ```sql CREATE INDEX idx_status ON device_status (status) INDEX_TYPE REDBLACK; ``` タイプ別の主キーと追加インデックスの設計は、次を参照してください。 - [VOLATILEのインデックスとパフォーマンス](/ja/dbms/volatile-table-usage/index-performance/) - [LOOKUPのインデックスとパフォーマンス](/ja/dbms/lookup-table-usage/index-performance/) ## DROP INDEX ```sql drop_index_stmt ::= 'DROP INDEX' index_name ``` ```sql DROP INDEX idx_status; ``` 対象インデックスを使用するセッションがある場合は、削除に失敗することがあります。 削除前に実行計画と、そのインデックスを使用する本番クエリを確認してください。 ## 関連文書 - [SEARCH / ESEARCH / REGEXP](../search-esearch-regexp-syntax/) - [クエリのパフォーマンスチューニング](/ja/dbms/performance-tuning/performance-query-tuning/) --- title: "RETENTION" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/retention-syntax/ language: ja kind: page --- # RETENTION RETENTIONポリシーは、TAG、KV、LOGテーブルで保持期間を過ぎたデータを定期的に削除します。 TRANSACTION、LOOKUP、VOLATILEには適用できません。 ## RETENTIONポリシーの作成 ```sql create_retention_stmt ::= 'CREATE RETENTION' policy_name 'DURATION' positive_integer ( 'MONTH' | 'DAY' | 'HOUR' | 'MIN' | 'SEC' ) 'INTERVAL' positive_integer ( 'DAY' | 'HOUR' | 'MIN' | 'SEC' ) ``` | パラメーター | 説明 | |----------|------| | `policy_name` | ポリシー名 | | `DURATION duration MONTH\|DAY\|HOUR\|MIN\|SEC` | データ保持期間(`MONTH`は固定30日) | | `INTERVAL interval DAY\|HOUR\|MIN\|SEC` | 削除の実行周期 | ```sql -- 1日保持し、1時間ごとに削除実行 CREATE RETENTION policy_1d_1h DURATION 1 DAY INTERVAL 1 HOUR; -- 30日保持し、1日ごとに削除実行 CREATE RETENTION policy_30d_1d DURATION 30 DAY INTERVAL 1 DAY; -- 3か月保持し、1日ごとに削除実行 CREATE RETENTION policy_3m_1d DURATION 3 MONTH INTERVAL 1 DAY; ``` ## RETENTIONポリシーの削除 ```sql drop_retention_stmt ::= 'DROP RETENTION' policy_name ``` ```sql DROP RETENTION policy_1d_1h; ``` ## テーブルへのRETENTIONポリシーの適用 ```sql alter_table_add_retention_stmt ::= 'ALTER TABLE' table_name 'ADD RETENTION' policy_name ``` ```sql ALTER TABLE sensor_tag ADD RETENTION policy_1d_1h; ``` ## テーブルからのRETENTIONポリシーの解除 ```sql alter_table_drop_retention_stmt ::= 'ALTER TABLE' table_name 'DROP RETENTION' ``` ```sql ALTER TABLE sensor_tag DROP RETENTION; ``` ## RETENTIONポリシー一覧の検索 システムテーブルで、登録されたRETENTIONポリシーと適用状況を検索します。 ```sql -- 全RETENTIONポリシーの検索 SELECT * FROM M$RETENTION; -- テーブル別の適用ジョブと最終削除基準を確認 SELECT USER_NAME, TABLE_NAME, POLICY_NAME, STATE, LAST_DELETED_TIME FROM V$RETENTION_JOB ORDER BY USER_NAME, TABLE_NAME; ``` ## 全体の例 ```sql -- 1. RETENTIONポリシー作成(1日保持、1時間ごとに削除) CREATE RETENTION ret_1d DURATION 1 DAY INTERVAL 1 HOUR; -- 2. TAGテーブル作成 CREATE TAG TABLE sensor_tag ( name VARCHAR(40) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ); -- 3. テーブルにRETENTIONポリシーを適用 ALTER TABLE sensor_tag ADD RETENTION ret_1d; -- 4. ポリシー適用を確認 SELECT * FROM M$RETENTION; -- 5. ポリシーを解除 ALTER TABLE sensor_tag DROP RETENTION; -- 6. ポリシーを削除 DROP RETENTION ret_1d; ``` ## 注意事項 - RETENTIONポリシーは、LOGテーブルとTAGテーブルに適用できます。 - KVテーブルにも適用できます。 - 1つのテーブルには1つのRETENTIONポリシーだけを適用できます。 - `MONTH`はカレンダー月ではなく、固定30日として計算します。カレンダー境界が重要なポリシーは、 `DAY`単位に換算し、実際の削除基準を検証します。 - RETENTIONジョブが削除した行は元に戻せないため、保持期間と実行周期を慎重に設定してください。 `DROP RETENTION`は、すべてのテーブルからポリシーを解除した後で、ポリシーオブジェクトだけを削除します。 - `INTERVAL`は削除ジョブの実行周期であり、実際の削除時刻は多少遅れる場合があります。 - 存在しないポリシー、未サポートのテーブルタイプ、同じテーブルへの重複適用はエラーです。 - 適用中のポリシーオブジェクトは、すべてのテーブルから解除してから削除します。 ## 関連文書 - [Retention Policyの役割](/ja/dbms/core-concepts/features-concepts/#role-retention-policy) — 自動データ削除ポリシーの概念 --- title: "BACKUP / RESTORE / MOUNT" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/backup-restore-mount-syntax/ language: ja kind: page --- # BACKUP / RESTORE / MOUNT Machbaseのバックアップ・リストア・マウント構文は、データを保護し、必要に応じて復旧や過去データの検索を行うために使用します。 > **権限**: 一般ユーザーがバックアップ・マウントを実行するには、別の権限が必要です。 > ```sql > GRANT BACKUP ON DATABASE database_name TO user_name; > GRANT MOUNT ON DATABASE MACHBASEDB TO user_name; > ``` --- ## BACKUP ### 論理データベースのバックアップ 8.7.0 Standard Editionでは、対象カタログを明示する論理バックアップを使用できます。 ```sql backup_logical_database_stmt ::= 'BACKUP DATABASE' database_name [ 'AFTER' 'backup_path_or_lsn' ] 'INTO DISK' '=' 'backup_path' ``` ```sql BACKUP DATABASE factory_a INTO DISK = '/backup/factory_a_20260806'; BACKUP DATABASE factory_a AFTER '/backup/factory_a_20260806' INTO DISK = '/backup/factory_a_inc'; ``` 論理バックアップは、1つのアクティブなデータベースカタログを対象とします。 複数のアクティブデータベースを含むインスタンス全体のイメージは、論理`MOUNT`または`RESTORE`の入力には使用できません。 ### フルバックアップ ```sql backup_database_stmt ::= 'BACKUP DATABASE INTO DISK' '=' 'backup_path' [ 'IMPORT MODE' ] ``` 現在のデータベース全体を指定パスに保存します。サーバーを停止せずに実行するオンラインバックアップです。 ```sql -- 絶対パスでフルバックアップ BACKUP DATABASE INTO DISK = '/backup/machbase_20240101'; -- 相対パス($MACHBASE_HOME/dbs基準) BACKUP DATABASE INTO DISK = 'backup_20240101'; ``` - `backup_path`がすでに存在するとエラーになります。日付などを含む一意の名前を使用してください。 - バックアップ完了まで、コマンドはブロックします。 ### 増分バックアップ ```sql backup_incremental_stmt ::= 'BACKUP DATABASE AFTER' 'backup_path_or_lsn' 'INTO DISK' '=' 'backup_path' ``` 最後のフルバックアップまたは増分バックアップを基準にバックアップします。 テーブルタイプごとの保存方式は区別する必要があります。 TRANSACTIONストレージは増分イメージにもその時点の全体スナップショットとして含まれるため、変更行だけの差分や変更量に相当する容量として計算しないでください。 [TRANSACTIONのバックアップ検証](/ja/dbms/rdb-table-usage/backup-restore-mount/)で、バックアップと現在のデータの検索を比較できます。 ```sql -- フルバックアップ後の変更の増分バックアップ BACKUP DATABASE AFTER '/backup/machbase_20240101' INTO DISK = '/backup/incr_20240102'; ``` ### 期間バックアップ ```sql backup_period_stmt ::= 'BACKUP DATABASE' 'FROM' datetime_expr 'TO' datetime_expr 'INTO DISK' '=' 'backup_path' ``` 指定した時間範囲に該当するデータだけをバックアップします。 ```sql BACKUP DATABASE FROM TO_DATE('2024-01-01','YYYY-MM-DD') TO TO_DATE('2024-02-01','YYYY-MM-DD') INTO DISK = '/backup/period_jan'; ``` ### テーブルのバックアップ ```sql backup_table_stmt ::= 'BACKUP TABLE' table_name 'INTO DISK' '=' 'backup_path' ``` データベース全体ではなく、特定のテーブルだけを選択してバックアップします。 ```sql BACKUP TABLE sensor_log INTO DISK = '/backup/sensor_log_20240101'; ``` --- ## RESTORE 従来の`machadmin -r`は、サーバーを停止するオフラインのインスタンス復旧です。 8.7.0 Standard Editionでは、論理データベースを新しいカタログに復元するか、READ ONLYの対象を置換する、 オンラインの`RESTORE DATABASE`もサポートします。 ```sql restore_database_stmt ::= 'RESTORE DATABASE' database_name 'FROM DISK' '=' 'backup_path' [ 'REMAP OWNER' old_owner 'TO' new_owner ] [ 'REPLACE' ] ``` ```sql RESTORE DATABASE factory_a_copy FROM DISK = '/backup/factory_a_20260806' REMAP OWNER APP_A TO APP_ARCHIVE; RESTORE DATABASE factory_a FROM DISK = '/backup/factory_a_20260806' REPLACE; ``` `RESTORE DATABASE`はSYS専用です。 `REPLACE`の対象はREAD ONLYで参照がないことが必要です。 リストア後にデータベース・テーブル権限は自動継承されないため、再付与する必要があります。 バックアップイメージの未サポートオブジェクトや所有者の競合によって、リストア全体が失敗する場合があります。 ### 既存インスタンスのオフライン復旧(`machadmin -r`) 復旧前にバックアップSQLファイルを準備・検証してから実行します。 ```sql -- /secure/path/pre_restore_backup.sql BACKUP DATABASE INTO DISK = '/backup/before_restore'; ``` ```bash # 1. 復旧前に現在のデータをバックアップ machsql -s 127.0.0.1 -P 5656 -u SYS \ -f /secure/path/pre_restore_backup.sql # 2. サーバー終了 machadmin -s # 3. 現在のデータベースを削除 machadmin -d # 4. バックアップデータから復元 machadmin -r /backup/machbase_20240101 # 5. サーバー起動 machadmin -u ``` `machadmin -d`は現在のデータベースを破棄します。 復旧対象、バックアップ、元に戻す計画を確認し、明示的な承認を得た後だけ実行してください。 リストアすると、現在のデータベースはバックアップ時点の状態に完全に置き換わります。 ### 増分バックアップのリストア 復元する最後の増分バックアップのパスを一度指定します。 増分バックアップはチェーン情報を含むため、フルバックアップから繰り返し適用する必要はありません。 ```bash machadmin -s machadmin -d machadmin -r /backup/incr_20240103 machadmin -u ``` ### machadminの主なオプション | オプション | 説明 | |------|------| | `-s` (`--shutdown`) | サーバーの正常終了 | | `-k` (`--kill`) | サーバーの強制終了 | | `-u` (`--startup`) | サーバーの起動 | | `-d` (`--destroydb`) | 現在のデータベースの削除 | | `-r path` (`--restore`) | 指定したバックアップパスから復元 | --- ## MOUNT DATABASE ```sql mount_database_stmt ::= 'MOUNT DATABASE' 'backup_database_path' 'TO' mount_name ``` サーバーを停止したりアクティブなデータベースを置換したりせずに、単一カタログのバックアップイメージを現在のサーバーへマウントデータベースとして接続します。 マウントデータベースは常にREAD ONLYであり、`USE`で現在のデータベースにはできません。 - `backup_database_path`: DISK方式で作成したバックアップディレクトリのパス - `mount_name`: マウントデータベースへのアクセスに使用するデータベース別名 ```sql -- 絶対パスでマウント MOUNT DATABASE '/backup/machbase_20240101' TO backup_db; -- 相対パス($MACHBASE_HOME/dbs基準) MOUNT DATABASE 'machbase_20240101' TO backup_db; ``` ### マウントしたデータベースの検索 マウントしたデータベースのテーブルには、`mount_name.user_name.table_name`形式でアクセスします。 検索には、マウントデータベースの`USAGE`と対象テーブルの`SELECT`が両方必要です。 ```sql -- マウントしたデータベースのテーブルを検索 SELECT * FROM backup_db.sys.sensor_log WHERE _arrival_time > TO_DATE('2024-01-01','YYYY-MM-DD'); -- 現在のデータベースとマウントデータベースを結合して検索(JOIN) SELECT a.name, a.value AS current_val, b.value AS backup_val FROM sensor_log a JOIN backup_db.sys.sensor_log b ON a.name = b.name; ``` --- ## UMOUNT DATABASE ```sql umount_database_stmt ::= 'UMOUNT DATABASE' mount_name ``` マウントしたデータベースを解除します。 ```sql UMOUNT DATABASE backup_db; ``` マウントデータベースを参照する開いたカーソルや実行中のクエリがある場合、アンマウントは失敗します。 該当するセッションを終了してから再実行してください。 --- ## 制約と注意事項 | 項目 | 説明 | |------|------| | マウントデータベースへの書き込み | 不可(読み取り専用) | | IBFILE方式バックアップのマウント | 不可(DISK方式だけマウント可能) | | バージョン互換性 | バックアップデータベースと現在のサーバーのメタバージョンに互換性が必要 | | TAGテーブルの期間復元 | 未サポート(フルバックアップまたは増分バックアップからのみ復元可能) | | Cluster Edition | 複数データベースとMOUNT/UMOUNTは未サポート | --- ## 関連文書 - [バックアップ・リストア・マウント運用ガイド](/ja/dbms/operations-configuration-recovery/backup-restore-mount/) - 詳細な運用手順と自動化例 - [GRANT/REVOKE](../user-auth-syntax/#grant-revoke) - バックアップ・マウント権限の付与 --- title: "ROLLUP" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/rollup-syntax/ language: ja kind: page --- # ROLLUP ROLLUPは時間軸TAGの繰り返し集計を保存・参照する機能です。通常・条件付き・拡張ROLLUPは 公開の`rollup()`関数で参照し、Customはユーザーの出力先TAGを再集計して参照します。 ## 作成 次は構文の表記です。角括弧や波括弧をそのまま実行しないでください。 ```text CREATE ROLLUP [IF NOT EXISTS] name ON source_tag [(column_name | json_path_expression)] INTERVAL n { SEC | MIN | HOUR } [WAKEUP INTERVAL m { SEC | MIN | HOUR }] [EXTENSION] [WHERE predicate]; CREATE ROLLUP [IF NOT EXISTS] name FROM source_rollup INTERVAL n { SEC | MIN | HOUR } [WAKEUP INTERVAL m { SEC | MIN | HOUR }] [EXTENSION] [WHERE predicate]; CREATE ROLLUP [IF NOT EXISTS] name INTO (destination_tag) AS (SELECT ...) INTERVAL n { SEC | MIN | HOUR } [WAKEUP INTERVAL m { SEC | MIN | HOUR }]; ``` - EXTENSIONはキーワードのみを記述し、extension_nameは付けません。 - CREATEの時間単位はSEC/MIN/HOURです。DAYなどのクエリ単位とは区別します。 - 通常の数値列はSUMMARIZEDなしで明示できます。JSONパス集計とドキュメント全体の集計は異なり、ドキュメント全体とWITH ROLLUPによる自動作成にはSUMMARIZED条件があります。 - FROMの間隔はソースより大きな整数倍であり、拡張属性と集計モードが一致する必要があります。 - WAKEUPは正数で、集計間隔以下であり、その間隔を割り切れる必要があります。 - CustomはStandard専用です。ソースTAGが1つと事前作成済みの出力先TAGが必要です。WHEREはSELECT内に記述し、BASETIMEの直接条件・JOIN・FROMサブクエリは許可しません。 - IF NOT EXISTSは既存名の場合に作成を省略する機能であり、定義の変更、比較、一致処理は行いません。構文とソースの検証をすべて省略するオプションでもありません。 ## 削除 ```sql DROP ROLLUP rollup_name; ``` 参照元となる上位ROLLUPから削除します。Custom出力先TAGは、関連ジョブが残っているとDROPが拒否されます。 元のTAGのCASCADEは関連ROLLUPの削除範囲を確認してから使用し、ユーザーのCustom出力先テーブルは 別のライフサイクルで管理します。 ## 制御 ```sql ALTER ROLLUP rollup_name STOP; ALTER ROLLUP rollup_name START; ALTER ROLLUP rollup_name WAKEUP; ALTER ROLLUP rollup_name FORCE; ALTER ROLLUP rollup_name SET WAKEUP INTERVAL 10 SEC; ``` これらのコマンドは、既存ジョブと有効な間隔条件を前提とします。作成時に自動開始し、すでに開始・停止済みの 状態を繰り返し指定するとエラーになる場合があります。WAKEUPは完了を待たず、FORCEは対象がソースの 処理範囲に追いつくまで待機します。過去のソースの補正では、[REBUILD固有のサポート範囲](../rollup-rebuild-syntax/)を確認します。 ## クエリと候補の選択 ```text rollup(time_unit, period, basetime_column [, origin]) ``` 戻り値の型はDATETIMEです。periodは正の整数リテラルです。通常のDATE_TRUNC + GROUP BYクエリは、 ROLLUPが存在するだけでは自動的に切り替わりません。ROLLUPの参照には`rollup()`を明示し、適用可能な 候補がなければ別途ソースデータのクエリを使用します。 自動選択では、同じ列・パス・モードで条件なしの候補を先に探し、使用可能な最大の間隔を選びます。 同じ間隔では登録順序が影響します。通常/拡張だけで優先順位を断定しないでください。 特定のデータ集合に固定するにはROLLUP_TABLEヒントを使用します。 SEC/MINの候補間隔はperiod秒/分を基準に確認します。HOUR・DAY・WEEK・MONTH・YEARは候補選択時に period時間を基準に確認します。これは結果バケットの暦計算とは別の規則です。 月・年のoriginでは、月の1日であるという条件を確認してください。 SELECTでnameを返すタグ別集計は、GROUP BYにもnameを含めます。時間範囲・origin・NULL処理・候補条件を そろえてから元データの結果と比較します。通常の数値ROLLUPはMIN/MAX/SUM/COUNT/AVG/SUMSQ、 拡張ROLLUPはFIRST/LASTもサポートします。元データに対するFIRST/LASTの使用と保存ROLLUPの拡張要件は 区別してください。JSONドキュメント全体のCOUNTとパス別の件数は別の規則です。 実行可能な作成・参照・エラーの例は、[第6章 ROLLUPの利用](/ja/dbms/tag-rollup-usage/)と [クエリ構文](/ja/dbms/tag-rollup-usage/query-syntax-rollup/)を参照してください。 --- title: "ROLLUP_REBUILD" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/rollup-rebuild-syntax/ language: ja kind: page --- # ROLLUP_REBUILD ROLLUP_REBUILDは、対応するTAG集計の過去のバケットを再計算するStandard Editionのプロシージャーです。 Cluster Editionではサポートしません。 ## 構文と引数 ```text EXEC ROLLUP_REBUILD(source_tag, tag_name, begin_time, end_time); ``` | 引数 | 現在の入力形式 | |---|---| | source_tag | ソースTAGの識別子。必要に応じて所有者で修飾 | | tag_name | 再構築する1つのタグ名文字列 | | begin_time | 時刻文字列、または定数文字列引数を持つTO_DATE | | end_time | 同じ形式の終了時刻。begin_time以上 | 現在の時刻引数処理は、一般的なDATETIME式の評価ではありません。NOW、NOW-1h、列・バインドパラメーターなどは 例として使用しないでください。相対範囲が必要な場合は運用ツールで時刻を確定し、対応する定数形式で渡します。 日付文字列、書式、タイムゾーンを明確にしてください。 ## 時間範囲 開始・終了が属するバケットを含め、バケット全体を再計算します。1分単位の場合、00:00:30~00:01:00は [00:00:00, 00:02:00)の範囲です。開始=終了でもその時刻のバケットを処理し、開始>終了はエラーです。 HOUR段階では、時間バケット全体へさらに範囲が広がる場合があります。 ソースのWHEREの半開区間の終端をそのまま渡すと、次のバケットも含まれる場合があります。 補正した実際の時刻と各集計のバケット境界を基準に影響範囲を決定します。 ## 対象と制約 - 基本演習の対象は、完全な自動SEC→MIN→HOUR階層です。 - 任意名の手動の通常ROLLUPや、SECがない自動階層も同じ経路で処理できると仮定しないでください。 - Customツリーは別経路で、現在の時間境界生成は1 SEC・1 MIN・1 HOURの間隔を対象とします。10 MINなど作成可能な他の間隔と、再構築可能な範囲は区別してください。 - Custom SELECTの時間バケットとoriginは、再構築の境界に一致する必要があります。 - 有効な対象がある場合、存在しないタグでは何も変更しない場合があります。 - 元データが失われていれば、削除前の統計値を復元することはできません。 ## 実行例 次は、ch6_rebuild演習オブジェクトが準備済みの場合の呼び出しです。 ```sql EXEC ROLLUP_REBUILD(ch6_rebuild, 'S1', TO_DATE('2026-01-01 00:00:30', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2026-01-01 00:01:00', 'YYYY-MM-DD HH24:MI:SS')); ``` 準備SQL、元データの訂正、通常・Custom結果の比較、後処理は、 [6.10 完全な演習](/ja/dbms/tag-rollup-usage/rollup-rebuild/)を参照してください。 ## ジョブ状態と失敗 関連する集計ジョブは停止・再計算・再起動の段階を経ます。再構築中に通常の集計がそのまま続く保証はありません。 ソースの安定した参照のための処理と、データ再生成の影響を隔離環境で確認してください。 失敗時には一部の結果がすでに変わっている場合があります。全体のロールバックや元の停止状態への自動復元を 前提にせず、元データ・対象バケット・V$ROLLUP・gap・最初のエラーを確認します。 非対応のジョブを除外するか手順を修正するまでは、同じコマンドを繰り返さないでください。 [作成・参照構文](../rollup-syntax/)、[サポート範囲](/ja/dbms/reference/support-scope-constraints/rollup/)、 [トラブルシューティング](/ja/dbms/troubleshooting/rollup/)も確認してください。 --- title: "USER/AUTH" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/user-auth-syntax/ language: ja kind: page --- # USER/AUTH ユーザーの作成・削除・パスワード変更、権限の付与・取り消し、公開鍵を使用するAUTH KEYの管理構文です。 --- ## CREATE USER {#create-drop-alter-user} ```sql create_user_stmt ::= 'CREATE USER' user_name 'IDENTIFIED BY' password [ 'PASSWORD POLICY' ( 'NONE' | 'LOW' | 'HIGH' ) ] [ 'WITH AUTH KEY' '(' auth_key_spec ')' ] auth_key_spec ::= "key='" pem_public_key "'," "valid_before='" YYYY-MM-DD "'," "comment='" text "'" ``` ユーザー名は保存時に大文字へ変換します。 ```sql -- 基本的なユーザー作成 CREATE USER app_user IDENTIFIED BY 'App#1234'; -- パスワードポリシーの指定 CREATE USER ops_user IDENTIFIED BY 'Ops@Strong1' PASSWORD POLICY HIGH; -- AUTH KEYとともに作成(公開鍵認証) CREATE USER app_user IDENTIFIED BY 'App#1234' WITH AUTH KEY ( key='-----BEGIN PUBLIC KEY-----\nMFkw...(省略)...==\n-----END PUBLIC KEY-----\n', valid_before='2047-12-31', comment='initial key' ); ``` ### パスワードポリシー | ポリシー | 説明 | |------|------| | `NONE` | 強度の制約なし。有効期限なし | | `LOW` | 10文字以上、大文字・小文字・特殊文字を含む。連続する数字・キーボード配列のパターンは禁止 | | `HIGH` | LOWの規則 + 直近24個のパスワードの再利用禁止 + 90日で自動失効 | --- ## DROP USER ```sql drop_user_stmt ::= 'DROP USER' user_name ``` `SYS`ユーザーは削除できません。対象ユーザーが作成したテーブルが残っている場合はエラーになります。 別の管理者セッションがユーザーを削除しても、既存のアクティブセッションは即座には終了しません。新規接続は 失敗し、既存セッションはログイン時のユーザー名とIDを保持します。運用手順は[アカウント管理](../../../../security-access-control/account/#drop-user-active-session)を、 確認関数は[ユーザーコンテキスト関数](../../functions/functions-full/#current-session-user)を参照してください。 ```sql DROP USER old_user; ``` --- ## ALTER USER ```sql -- パスワードの変更 alter_user_pwd_stmt ::= 'ALTER USER' user_name 'IDENTIFIED BY' new_password [ 'PASSWORD POLICY' ( 'NONE' | 'LOW' | 'HIGH' ) ] ``` ポリシーのみを変更する構文は許可しません。ポリシーを変更する場合は、必ず新しいパスワードも指定してください。 ```sql -- パスワードの変更 ALTER USER app_user IDENTIFIED BY 'NewPass#456'; -- パスワードとポリシーを同時変更 ALTER USER app_user IDENTIFIED BY 'NewPass#456' PASSWORD POLICY HIGH; ``` --- ## CONNECT ```sql user_connect_stmt ::= 'CONNECT' user_name '/' password ``` アプリケーションを終了せず、別のユーザーで再接続します。 ```sql CONNECT app_user/App#1234; ``` --- ## GRANT / REVOKE {#grant-revoke} ```sql grant_stmt ::= 'GRANT' priv_list 'ON' object_ref 'TO' user_name revoke_stmt ::= 'REVOKE' priv_list 'ON' object_ref 'FROM' user_name priv_list ::= priv_value ( ',' priv_value )* object_ref ::= 'DATABASE' database_name | 'TABLE' ['database_name.'] owner_name '.' table_name | ['database_name.'] owner_name '.' table_name ``` ### テーブル権限 ```sql -- テーブルのDML権限 GRANT SELECT ON sensor_log TO reader; GRANT SELECT, INSERT ON sys.sensor_log TO writer; GRANT ALL ON sys.sensor_log TO app_user; -- 権限の取り消し REVOKE INSERT ON sys.sensor_log FROM writer; REVOKE ALL ON sys.sensor_log FROM app_user; ``` テーブル権限の種類: `SELECT`, `INSERT`, `DELETE`, `UPDATE`, `ALL` ### データベース権限(Machbase 8.5以降) ```sql -- DDL権限(CREATE + DROP) GRANT DDL ON DATABASE factory_a TO deploy_user; -- 個別のDDL権限 GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT CREATE ON DATABASE factory_a TO create_user; GRANT DROP ON DATABASE factory_a TO drop_user; GRANT ALTER ON DATABASE factory_a TO ops_user; -- 運用権限 GRANT BACKUP ON DATABASE factory_a TO backup_user; GRANT MOUNT ON DATABASE MACHBASEDB TO mount_user; GRANT USAGE ON DATABASE factory_a_backup TO report_user; -- すべてのデータベース権限 GRANT ALL ON DATABASE factory_a TO admin_user; -- 権限の取り消し REVOKE BACKUP ON DATABASE factory_a FROM backup_user; ``` データベース権限の種類: `CONNECT`, `CREATE`, `DROP`, `ALTER`, `BACKUP`, `MOUNT`, `USAGE`, `DDL`(`CREATE+DROP`), `ALL`(`CONNECT+CREATE+DROP+ALTER+BACKUP`) ### データベース権限が必要な操作 | 操作 | 必要な権限 | |------|------------| | CREATE/DROP TABLE, VIEW, INDEX, ROLLUP, TABLESPACE, RETENTION | `CREATE`、`DROP`、または`DDL` | | ALTER SYSTEM | `ALTER` | | BACKUP DATABASE | `BACKUP` | | MOUNT/UMOUNT DATABASE | `MOUNT` | ### ユーザー作成時のデフォルト権限 新規ユーザーはデフォルトで`SELECT`、`INSERT`、`DELETE`、`UPDATE`、`CREATE`、`DROP`権限を持ちます。 `ALTER`、`MOUNT`、`BACKUP`は明示的に付与してください。 --- ## AUTH KEY管理 {#auth-key} AUTH KEYは、パスワードの代わりに公開鍵によるチャレンジ認証を使用するため、Machbaseに登録する公開鍵です。 ### 対応するアルゴリズム | アルゴリズム | 対応するパラメーター | 署名方式 | |---------|-------------|----------| | ECDSA | P-256, P-384, P-521 | ECDSA | | RSA | 2048, 3072, 4096 bits | RSA_PKCS1_V15, RSA_PSS | ### 鍵ファイルの生成(openssl) ```bash # ECDSA P-256鍵の生成 openssl ecparam -name prime256v1 -genkey -noout -out app_user.key openssl ec -in app_user.key -pubout -out app_user.pub chmod 600 app_user.key # RSA 2048-bit鍵の生成 openssl genrsa -out app_user_rsa.key 2048 openssl rsa -in app_user_rsa.key -pubout -out app_user_rsa.pub chmod 600 app_user_rsa.key # PEMをSQLインライン形式へ変換(改行を\nにする) awk '{printf "%s\\n", $0}' app_user.pub ``` ### AUTH KEYの追加 ```sql alter_user_add_auth_key_stmt ::= 'ALTER USER' user_name 'ADD AUTH KEY' '(' auth_key_spec ')' auth_key_spec ::= "key='" pem_public_key "'," "valid_before='" YYYY-MM-DD "'," "comment='" text "'" ``` ```sql ALTER USER app_user ADD AUTH KEY ( key='-----BEGIN PUBLIC KEY-----\nMFkw...(省略)...==\n-----END PUBLIC KEY-----\n', valid_before='2047-12-31', comment='primary key' ); ``` 追加した鍵は直ちに有効な状態(`ACTIVATED=1`)で登録されます。 ### AUTH KEYの有効化 / 無効化 ```sql alter_user_activate_key_stmt ::= 'ALTER USER' user_name 'ACTIVATE AUTH KEY ID' key_id alter_user_deactivate_key_stmt ::= 'ALTER USER' user_name 'DEACTIVATE AUTH KEY ID' key_id ``` ```sql ALTER USER app_user DEACTIVATE AUTH KEY ID 3; ALTER USER app_user ACTIVATE AUTH KEY ID 3; ``` ### AUTH KEYの有効期間変更 ```sql alter_user_alter_key_stmt ::= 'ALTER USER' user_name 'ALTER AUTH KEY ID' key_id "VALID_BEFORE='" YYYY-MM-DD "'" ``` ```sql ALTER USER app_user ALTER AUTH KEY ID 3 VALID_BEFORE='2048-06-30'; ``` ### AUTH KEYの削除 ```sql alter_user_drop_key_stmt ::= 'ALTER USER' user_name 'DROP AUTH KEY ID' key_id ``` ```sql ALTER USER app_user DROP AUTH KEY ID 3; ``` ### AUTH KEYの参照 ```sql SELECT key_id, user_name, key_algo, key_param, activated, valid_before, comment FROM V$USER_AUTH_KEYS WHERE user_name = 'APP_USER' ORDER BY key_id; ``` `V$USER_AUTH_KEYS`の主な列: `KEY_ID`, `USER_NAME`, `KEY_ALGO`, `KEY_PARAM`, `ACTIVATED`, `VALID_AFTER`, `VALID_BEFORE`, `COMMENT`, `PUBKEY` --- ## 関連ドキュメント - [ユーザー管理ガイド](../../../../operations-configuration-recovery/) - ユーザー運用の手順と例 - [システム/セッション管理構文](../system-session-alter-syntax/) - ALTER SYSTEM, ALTER SESSION --- title: "SYSTEM/SESSION/ALTER SYSTEM" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/system-session-alter-syntax/ language: ja kind: page --- # SYSTEM/SESSION/ALTER SYSTEM `ALTER SYSTEM`はサーバー全体のリソースを管理する構文です。`ALTER SESSION`は現在のセッションだけに適用するパラメーターを設定します。 > **権限**: `ALTER SYSTEM`は`SYS`アカウント、または`GRANT ALTER ON DATABASE database_name TO user_name;`で権限を付与されたユーザーのみ実行できます。 --- ## ALTER SYSTEM {#alter-system} ### コマンド一覧 | コマンド | 説明 | |--------|------| | `KILL SESSION n` | 指定セッションを強制終了 | | `CANCEL SESSION n` | セッションを維持し、実行中のクエリだけをキャンセル | | `CHECKPOINT` | メモリバッファーを直ちにディスクへ同期 | | `FREEZE` | 全DMLを一時停止(バックアップ準備用) | | `UNFREEZE` | FREEZEで停止したDMLを再開 | | `FLUSH AGER` | Agerスレッドを直ちに実行して期限切れデータを整理 | | `FLUSH SYS_STAT` | クエリオプティマイザー用のシステム統計を更新 | | `FLUSH PVO_CACHE` | PVO Statementキャッシュを初期化 | | `FLUSH PAGE_CACHE` | OSページキャッシュを強制解放 | | `FLUSH TAG_CACHE` | TAGテーブルのメタデータキャッシュを初期化 | | `INSTALL LICENSE` | デフォルトパスのライセンスファイルをインストール | | `INSTALL LICENSE = 'path'` | 指定パスのライセンスファイルをインストール | | `CHECK DISK_USAGE` | LOGテーブルのディスク使用量を再計算 | | `SET property = value` | システムプロパティの動的変更 | --- ### KILL SESSION / CANCEL SESSION ```sql alter_system_kill_session_stmt ::= 'ALTER SYSTEM KILL SESSION' session_id alter_system_cancel_session_stmt ::= 'ALTER SYSTEM CANCEL SESSION' session_id ``` ```sql -- 現在のセッション一覧を確認 SELECT id, user_id, client_type FROM v$session; -- セッションを強制終了(切断、トランザクションをロールバック) ALTER SYSTEM KILL SESSION 12; -- 実行中のクエリだけをキャンセル(接続を維持) ALTER SYSTEM CANCEL SESSION 6; ``` - `KILL SESSION`: SYSユーザーのみ実行可能。対象セッションを即座に終了します。 - `CANCEL SESSION`: 同じユーザーまたはSYSのみ実行可能。セッションを維持し、現在実行中のSQLだけを中止します。 --- ### CHECKPOINT ```sql alter_system_checkpoint_stmt ::= 'ALTER SYSTEM CHECKPOINT' ``` メモリにバッファーされたデータを直ちにディスクへ同期します。 ```sql ALTER SYSTEM CHECKPOINT; ``` --- ### FREEZE / UNFREEZE ```sql alter_system_freeze_stmt ::= 'ALTER SYSTEM FREEZE' alter_system_unfreeze_stmt ::= 'ALTER SYSTEM UNFREEZE' ``` バックアップ準備など整合性が必要な場合、すべてのDMLを一時停止します。 ```sql ALTER SYSTEM FREEZE; -- (バックアップまたは点検を実行) ALTER SYSTEM UNFREEZE; ``` --- ### FLUSH ```sql alter_system_flush_stmt ::= 'ALTER SYSTEM FLUSH' ( 'AGER' | 'SYS_STAT' | 'PVO_CACHE' | 'PAGE_CACHE' | 'TAG_CACHE' ) ``` ```sql -- Agerを即時実行(期限切れデータを整理) ALTER SYSTEM FLUSH AGER; -- クエリオプティマイザーの統計を更新 ALTER SYSTEM FLUSH SYS_STAT; -- PVO Statementキャッシュを初期化 ALTER SYSTEM FLUSH PVO_CACHE; -- OSページキャッシュを強制解放 ALTER SYSTEM FLUSH PAGE_CACHE; -- TAGメタデータキャッシュを初期化 ALTER SYSTEM FLUSH TAG_CACHE; ``` --- ### INSTALL LICENSE ```sql -- デフォルトパス ($MACHBASE_HOME/conf/license.dat) alter_system_install_license_stmt ::= 'ALTER SYSTEM INSTALL LICENSE' -- 指定パス alter_system_install_license_path_stmt ::= 'ALTER SYSTEM INSTALL LICENSE' '=' "'" path "'" ``` ```sql -- デフォルトパスからインストール ALTER SYSTEM INSTALL LICENSE; -- 指定パスからインストール ALTER SYSTEM INSTALL LICENSE = '/tmp/new_license.dat'; ``` --- ### CHECK DISK_USAGE ```sql alter_system_check_disk_stmt ::= 'ALTER SYSTEM CHECK DISK_USAGE' ``` `V$STORAGE`の`DC_TABLE_FILE_SIZE`値をファイルシステムから再計算します。プロセス障害や停電後に使用量が不正確な場合に使用します。 ```sql ALTER SYSTEM CHECK DISK_USAGE; ``` --- ### SET (システムプロパティの動的変更) ```sql alter_system_set_stmt ::= 'ALTER SYSTEM SET' property_name '=' value_expr value_expr ::= value | property_name '|' number -- ビットOR(フラグ追加) | property_name '&' '~' number -- ビットAND NOT(フラグ削除) ``` 変更できるプロパティ一覧: | プロパティ | 説明 | |------|------| | `QUERY_PARALLEL_FACTOR` | クエリの並列処理スレッド数 | | `DEFAULT_DATE_FORMAT` | デフォルトの日付形式(例: `'YYYY-MM-DD HH24:MI:SS'`) | | `TRACE_LOG_LEVEL` | トレースログレベル(ビットフラグ) | | `DISK_COLUMNAR_PAGE_CACHE_MAX_SIZE` | ディスク列指向ページキャッシュの最大サイズ | | `MAX_SESSION_COUNT` | 最大セッション数 | | `SESSION_IDLE_TIMEOUT_SEC` | セッションのアイドルタイムアウト(秒) | | `PROCESS_MAX_SIZE` | プロセスの最大メモリサイズ | | `TAG_CACHE_MAX_MEMORY_SIZE` | TAGキャッシュの最大メモリサイズ | | `PVO_CACHE_ENABLE` | PVOキャッシュの有効化(0/1) | | `PVO_CACHE_MAX_MEMORY_SIZE` | PVOキャッシュの最大メモリサイズ | ```sql -- 値を直接設定 ALTER SYSTEM SET TRACE_LOG_LEVEL = 3; ALTER SYSTEM SET DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; -- 変更前の現在値を確認 SELECT NAME, VALUE, MIN, MAX FROM V$PROPERTY WHERE NAME = 'MAX_SESSION_COUNT'; -- ビットフラグの追加(OR) ALTER SYSTEM SET TRACE_LOG_LEVEL = TRACE_LOG_LEVEL | 0x00000004; -- ビットフラグの削除(AND NOT) ALTER SYSTEM SET TRACE_LOG_LEVEL = TRACE_LOG_LEVEL & ~0x00000001; -- 16進数で設定 ALTER SYSTEM SET TRACE_LOG_LEVEL = 0x00000003; ``` --- ## ALTER SESSION {#alter-session} セッション単位のパラメーターを変更します。 ```sql alter_session_stmt ::= 'ALTER SESSION SET' session_property_name '=' value ``` ### SET SQL_LOGGING ```sql ALTER SESSION SET SQL_LOGGING = flag -- flag: ビットORの組み合わせ -- 0x1: 解析・検証・最適化段階のログ -- 0x2: DDL実行結果のログ ``` ```sql ALTER SESSION SET SQL_LOGGING = 3; -- 解析ログ + DDLログ ALTER SESSION SET SQL_LOGGING = 0; -- ログ記録を無効化 ``` ### SET DEFAULT_DATE_FORMAT ```sql ALTER SESSION SET DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; ALTER SESSION SET DEFAULT_DATE_FORMAT = 'YYYYMMDD'; ``` ### SET SHOW_HIDDEN_COLS `SELECT *`で隠し列(`_arrival_time`)も表示するか設定します。 ```sql ALTER SESSION SET SHOW_HIDDEN_COLS = 1; -- 隠し列を表示 ALTER SESSION SET SHOW_HIDDEN_COLS = 0; -- 隠し列を非表示(デフォルト) ``` ### SET FEEDBACK_APPEND_ERROR Append APIのエラーメッセージをクライアントへ送信するか設定します。 ```sql ALTER SESSION SET FEEDBACK_APPEND_ERROR = 1; -- エラーメッセージを送信(サーバーのデフォルト) ALTER SESSION SET FEEDBACK_APPEND_ERROR = 0; -- エラーメッセージを送信しない ``` ### SET MAX_QPX_MEM 単一SQLのGROUP BY、DISTINCT、ORDER BYで使用できる最大メモリ(バイト)です。 ```sql ALTER SESSION SET MAX_QPX_MEM = 1073741824; -- 1GB ``` ### SET DDL_LOCK_TIMEOUT Standard Editionで競合するDDLロックの待機時間を秒単位で指定します。デフォルトは`0`、範囲は`0`~`1000000`です。 `0`の場合は待機せず、直ちに`ERR-02031: Resource busy ()`を返します。 ```sql ALTER SESSION SET DDL_LOCK_TIMEOUT = 10; -- 最大10秒待機 ``` 実行中のDDLの待機時間は変わらず、新しい値は次のDDLから適用します。セッションごとの現在値は `V$SESSION.DDL_LOCK_TIMEOUT`で確認します。 ```sql SELECT id, user_name, ddl_lock_timeout FROM v$session WHERE closed = 0 ORDER BY id; ``` 競合範囲とエラー処理は[DDLの同時実行とロック](../ddl-syntax/#ddl-concurrency)を参照してください。 ### SET SESSION_IDLE_TIMEOUT_SEC アイドル状態のセッションで接続を維持する最大時間(秒)です。 ```sql ALTER SESSION SET SESSION_IDLE_TIMEOUT_SEC = 300; -- 5分 ``` ### SET QUERY_TIMEOUT クエリ実行の最大待機時間(秒)です。超過するとクエリを自動中止します。 ```sql ALTER SESSION SET QUERY_TIMEOUT = 60; -- 60秒 ``` --- ## 関連ビュー | ビュー | 説明 | |----|------| | `v$session` | 現在の接続セッション一覧とセッション別パラメーター | | `v$storage` | ディスク使用量情報(`DC_TABLE_FILE_SIZE`など) | | `v$license_info` | インストール済みライセンス情報 | | `v$property` | システムプロパティと現在値 | ```sql -- セッション一覧を参照 SELECT id, user_id, client_type, login_time FROM v$session; -- システムプロパティを確認 SELECT name, value FROM v$property WHERE name = 'TRACE_LOG_LEVEL'; ``` --- ## 関連ドキュメント - [ALTER SYSTEM運用ガイド](../../../../operations-configuration-recovery/alter-system/) - 詳細な運用手順とコマンド別の動作説明 - [GRANT/REVOKE](../user-auth-syntax/#grant-revoke) - ALTER SYSTEM権限の付与 --- title: "DATABASE" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/database-syntax/ language: ja kind: page --- # DATABASE Machbase 8.7.0 Standard Editionの論理データベースのライフサイクルとセッション選択の構文です。 データベース名はカタログ名であり、サーバーインスタンスの物理ストレージを管理する`machadmin -c`、`machadmin -d`とは区別します。 ## CREATE DATABASE ```sql create_database_stmt ::= 'CREATE DATABASE' ['IF NOT EXISTS'] database_name ``` `CREATE DATABASE`は、現在のMachbaseインスタンスにアクティブな論理データベースを作成します。 新しいデータベースのデフォルトのアクセスモードは`READ WRITE`です。 ユーザーと認証情報はインスタンス全体で共有され、テーブル・ビュー・インデックスとオブジェクト権限はデータベースごとに管理されます。 ```sql CREATE DATABASE factory_a; CREATE DATABASE IF NOT EXISTS factory_b; ``` ## ALTER DATABASE ```sql alter_database_stmt ::= 'ALTER DATABASE' database_name ( 'READ ONLY' | 'READ WRITE' ) ``` `READ ONLY`データベースは検索できますが、書き込みDML、Append、変更DDLは実行できません。 実行中の書き込みを終了してからモードを変更してください。 ```sql ALTER DATABASE factory_a READ ONLY; ALTER DATABASE factory_a READ WRITE; ``` ## DROP DATABASE ```sql drop_database_stmt ::= 'DROP DATABASE' ['IF EXISTS'] database_name [ 'RESTRICT' | 'CASCADE' | 'FORCE' | 'CASCADE FORCE' | 'FORCE CASCADE' ] ``` - `RESTRICT`は、オブジェクトや使用中の参照がある場合は削除しません。 - `CASCADE`は、対象データベースのオブジェクト、メタデータ、データベースローカルの権限を削除します。 - `FORCE`は、終了可能なセッション、ステートメント、カーソル、ジョブの参照を終了してから削除を進めます。 - オブジェクトと参照を両方削除する場合は、`CASCADE FORCE`を使用します。 デフォルトのデータベース`MACHBASEDB`は削除できません。 現在のセッションのデータベースも削除できないため、先に`USE MACHBASEDB`または別のアクティブなデータベースへのUSEを実行する必要があります。 ## USE ```sql use_database_stmt ::= 'USE' ['DATABASE'] database_name ``` `USE`と`USE DATABASE`は同じ動作です。現在のセッションのデータベースだけを変更し、他の接続には影響しません。 トランザクションの進行中、または対象がマウントされたデータベースの場合は失敗します。 ```sql USE factory_a; USE DATABASE factory_b; ``` ## 現在のデータベースの確認 ```sql SELECT CURRENT_DATABASE(); SELECT DATABASE(); SELECT CURRENT_CATALOG; SHOW CURRENT DATABASE; SHOW DATABASES; ``` 推奨する確認方法は`CURRENT_DATABASE()`です。 クライアントの接続オプションで初期データベースを指定していても、接続直後にこの値を確認し、実際のサーバーカタログを検証してください。 ## オブジェクト名 テーブル・ビューとDMLの対象は、次の形式で指定できます。 ```text table_name -- 現在のデータベース、現在のユーザー owner.table_name -- 現在のデータベース、指定した所有者 database_name.owner.table_name -- 指定したデータベース、指定した所有者 ``` 2部構成の名前は常に`owner.table`です。 したがって、`factory_a.sensor_log`はデータベースとテーブルの2部構成の名前とは解釈されません。 別のデータベースを明示するには、`factory_a.sys.sensor_log`のように3部構成を使用します。 ```sql SELECT * FROM factory_a.sys.sensor_log; INSERT INTO factory_b.app.orders VALUES (1, 'ready'); ``` 別のデータベースを直接参照するには、対象データベースの`CONNECT`と対象テーブルの必要なDML権限が両方必要です。 インデックス名、`LOAD DATA`の対象などは、各構文の修飾子の制約に従います。 ## 権限構文とデータベース範囲 データベース権限とテーブル権限は別です。基本形式は次のとおりです。 ```sql GRANT CONNECT ON DATABASE factory_a TO app_a; GRANT CREATE, ALTER ON DATABASE factory_a TO deployer; GRANT SELECT, INSERT ON TABLE factory_a.sys.sensor_log TO app_a; REVOKE CONNECT ON DATABASE factory_a FROM app_a; ``` マウントされたデータベースを検索するには、対象データベースの`USAGE`とテーブルの`SELECT`が両方必要です。 `MOUNT DATABASE`と`UMOUNT DATABASE`を実行する運用権限は、[USER/AUTH構文](../user-auth-syntax/#grant-revoke)と [複数データベースの運用ガイド](/ja/dbms/operations-configuration-recovery/multi-database/)を参照してください。 ## BACKUP/RESTOREとの関係 論理データベースのバックアップ・リストア構文は、[BACKUP / RESTORE / MOUNT](../backup-restore-mount-syntax/)にまとめています。 単一のアクティブカタログを対象とした名前付きバックアップだけを、論理MOUNTまたはRESTOREの入力に使用できます。 複数のアクティブデータベースを含むインスタンス全体のイメージは、論理カタログとしてマウント・リストアできません。 --- title: "AUTO_INCREMENT" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/auto-increment-syntax/ language: ja kind: page --- # AUTO_INCREMENT `AUTO_INCREMENT`は、単一の64ビット整数PRIMARY KEY値をサーバーが自動生成するための列属性です。 Machbase 8.7.0からLOOKUPとVOLATILEでもサポート ## サポート範囲 | 項目 | サポート範囲 | |---|---| | Edition | Standard Edition | | テーブル | TRANSACTION、LOOKUP、VOLATILE | | 列の型 | `LONG`、`INT64` | | キー | 列単位の単一`PRIMARY KEY` | テーブルレベル・複合PRIMARY KEYには使用できません。 LOOKUPの同じ列に`PROPERTY(SEQUENCE)`を併用したり、`NEXTVAL()`を使用したりしないでください。 ```sql CREATE TRANSACTION TABLE device_master ( id LONG PRIMARY KEY AUTO_INCREMENT, device_name VARCHAR(80), site_code VARCHAR(32) ); CREATE LOOKUP TABLE lookup_order ( id INT64 PRIMARY KEY AUTO_INCREMENT, item VARCHAR(100) ); CREATE VOLATILE TABLE volatile_order ( id LONG PRIMARY KEY AUTO_INCREMENT, item VARCHAR(100) ); ``` 明示的なトランザクションの進行中は、TRANSACTIONテーブルのDDLを実行できません。 先に`COMMIT`または`ROLLBACK`してからテーブルを作成します。 ## 自動値の生成 自動生成列を省略するか`NULL`を入力すると、サーバーが値を生成します。 ```sql INSERT INTO device_master(device_name, site_code) VALUES ('compressor-01', 'SEOUL-A'); INSERT INTO device_master(id, device_name, site_code) VALUES (NULL, 'pump-02', 'SEOUL-A'); ``` `NULL`以外の値を直接指定することもできます。 指定値が現在の次の値以上なら、次の自動値はそれより大きい値から進み、小さい値を指定しても番号は戻りません。 `0`は有効です。`INT64_MAX`の後は生成できる値がないため、自動INSERTは失敗します。 重複キーや失敗したINSERTの後で番号が再使用されるかどうかに依存しないでください。 この値は行識別子であり、欠番のない業務連番ではありません。 ## テーブル別の違い | 動作 | TRANSACTION | LOOKUP | VOLATILE | |---|:---:|:---:|:---:| | 再起動後の行と次の自動値の保持 | O | O | X | | 明示的トランザクション | O | X | X | | `INSERT ... SELECT`による自動値生成 | O | X | X | | 単一INSERT結果のROWID | O | O | O | VOLATILEテーブルは、サーバー再起動時にデータが消失し、次の自動値は1に戻ります。 テーブル定義は保持されるため、再作成は不要です。 自動列を省略した`INSERT ... SELECT`は、TRANSACTIONのデータ移行でのみ使用できます。 ```sql INSERT INTO device_master(device_name, site_code) SELECT device_name, site_code FROM staging_device ORDER BY device_name; ``` ## INSERT結果の確認 対応するSDKは、成功した単一の`INSERT ... VALUES`の実行結果から、生成された識別子を提供できます。 batch、Append、loader、`INSERT ... SELECT`、UPSERTでは単一値を返しません。 詳細条件は[ROWID](../../rowid/)、言語別APIは [SDK機能のサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/)を参照してください。 ## 関連文書 - [TRANSACTIONテーブルの構造](/ja/dbms/rdb-table-usage/table-structure-schema/) - [LOOKUPテーブルの構造](/ja/dbms/lookup-table-usage/table-structure-schema/) - [VOLATILEテーブルの構造](/ja/dbms/volatile-table-usage/table-structure-schema/) - [LOOKUP SEQUENCE](/ja/dbms/lookup-table-usage/sequence-column/) --- title: "EXECプロシージャとROLLUPGAP" url: https://docs.machbase.com/ja/dbms/reference/sql/syntax/execute-procedure-syntax/ language: ja kind: page --- # EXECプロシージャとROLLUPGAP Machbaseが公開するテーブル・ROLLUP制御プロシージャと、machsqlの状態確認コマンドを説明します。 ## 共通のEXEC形式 ```text execute_procedure_stmt ::= 'EXEC' procedure_name [ '(' argument_list ')' ] ``` プロシージャごとの引数の数は固定です。 名前がない場合、引数の数・型が異なる場合、対象オブジェクトが存在しない場合はエラーを返します。 ## TABLE_FLUSH ```sql EXEC TABLE_FLUSH(table_name); ``` | 項目 | 仕様 | |---|---| | 引数 | テーブル名1つ | | Edition | Standard、Cluster | | 動作 | テーブルの保留中のストレージ・入力バッファを明示的にflush | | 戻り値 | ResultSetなしで文の成功またはエラーを返す | | エラー | テーブルなし、アクセス不可、flush処理失敗 | 検証や運用で明示的なストレージのflushが必要な場合に使用します。 トランザクションのコミットやクエリの可視性を保証する手段ではありません。 入力行ごとに呼ぶとflushコストが増えるため、繰り返し呼び出さないでください。 ## INDEX_FLUSH ```sql EXEC INDEX_FLUSH(table_name); EXEC INDEX_FLUSH(table_name, index_name); ``` テーブル名だけを指定すると、そのテーブルのすべてのインデックス構築が終わるまで待機します。 インデックス名も指定すると、そのインデックスだけを対象にします。 指定したインデックスがそのテーブルに属さない場合はエラーです。ResultSetは返しません。 ## TABLE_REFRESH ```sql EXEC TABLE_REFRESH(lookup_table_name); ``` | 項目 | 仕様 | |---|---| | 引数 | LOOKUPテーブル名1つ | | Edition | Standard、Cluster | | 動作 | 永続LOOKUPの内容を実行時メモリテーブルに再反映 | | 名前の範囲 | 現在のデータベースのテーブル。`owner.table`を許可 | | 権限 | テーブル所有者または許可された管理ユーザー | | 書き込み制限 | READ ONLYデータベースでは実行不可 | | 戻り値 | ResultSetなしで文の成功またはエラーを返す | | エラー | LOOKUP以外のテーブル、テーブルなし、書き込み許可判定の失敗 | 実行前に進行中のLOOKUP変更とクエリへの影響を確認し、完了後に行数と代表的なキーを再検索します。 ## FREEZE_TAG_INDEXとUNFREEZE_TAG_INDEX ```sql EXEC FREEZE_TAG_INDEX(tag_table_name); EXEC UNFREEZE_TAG_INDEX(tag_table_name); ``` TAGテーブルのタグインデックスを凍結・解除する1引数のプロシージャです。TAG以外のテーブルには使用できません。 インデックス保守の境界を直接制御する運用コマンドのため、通常の取り込み処理で常用せず、 失敗時は必ず`UNFREEZE_TAG_INDEX`の実行を確認してください。 両方ともResultSetなしで文の成功またはエラーを返します。 ## ROLLUP_STARTとROLLUP_STOP ```sql EXEC ROLLUP_START; EXEC ROLLUP_START(rollup_name); EXEC ROLLUP_STOP; EXEC ROLLUP_STOP(rollup_name); ``` 両方のプロシージャは、0引数とROLLUP名1引数の形式に対応します。 名前を指定するとそのROLLUP、省略すると現在のユーザー範囲のROLLUPを制御します。 SYSの引数なし実行は全ユーザー範囲に適用される場合があるため、対象確認と変更承認が必要です。 存在しないROLLUP、開始済みの対象へのSTART、停止済みの対象へのSTOPはエラーです。 `V$ROLLUP.RUN_STATE`で変更結果を確認します。 ## ROLLUP_FORCE ```sql EXEC ROLLUP_FORCE; EXEC ROLLUP_FORCE(rollup_name); ``` 0引数形式は、現在のユーザー範囲の基本SEC→MIN→HOUR階層を処理します。 名前を指定すると、そのROLLUPソースの現在のEND_RIDに追いつくまで待機する同期処理です。 停止したROLLUPは、先にSTART状態であることを確認します。 完了後は`V$ROLLUP`と`SHOW ROLLUPGAP`で、関連するすべてのソース段階のgapを確認します。 ## ROLLUP_REBUILD タグと時間範囲を受け取る、4引数のStandard専用プロシージャです。 詳細仕様の正本は[ROLLUP_REBUILD](../rollup-rebuild-syntax/)です。 ## SHOW ROLLUPGAP ```sql SHOW ROLLUPGAP; ``` `SHOW ROLLUPGAP`はサーバーSQLではなく、**machsql専用のクライアントコマンド**です。 JDBC、ODBC、SDKの通常のSQL実行APIに同じ文字列を送信しないでください。 Standardの出力には、ソース・ROLLUPテーブル、ソースEND_RID、ROLLUP END_RID、`GAP`、状態、起動時刻が含まれます。 Clusterの出力には`HOSTNAME`が加わり、ノード別の状態を表示します。 `GAP = SRC_END_RID - ROLLUP_END_RID`であり、階層内のすべてのソース→ROLLUP行が0であることを確認して初めて、階層全体が追いついたと判断できます。 ## 関連文書 - [ROLLUPの運用と状態](/ja/dbms/tag-rollup-usage/ingestion-control-rollup/) - [V$ROLLUPリファレンス](/ja/dbms/reference/system-catalog/vrollup/) - [machsqlコマンド](/ja/dbms/reference/command-line-tools/machsql/) --- title: "16.1.2 データ型辞典" url: https://docs.machbase.com/ja/dbms/reference/sql/types/ language: ja kind: section --- # 16.1.2 データ型辞典 MachbaseがサポートするSQLデータ型を説明します。 型は保存する値の範囲と精度に合わせて選択します。整数の最小値や最大値など、NULL表現に予約された値は 通常のデータとして使用できません。次の表の`NULL値`は内部表現です。SQLでは`NULL`を挿入し、 `IS NULL`で検査します。 ## データ型の概要 | 型 | サイズ | 値の範囲 | NULL値 | |------|------|---------|---------| | `SHORT` | 2 bytes | -32,767 ~ 32,767 | -32,768 | | `USHORT` | 2 bytes | 0 ~ 65,534 | 65,535 | | `INTEGER` | 4 bytes | -2,147,483,647 ~ 2,147,483,647 | -2,147,483,648 | | `UINTEGER` | 4 bytes | 0 ~ 4,294,967,294 | 4,294,967,295 | | `LONG` | 8 bytes | -9,223,372,036,854,775,807 ~ 9,223,372,036,854,775,807 | -9,223,372,036,854,775,808 | | `ULONG` | 8 bytes | 0 ~ 18,446,744,073,709,551,614 | 18,446,744,073,709,551,615 | | `FLOAT` | 4 bytes | 32ビット単精度浮動小数点 | 正の最大値 | | `DOUBLE` | 8 bytes | 64ビット倍精度浮動小数点 | 正の最大値 | | `DECIMAL(M,D)` | precisionにより可変 | exact fixed-point, M: 1~65, D: 0~30 | - | | `ARRAY` | 要素型と要素数により可変 | 固定長1次元数値配列、要素数1~1024 | 配列全体のNULLと要素のNULLを区別 | | `DATETIME` | 8 bytes | 1970-01-01 ~ 2262-04-11 (ナノ秒精度) | - | | `VARCHAR(n)` | 可変 | 最大nバイト(LOGの宣言範囲: 1~32,767) | - | | `IPV4` | 4 bytes | 0.0.0.0 ~ 255.255.255.255 | - | | `IPV6` | 16 bytes | 0000:...:0000 ~ FFFF:...:FFFF | - | | `TEXT` | 可変 | 0 ~ 64MB(全文検索インデックス対応) | - | | `BINARY` | 可変 | LOG: 0~64MB / TAG: 1~32,767 bytes (固定長) | - | | `JSON` | 可変 | JSONドキュメント: 1~32,768 bytes / path: 1~512 bytes | - | --- ## 整数型 ### SHORT 16ビット符号付き整数型です。保存サイズはCの`int16_t`と同じですが、最小値(-32,768)は NULL表現に予約されています。SQLでは別名`INT16`も使用できます。 ```sql CREATE LOG TABLE t (c1 SHORT); INSERT INTO t VALUES (-32767); -- 有効な最小値 INSERT INTO t VALUES (-32768); -- NULLとして処理 ``` ### USHORT 16ビット符号なし整数(`uint16_t`)です。最大値(65,535)はNULLとして認識されます。 ### INTEGER 32ビット符号付き整数型です。保存サイズはCの`int32_t`と同じですが、最小値はNULL表現に予約されています。 SQLでは別名`INT32`または`INT`も使用できます。 ### UINTEGER 32ビット符号なし整数(`uint32_t`)です。 ### LONG 64ビット符号付き整数型です。保存サイズはCの`int64_t`と同じですが、最小値はNULL表現に予約されています。 SQLでは別名`INT64`も使用できます。 ### ULONG 64ビット符号なし整数(`uint64_t`)です。 --- ## 浮動小数点型 ### FLOAT C言語の32ビット浮動小数点型`float`と同じです。正の最大値はNULLとして認識されます。 ### DOUBLE C言語の64ビット浮動小数点型`double`と同じです。正の最大値はNULLとして認識されます。 --- ## 固定小数点型 ### DECIMAL / NUMERIC 宣言した精度と小数桁数の範囲で10進数を正確に保存する固定小数点型です。入力値の小数桁数が 宣言範囲を超えると丸めが発生する場合があるため、金額や比率を保存する場合は必要な桁数を 事前に決めてください。`NUMERIC`、`DEC`、`FIXED`、`NUMBER`は`DECIMAL`の別名です。 ```sql CREATE TRANSACTION TABLE invoice ( id LONG PRIMARY KEY, amount DECIMAL(18,2), rate NUMERIC(7,4) ); ``` `DECIMAL`は`DECIMAL(10,0)`、`DECIMAL(M)`は`DECIMAL(M,0)`と解釈します。宣言規則、丸め、 インデックス、集計、クライアントマッピングは[DECIMALとNUMERIC固定小数点型](decimal-numeric-fixed-point/)を 参照してください。 --- ## ARRAY型 Machbase DBMS 8.7.0は、数値要素を決まった個数保存する固定長1次元の`ARRAY`型をサポートします。 要素型の後に要素数(cardinality)を指定します。 ```sql CREATE LOG TABLE sensor_array ( id INTEGER, location DOUBLE[2], acceleration FLOAT[3] ); ``` 対応する要素型、NULLの区別、取り込み・参照構文、SDK別の表現は [数値ARRAY型](array/)を参照してください。 --- ## 日付/時刻型 ### DATETIME 1970年1月1日午前0時からの経過時間をナノ秒値で内部保存します。表現範囲は1970-01-01 00:00:00 000:000:000 ~ 2262-04-11 23:47:16.854:775:807です。 - ナノ秒単位まで処理可能 - 内部表現: 8バイト整数 (nanoseconds since epoch) - 文字列表現: `YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn` ```sql -- 文字列からDATETIMEへ変換 SELECT TO_DATE('2024-01-15 10:30:00 000:000:000'); -- DATETIMEから文字列へ変換 SELECT TO_CHAR(ts, 'YYYY-MM-DD HH24:MI:SS') FROM t; ``` --- ## 文字列型 ### VARCHAR(n) 可変長文字列型です。`n`は文字数ではなく保存できるバイト数で、LOGでの宣言範囲は1~32,767です。 UTF-8では文字によって必要なバイト数が異なるため、ハングルや絵文字などを保存する場合は、 実際のエンコーディングサイズを考慮して長さを指定してください。 ```sql CREATE LOG TABLE t (name VARCHAR(100), description VARCHAR(1000)); ``` ### TEXT VARCHARのサイズを超える大容量テキストを保存する型で、最大64MBを保存できます。 テキスト保存のサポートとKEYWORDインデックスのサポートは別です。 インデックスの使用可否はテーブルタイプによって異なります。 - LOGとStandard EditionのTRANSACTIONテーブルでサポート - LOGテーブルはKEYWORDインデックスと`SEARCH`演算子でキーワード検索が可能 - TAG、LOOKUP、VOLATILEテーブルでは非対応 LOGのTEXT列そのものにはORDER BY・GROUP BYを適用できません。 これは性能上の推奨事項ではなく、クエリ検証で拒否される制約です。 ソート・集計に使用するデバイス、エラーコード、重要度などは別のVARCHAR列や数値列に保存してください。 TEXTをVARCHARへ変更するための`MODIFY COLUMN`もサポートしません。 ```sql CREATE LOG TABLE log_table (ts DATETIME, message TEXT); -- キーワードインデックスの作成 CREATE INDEX idx_msg ON log_table (message) INDEX_TYPE KEYWORD; ``` --- ## バイナリ型 ### BINARY 画像や文書などの非構造化バイナリデータを保存する型です。 - **LOGテーブル**: 可変長、最大64MB - **TRANSACTIONテーブル**: 可変長バイナリ値をサポート(Standard Edition) - **TAGテーブル**: `BINARY(n)`形式の固定長型、1 ~ 32,767 bytes - LOOKUP、VOLATILEテーブルでは非対応 TAGテーブルの`BINARY(n)`: - `X'...'`、`B'...'`、`O'...'`リテラルをサポート(小文字の接頭辞にも対応) - 互換性のために`'0x...'`形式もサポート - 宣言した長さを超えると`ERR-02233`エラーが発生 --- ## ネットワークアドレス型 ### IPV4 IPv4アドレスを保存する型です。内部で4バイトを使用し、`"0.0.0.0"` ~ `"255.255.255.255"`の範囲を表します。 ```sql CREATE LOG TABLE access_log (ts DATETIME, src_ip IPV4, dst_ip IPV4); INSERT INTO access_log VALUES (NOW, '192.168.0.1', '10.0.0.1'); SELECT * FROM access_log WHERE src_ip = TO_IPV4('192.168.0.1'); ``` ### IPV6 IPv6アドレスを保存する型です。内部で16バイトを使用します。省略表記にも対応します。 - `"::FFFF:1232"` — 先頭の0を省略 - `"::FFFF:192.168.0.3"` — IPv4互換表記 - `"::192.168.3.1"` — IPv4互換表記 (deprecated) ```sql CREATE LOG TABLE v6_log (ts DATETIME, src_ip IPV6); INSERT INTO v6_log VALUES (NOW, '21DA:D3:0:2F3B:2AA:FF:FE28:9C5A'); ``` --- ## JSON型 JSONドキュメントを保存する型です。キーと値のペアで構成されるJSONデータをテキスト形式で保存します。 - データの最大サイズ: 32,768 bytes - JSONパスの最大長: 512 bytes - TAG、LOG、LOOKUP、TRANSACTIONテーブルでサポート - VOLATILEテーブルではJSON列の作成不可 - LOOKUPテーブルのJSON列は主キーとして使用不可 ```sql CREATE LOG TABLE sensor_data ( ts DATETIME, data JSON ); INSERT INTO sensor_data VALUES (NOW, '{"temp":23.5,"hum":60}'); SELECT data -> 'temp' AS temperature FROM sensor_data; ``` テーブルタイプ別のJSONサポート範囲の詳細は、[JSON型のテーブルタイプ別サポート範囲](table-types-type-support-scope-json/)を参照してください。 --- ## SQLデータ型のマッピング Machbaseのデータ型とSQL標準型、C型の対応関係です。 | Machbase 型 | Machbase CLI 型 | SQL 型 | C 型 | C基本型 | |--------------|------------------|----------|--------|------------| | `short` | SQL_SMALLINT | SQL_SMALLINT | SQL_C_SSHORT | `int16_t` | | `ushort` | SQL_USMALLINT | SQL_SMALLINT | SQL_C_USHORT | `uint16_t` | | `integer` | SQL_INTEGER | SQL_INTEGER | SQL_C_SLONG | `int32_t` | | `uinteger` | SQL_UINTEGER | SQL_INTEGER | SQL_C_ULONG | `uint32_t` | | `long` | SQL_BIGINT | SQL_BIGINT | SQL_C_SBIGINT | `int64_t` | | `ulong` | SQL_UBIGINT | SQL_BIGINT | SQL_C_UBIGINT | `uint64_t` | | `float` | SQL_FLOAT | SQL_REAL | SQL_C_FLOAT | `float` | | `double` | SQL_DOUBLE | SQL_FLOAT, SQL_DOUBLE | SQL_C_DOUBLE | `double` | | `decimal` | SQL_DECIMAL | SQL_DECIMAL, SQL_NUMERIC | SQL_C_NUMERIC | decimal-preserving value | | `datetime` | SQL_TIMESTAMP | SQL_TYPE_TIMESTAMP | SQL_C_TYPE_TIMESTAMP | `char *` (YYYY-MM-DD ...) | | `varchar` | SQL_VARCHAR | SQL_VARCHAR | SQL_C_CHAR | `char *` | | `ipv4` | SQL_IPV4 | SQL_VARCHAR | SQL_C_CHAR | `char *` (IP文字列) | | `ipv6` | SQL_IPV6 | SQL_VARCHAR | SQL_C_CHAR | `char *` (IP文字列) | | `text` | SQL_TEXT | SQL_LONGVARCHAR | SQL_C_CHAR | `char *` | | `binary` | SQL_BINARY | SQL_BINARY | SQL_C_BINARY | `char *` | | `json` | SQL_JSON | SQL_JSON | SQL_C_CHAR | `json_t` | --- ## テーブルタイプ別の対応データ型 | 型 | TAG | LOG | LOOKUP | VOLATILE | TRANSACTION | |------|:---:|:---:|:------:|:--------:|:---:| | SHORT | O | O | O | O | O | | USHORT | O | O | O | O | O | | INTEGER | O | O | O | O | O | | UINTEGER | O | O | O | O | O | | LONG | O | O | O | O | O | | ULONG | O | O | O | O | O | | FLOAT | O | O | O | O | O | | DOUBLE | O | O | O | O | O | | DECIMAL / NUMERIC | O | O | O | O | O | | DATETIME | O | O | O | O | O | | VARCHAR | O | O | O | O | O | | IPV4 | O | O | O | O | O | | IPV6 | O | O | O | O | O | | TEXT | X | O | X | X | O | | JSON | O | O | O | X | O | | BINARY | O (固定長) | O | X | X | O | DECIMALはすべての公開テーブルタイプでサポートします。TRANSACTIONテーブル自体はStandard Editionで 使用し、Cluster EditionではLOG/TAGテーブルのDECIMAL列とDDL伝播をサポートします。 --- title: "JSON型のテーブルタイプ別サポート範囲" url: https://docs.machbase.com/ja/dbms/reference/sql/types/table-types-type-support-scope-json/ language: ja kind: page --- # JSON型のテーブルタイプ別サポート範囲 JSON型の列を各テーブルタイプで使用する場合のサポート範囲を示します。 ## サポート範囲の概要 | テーブルタイプ | JSON列の作成 | JSON path query | JSON PK | 備考 | |------------|:-------------:|:---------------:|:-------:|------| | TAG | O | O | X | JSON列とJSON関数をサポート。PKは非対応 | | LOG | O | O | X | JSON列とJSON関数をサポート | | LOOKUP | O | O | X | 通常の列としてサポート。JSONパスインデックスは非対応 | | VOLATILE | X | X | X | JSON列の作成不可 | | TRANSACTION | O | O | X | JSON列とJSON関数をサポート | ## LOOKUPテーブル LOOKUPテーブルはJSON型の列を通常の列としてサポートします。 ```sql CREATE LOOKUP TABLE config_lookup ( key VARCHAR(64) PRIMARY KEY, site VARCHAR(32), config JSON ); INSERT INTO config_lookup VALUES ( 'device-001', 'SEOUL', '{"region":"kr","level":3,"state":"ready"}' ); SELECT key FROM config_lookup WHERE config->'$.region' = 'kr' AND JSON_EXTRACT_INTEGER(config, '$.level') >= 3; ``` JSON列は`JSON_SET`、`JSON_SET_JSON`、`JSON_REMOVE`などのJSON関数で更新できます。 ```sql UPDATE config_lookup SET config = JSON_SET(config, '$.state', 'active') WHERE site = 'SEOUL'; ``` ただし、JSON列は主キーとして宣言できません。 ```sql -- エラー CREATE LOOKUP TABLE invalid_lookup ( config JSON PRIMARY KEY ); ``` ## VOLATILEテーブル VOLATILEテーブルではJSON型の列を作成できません。 ```sql CREATE VOLATILE TABLE session_data ( session_id VARCHAR(64) PRIMARY KEY, payload JSON ); ``` ## JSON関連関数のテーブルタイプ別サポート | 関数/演算子 | TAG | LOG | LOOKUP | VOLATILE | TRANSACTION | |-------------|:---:|:---:|:------:|:--------:|:---:| | `->`演算子 | O | O | O | X | O | | `JSON_EXTRACT*` | O | O | O | X | O | | `JSON_TYPEOF` | O | O | O | X | O | | `JSON_IS_VALID` | O | O | O | O | O | | `JSON_SET` | O | O | O | X | O | | `JSON_SET_JSON` | O | O | O | X | O | | `JSON_REMOVE` | O | O | O | X | O | ## 使用上の注意 - JSONパス文字列は単一引用符(`'$.key'`)で囲みます。 - 数値の比較には`JSON_EXTRACT_INTEGER`、`JSON_EXTRACT_DOUBLE`などの型別の関数を使用します。 - LOOKUPテーブルではJSONパス専用インデックスをサポートしないため、頻繁に検索する値は別の列に分離します。 --- title: "DECIMALとNUMERIC固定小数点型" url: https://docs.machbase.com/ja/dbms/reference/sql/types/decimal-numeric-fixed-point/ language: ja kind: page --- # DECIMALとNUMERIC固定小数点型 `DECIMAL`は10進数を誤差なく保存する正確な固定小数点型です。`NUMERIC`、`DEC`、`FIXED`、`NUMBER`は `DECIMAL`の別名であり、`DESC`、`SHOW`、結果メタデータでは正規名の`DECIMAL`と表示されます。 `NUMBER`はMySQLの別名ではなく、Machbaseの互換性拡張の別名です。 ## 宣言構文 ```sql DECIMAL DECIMAL(precision) DECIMAL(precision, scale) NUMERIC NUMERIC(precision) NUMERIC(precision, scale) ``` | 宣言 | 解釈 | |------|------| | `DECIMAL` | `DECIMAL(10,0)` | | `DECIMAL(M)` | `DECIMAL(M,0)` | | `DECIMAL(M,D)` | precision `M`, scale `D` | - precisionは有効数字の総桁数で、`1`から`65`まで指定します。 - scaleは小数部の桁数で、`0`から`30`まで指定します。 - scaleはprecisionを超えることはできません。 - `UNSIGNED`と`ZEROFILL`はサポートしません。 ```sql CREATE TRANSACTION TABLE invoice ( invoice_id LONG PRIMARY KEY, amount DECIMAL(18,2), tax_rate NUMERIC(7,4) ); ``` ## 丸めと範囲超過 入力値の小数桁数がscaleを超えた場合は、中間値を0から遠ざかる方向へ丸める round-half-away-from-zeroを適用します。 ```sql CREATE TRANSACTION TABLE decimal_rounding ( id INTEGER PRIMARY KEY, amount DECIMAL(5,2) ); INSERT INTO decimal_rounding VALUES (1, 1.235); -- 1.24 INSERT INTO decimal_rounding VALUES (2, -1.235); -- -1.24 ``` precisionを超える値は、切り捨てや浮動小数点への変換を行わずエラーとして扱います。 `DECIMAL`のNULLは特定の数値を番兵値として使用せず、値とは別に管理します。 ## テーブルタイプ別サポート | テーブルタイプ | DECIMAL列 | 主な用途 | |------------|:------------:|----------------| | LOG | O | 金額・精算イベント、正確な集計 | | TAG | O | 正確な計測値と集計対象のデータ列 | | VOLATILE | O | 状態・キャッシュ値、主キー | | LOOKUP | O | 基準金額・比率、主キーとセカンダリインデックス | | TRANSACTION | O | リレーショナルな業務データ、PK/UNIQUE/通常インデックス | ```sql CREATE LOG TABLE payment_log ( occurred_at DATETIME, amount DECIMAL(18,2) ); CREATE TAG TABLE meter_value ( name VARCHAR(80) PRIMARY KEY, time DATETIME BASETIME, value DECIMAL(24,6) ); CREATE VOLATILE TABLE exchange_cache ( rate_key DECIMAL(12,6) PRIMARY KEY, label VARCHAR(32) ); CREATE LOOKUP TABLE price_rule ( rule_id LONG PRIMARY KEY, amount DECIMAL(18,2) ); ``` Cluster EditionではLOG/TAGテーブルのDECIMAL列とDDL伝播をサポートします。TRANSACTIONテーブルは DECIMAL型とは関係なくStandard Editionで使用します。 ## 比較とインデックス すべてのテーブルエンジンは同じDECIMAL比較規則を使用します。表現するscaleが異なっても、 数値が同じなら等しい値として比較します。 ```sql -- 1、1.0、1.00は等値・PK・UNIQUEの比較で同じ値です。 SELECT * FROM price_rule WHERE amount = 1.00; ``` VOLATILEとLOOKUPの主キーメモリインデックス、TRANSACTIONテーブルの通常・UNIQUE・PRIMARY KEY インデックスでDECIMALを使用できます。TRANSACTIONインデックスは等値、範囲、並べ替えに同じ数値順序を適用します。 VIEWの派生列もDECIMALのprecisionとscaleを維持します。`DESC`、`SHOW`、`M$SYS_COLUMNS`、 クライアントの結果メタデータでprecisionとscaleをそれぞれ確認できます。 ## 式と集約関数 `+`、`-`、`*`、`/`、`ROUND`、`TRUNC`、[CAST](../../functions/functions-full/#cast)と次の集計・ソート操作で DECIMAL値を使用できます。 - `SUM`, `AVG`, `MIN`, `MAX` - `GROUP BY`, `ORDER BY`, `DISTINCT` 正確なDECIMAL処理経路がない高度な統計関数、percentile、`TOP_K`などはDECIMAL値をDOUBLEに 変換して計算するため、結果が近似値になる場合があります。 ## 入出力とクライアントマッピング machloaderの`.fmt`、CSVインポート/エクスポート、Append経路は、符号、NULL、precision、scaleを 保持します。浮動小数点型を経由せず、文字列または各言語のdecimal型で渡してください。 | インターフェース | 推奨マッピング | |-----------|-----------| | ODBC | `SQL_DECIMAL` / `SQL_NUMERIC`, `SQL_C_NUMERIC` | | JDBC | `java.math.BigDecimal` | | Python | `decimal.Decimal` | | Node.js | decimal互換の文字列、またはコネクターのdecimal表現 | | .NET | `decimal`, `DbType.Decimal` | GoでNUMERIC値を扱う場合も、`float64`へ変換せず、コネクターが提供する10進精度を保持する値か 文字列表現を使用してください。 ## 型の選択 - 通貨、税率、精算額など10進数の正確性が必要な場合は`DECIMAL`を使用します。 - センサーの実数値など、近似値と広い指数範囲が重要な場合は`FLOAT`または`DOUBLE`を使用します。 - 保存・比較・演算中にDECIMAL値をDOUBLEへ変換すると、正確な固定小数点の性質が失われます。 --- title: "数値ARRAY" url: https://docs.machbase.com/ja/dbms/reference/sql/types/array/ language: ja kind: page --- # 数値ARRAY Machbase DBMS 8.7.0は、同じ数値型の値を決まった個数保存する固定長1次元の`ARRAY`型をサポートします。 センサーの座標や軸別の測定値など、1行に複数の数値をまとめて保存し、要素ごとに参照する場合に使用します。 一部の位置だけを取り込む方法と選択列Append APIは、 [Sparse ARRAYと選択列Append API](../../../../development-tools-integration/data-input-load-export/array-append/)を参照してください。 ## 対応する型と宣言範囲 列の宣言では、数値の要素型の後に`[cardinality]`を付けます。cardinalityは配列の要素数で、各行の 非NULL要素数ではなく、列に宣言した固定長を表します。配列全体が存在しない状態(whole NULL)と、 配列内の特定の値だけが存在しない状態(element NULL)は区別します。 | 要素型 | DDL例 | 説明 | |---|---|---| | `INT16` | `INT16[4]` | 16ビット符号付き整数 | | `UINT16` | `UINT16[4]` | 16ビット符号なし整数 | | `INT32` | `INT32[4]` | 32ビット符号付き整数 | | `UINT32` | `UINT32[4]` | 32ビット符号なし整数 | | `INT64` | `INT64[4]` | 64ビット符号付き整数 | | `UINT64` | `UINT64[4]` | 64ビット符号なし整数 | | `FLOAT` | `FLOAT[4]` | 単精度浮動小数点 | | `DOUBLE` | `DOUBLE[4]` | 倍精度浮動小数点 | | `DECIMAL(p,s)` | `DECIMAL(12,4)[4]` | 固定小数点数 | - cardinalityの範囲は`1..1024`です。 - `DECIMAL`のprecisionの範囲は`1..65`です。 - `DECIMAL`のscaleの範囲は`0..30`で、precisionを超えることはできません。 次の別名は、対応する正規の要素型として扱います。 | 別名 | 正規の型 | |---|---| | `SHORT` | `INT16` | | `USHORT` | `UINT16` | | `INT`, `INTEGER` | `INT32` | | `UINTEGER` | `UINT32` | | `LONG` | `INT64` | | `ULONG` | `UINT64` | | `NUMERIC`, `DEC`, `FIXED`, `NUMBER` | `DECIMAL` | ## テーブルの作成と列の追加 次の例は、4つのチャネル値、3つの累積値、2つの固定小数点値を保存します。 ```sql CREATE LOG TABLE SENSOR_ARRAY ( ID INTEGER, CHANNELS DOUBLE[4], COUNTERS UINT64[3], AMOUNTS DECIMAL(12,4)[2] ); ``` `ADD COLUMN`に対応する既存テーブルには、同じARRAY宣言を使用して列を追加できます。 削除には既存の`DROP COLUMN`構文を使用します。 ```sql ALTER TABLE SENSOR_ARRAY ADD COLUMN (STATUS_VALUES INT32[3]); ALTER TABLE SENSOR_ARRAY ADD COLUMN (LIMITS DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); ALTER TABLE SENSOR_ARRAY DROP COLUMN (STATUS_VALUES); ALTER TABLE SENSOR_ARRAY DROP COLUMN (LIMITS); ``` `DECIMAL(12)[2]`のようにscaleを省略すると、`DECIMAL(12,0)[2]`として扱います。 TAG METADATA ARRAYには`METADATA ADD COLUMN`と`METADATA DROP COLUMN`を使用します。 ```sql ALTER TABLE SENSOR_TAG METADATA ADD COLUMN (LIMITS DECIMAL(12,4)[2] DEFAULT [0.0000, NULL]); ALTER TABLE SENSOR_TAG METADATA DROP COLUMN (LIMITS); ``` `ARRAY`は次の場所の通常のデータ列に使用できます。 - LOGテーブル - TAG DATAの通常のDATA列 - TAG METADATAの通常のメタデータ列 - VOLATILEテーブル - LOOKUPテーブル - Standard EditionのTRANSACTIONテーブル `ARRAY`の追加によって各テーブルの既存のDML範囲が広がることはありません。例えばLOGテーブルの `UPDATE`は引き続き非対応であり、TAGテーブルの`UPDATE`も既存の許容されたDATAまたはMETADATA経路のみ使用できます。 ### ADD COLUMNのサポート範囲 | Edition | テーブルまたは列の領域 | ARRAY ADD/DROP | |---|---|:---:| | Standard | LOG | O | | Standard | VOLATILE | O | | Standard | LOOKUP | O | | Standard | TRANSACTION | O | | Standard | TAG METADATA | O | | Standard | TAG DATAの通常列 | X | | Cluster | LOG | O | | Cluster | その他のテーブルまたはTAG METADATA | X | TAG DATAの通常のARRAY列は`CREATE TABLE`で宣言できますが、ALTERでは追加できません。 ### DEFAULTと既存行 - DEFAULTがなければ、ALTER前から存在する行の新しいARRAY列は全体がNULLになります。 - LOG、LOOKUP、TRANSACTION、TAG METADATAは、明示したARRAY DEFAULTを既存行に適用します。 - VOLATILEはスカラー列の`ADD COLUMN`と同様、既存行をDEFAULTで書き直さないため、新しいARRAY列は全体がNULLになります。 - Cluster LOGは、明示したARRAY DEFAULTを既存行に適用します。 - DEFAULTの配列コンストラクターの要素数は、宣言したcardinalityと完全に一致する必要があります。 ALTER後にTAG DATAのINSERTまたはAppendで新しいタグが自動登録される場合、新しいメタデータ行には ADD COLUMNのDEFAULTを適用しません。追加したARRAYメタデータ列は全体がNULLとして作成されます。 このDEFAULTは、ALTER前から存在するメタデータ行にのみ適用します。 次の用途には`ARRAY`を使用できません。 - PRIMARY KEY、UNIQUE、通常のインデックスキー - `AUTO_INCREMENT`、`SEQUENCE` - TAGテーブルのNAME、BASETIME、BASE DISTANCE、SUMMARIZED列 TAG METADATA ARRAY列には自動インデックスを作成しません。明示的なインデックスも非対応です。 次の宣言はサポートしません。 ```sql INT32[] INT32[0] INT32[1025] VARCHAR[4] INT32[2][3] DECIMAL[4](12,4) ``` ## ARRAY値の取り込み `ARRAY[...]`と省略形`[...]`の両方を使用できます。 ```sql INSERT INTO SENSOR_ARRAY VALUES (1, ARRAY[1.5, NULL, 3.5, 4.5], [1, NULL, 3], [12.3400, NULL]); INSERT INTO SENSOR_ARRAY VALUES (2, [10.0, 20.0, 30.0, 40.0], [4, 5, 6], [1.2500, 2.5000]); INSERT INTO SENSOR_ARRAY VALUES (3, NULL, NULL, NULL); ``` コンストラクターの要素数は対象列のcardinalityと完全に一致する必要があります。長さが異なる場合は、 埋め合わせや切り詰めを行わず文を失敗させます。空の`[]`や`ARRAY[]`も、cardinalityが0の保存値としては使用できません。 各要素に、対象数値型の変換、符号、範囲、`DECIMAL`のprecisionとscaleの規則を適用します。 1つでも変換できない要素があれば文全体が失敗し、`ARRAY`の一部だけを保存することはありません。 ### 数値の範囲 整数型は内部のNULL番兵値を実際の値として保存できません。 | 型 | 保存可能な範囲 | |---|---| | `INT16` | `-32767..32767` | | `UINT16` | `0..65534` | | `INT32` | `-2147483647..2147483647` | | `UINT32` | `0..4294967294` | | `INT64` | `-9223372036854775807..9223372036854775807` | | `UINT64` | `0..18446744073709551614` | `FLOAT`と`DOUBLE`でも、NULL番兵値として予約された最大有限値は実際の要素として保存できません。 それを超える入力のInfinity処理は、対応するスカラー型と同じです。 ### 対象列がない場合のARRAY型推論 `SELECT [1,2,3]`など対象列のない文脈では、全要素から共通の型を推論します。 - すべての非NULL要素が同じ型なら、その型を維持します。 - 符号付き整数と符号なし整数は、すべての値を格納できる最小の整数型へ昇格します。 - 符号付き整数と`UINT64`が混在する場合は`DECIMAL(20,0)`を使用します。 - `DECIMAL`同士では、必要な整数桁数とscaleを組み合わせます。 - `FLOAT`のみなら`FLOAT`を維持し、他の数値型と混在する場合は`DOUBLE`へ昇格します。 - 空の配列、全要素がNULLの配列、非数値要素、入れ子の配列は推論エラーです。 INSERT、UPDATE、プリペアドパラメーターなど対象列がある場合は、対象列の要素型、cardinality、 `DECIMAL`メタデータで各要素を検証します。 ### 配列全体のNULLと要素のNULL `ARRAY`自体のNULLと、NULL要素を持つ`ARRAY`は異なる値です。 ```sql -- ARRAY自体がNULLです。 INSERT INTO SENSOR_ARRAY (ID, CHANNELS) VALUES (10, NULL); -- ARRAYは存在し、4つの要素がすべてNULLです。 INSERT INTO SENSOR_ARRAY (ID, CHANNELS) VALUES (11, [NULL, NULL, NULL, NULL]); ``` `NOT NULL`は`ARRAY`全体のNULLのみを制限します。このため、全要素がNULLの`ARRAY`は `NOT NULL`列にも取り込めます。 ## 要素の参照 要素の位置は0始まりです。cardinalityが4の場合、有効な位置は`0..3`です。 ```sql SELECT CHANNELS, CHANNELS[0] AS FIRST_CHANNEL, CHANNELS[3] AS LAST_CHANNEL, CHANNELS[4] AS OUT_OF_RANGE FROM SENSOR_ARRAY; ``` 次の場合は、エラーではなくSQL `NULL`を返します。 - 添字が負数、またはcardinality以上の場合 - 添字の式がSQL NULLの場合 - `ARRAY`全体がNULLの場合 - 該当要素がNULLの場合 {{< callout type="warning" >}} 要素の位置を表す`[位置]`は、引用符で囲んでいない単純な列名の後にのみ付けられます。 `A[0]`は使用できますが、`T.A[0]`と`"A"[0]`は使用できません。 {{< /callout >}} ## ARRAY_LENGTH `ARRAY_LENGTH()`は、配列全体がNULLでなければ、宣言された要素数(cardinality)を返します。 ```sql SELECT ID, ARRAY_LENGTH(CHANNELS) FROM SENSOR_ARRAY; ``` すべての要素がNULLでもcardinalityを返します。配列全体がNULLならNULLを返します。 型情報のない`ARRAY_LENGTH(NULL)`は引数の型を決定できないため、エラーになります。 ## ARRAY全体のCAST 同じcardinalityの数値`ARRAY`は、`CAST(array_expression AS TYPE[N])`で全要素の型を変換できます。 ```sql SELECT CAST(CHANNELS AS INT32[4]) FROM SENSOR_ARRAY; SELECT CAST(AMOUNTS AS DECIMAL(10,2)[2]) FROM SENSOR_ARRAY; ``` - 入力は数値`ARRAY`またはSQL `NULL`である必要があります。 - 変換先には、このドキュメントの数値要素型と別名を使用できます。 - 入力と変換先のcardinalityは完全に一致する必要があります。 - 配列全体のNULLと各要素のNULLは変換後も保持します。 - 各非NULL要素には、対応するスカラーCASTの数値変換規則を適用します。 - `DECIMAL[N]`は`DECIMAL(10,0)[N]`、`DECIMAL(p)[N]`は`DECIMAL(p,0)[N]`として扱います。 - 1つでも範囲や変換規則に違反する要素があれば、CASTとそれを含む文全体が失敗します。 プリペアドステートメントでは、CASTの変換先がパラメーターと結果の要素型、cardinality、 DECIMALの精度と小数桁数を決定します。同じ文にARRAY値、配列全体のNULL、一部の位置のみを指定する 疎なARRAYを再バインドできます。 ```sql SELECT CAST(? AS INT32[3]); SELECT CAST(? AS DECIMAL(12,4)[3]); ``` `CASE`や`UNION ALL`でARRAY結果を組み合わせるには、要素型、cardinality、DECIMALのprecision/scaleが すべて一致する必要があります。異なる場合は、明示的に同じARRAY型へCASTしてから組み合わせます。 次の変換はサポートしません。 - スカラー値をARRAYへ展開 - ARRAYをスカラーへ縮小 - 異なるcardinality間の埋め合わせや切り詰め - 文字列、日付、IP、BINARY、JSONのARRAYを変換先に指定 構文、数値変換、エラー規則の詳細は[CAST関数](../../functions/functions-full/#cast)を参照してください。 ## 比較と式 `ARRAY`全体に`=`、`<>`、`IS NULL`、`IS NOT NULL`を使用できます。同じ位置のNULL要素同士は、 `ARRAY`全体の等値比較では一致します。配列全体のNULLの比較は通常のSQL NULL規則に従います。 ```sql SELECT ID FROM SENSOR_ARRAY WHERE CHANNELS = [1.5, NULL, 3.5, 4.5] OR CHANNELS[1] IS NULL; ``` 要素の式は、対応する数値型の通常の式や述語で使用できます。ただし、`ARRAY`全体を次の場所で 使用することはできません。 - `DISTINCT` - `GROUP BY` - `ORDER BY` - 集約関数のDISTINCT引数 ## VIEW、INSERT SELECT、CASE、upsert VIEWと`INSERT ... SELECT`は、要素型、cardinality、`DECIMAL`のprecisionとscaleを保持します。 異なる数値`ARRAY`型へ取り込む場合は各要素を対象型へ変換し、1つでも変換できなければ文全体が失敗します。 INSERTとUPDATEの`CASE`結果にも、対象`ARRAY`の規則を適用します。 ```sql UPDATE SENSOR_LOOKUP SET AMOUNTS = CASE WHEN ID = 1 THEN [12345678.1234, NULL] ELSE AMOUNTS END WHERE ID = 1; ``` LOOKUPやVOLATILEテーブルの重複キーupsertでも、直接の`ARRAY`、定数`CASE`、プリペアドステートメントの 配列全体のバインドに同じ変換規則を適用します。upsertの右辺の式で既存行の列を参照できるかどうかは、 各テーブルの既存のポリシーに従います。 ## メタデータと表示形式 `DESC`とSQLエクスポートには正規の宣言形式を表示します。 ```sql DESC SENSOR_ARRAY; ``` システムカタログは`ARRAY`型コード、cardinality、precision、scaleを個別のフィールドに保持します。 SQLCLIまたはODBCの`SQLColumns()`は次の情報を返します。 - `DATA_TYPE`: `SQL_MACHBASE_ARRAY` - `TYPE_NAME`: `INT32[3]`、`DECIMAL(12,4)[2]`などの正規の宣言形式 - `COLUMN_SIZE`: cardinality - `DECIMAL_DIGITS`: `DECIMAL`要素のscale `machsql`、汎用ODBCのテキスト参照、Goの`database/sql`など文字列結果が必要な経路では、 `[value,null,value]`形式を使用します。小文字の`null`は要素のNULLで、列結果のSQL `NULL`は配列全体のNULLです。 ## SDKでのARRAYの読み書き 次の例では、共通のテーブルとデータを使用します。 ```sql CREATE LOG TABLE SDK_ARRAY_SAMPLE ( ID INTEGER, A_I32 INT32[3], A_U64 UINT64[3], A_DEC DECIMAL(12,4)[3] ); INSERT INTO SDK_ARRAY_SAMPLE VALUES (1, [1,NULL,-3], [1,NULL,18446744073709551614], [1.2500,NULL,-3.7500]); INSERT INTO SDK_ARRAY_SAMPLE (ID) VALUES (2); ``` 配列全体のNULLは各SDKのNULL値、要素のNULLはコレクション内部のNULL値で表します。 `UINT64`と`DECIMAL`には、SDKが提供する精度を保持できる型を使用してください。 ### C SQLCLI 型付きフェッチには`SQL_C_MACHBASE_ARRAY`と`SQL_MACHBASE_ARRAY_DESC`を使用します。 ```c SQLINTEGER values[3] = {0}; SQLLEN elements[3] = {0}; SQLLEN outer = 0; SQL_MACHBASE_ARRAY_DESC array = {0}; array.struct_size = sizeof(array); array.element_c_type = SQL_C_SLONG; array.capacity = 3; array.values = values; array.element_indicators = elements; SQLExecDirect(stmt, (SQLCHAR*)"SELECT A_I32 FROM SDK_ARRAY_SAMPLE WHERE ID=1", SQL_NTS); SQLBindCol(stmt, 1, SQL_C_MACHBASE_ARRAY, &array, sizeof(array), &outer); SQLFetch(stmt); /* outer != SQL_NULL_DATA, array.count == 3, * values[0] == 1, elements[1] == SQL_NULL_DATA, values[2] == -3 */ ``` 配列全体がNULLの場合は`outer == SQL_NULL_DATA`で、`array.count == 0`です。NULL要素を区別するには `element_indicators`を指定します。`DECIMAL`を文字列で取得する場合は`element_c_type = SQL_C_CHAR`と 要素バッファー間の`value_stride`を設定します。 プリペアドINSERTでは`capacity`、`count`、`ColumnSize`に対象のcardinalityを設定します。 ```c array.count = 3; SQLPrepare(stmt, (SQLCHAR*)"INSERT INTO SDK_ARRAY_SAMPLE(ID,A_I32) VALUES(3,?)", SQL_NTS); SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_MACHBASE_ARRAY, SQL_MACHBASE_ARRAY, 3, 0, &array, sizeof(array), &outer); SQLExecute(stmt); ``` 配列全体のNULLの取り込みは`outer = SQL_NULL_DATA`で指定します。ARRAYのパラメーターセット実行は 現在サポートせず、`HYC00`を返します。従来の`SQLAppendBatch`もARRAY型コードがないためARRAYは非対応ですが、 同じSQLSTATEが返される保証はありません。 ### C++ C++ではSQLCLIの記述子ABIをそのまま使用します。バインドからフェッチ完了まで`vector`のアドレスが 変わらないようにサイズを固定してください。 ```cpp std::vector values(3); std::vector indicators(3); SQLLEN outer = 0; SQL_MACHBASE_ARRAY_DESC array{}; array.struct_size = sizeof(array); array.element_c_type = SQL_C_SLONG; array.capacity = values.size(); array.values = values.data(); array.element_indicators = indicators.data(); SQLBindCol(stmt, 1, SQL_C_MACHBASE_ARRAY, &array, sizeof(array), &outer); ``` アプリケーションモデルでは、`std::optional>>`の外側の`optional`で 配列全体のNULLを、内側の`optional`で要素のNULLを表せます。 ### Machbase ODBCと汎用ODBC Machbase専用ヘッダーを使用するODBC Cプログラムは、C SQLCLIと同じARRAY記述子を使用します。 専用型を解釈しない汎用ツールでは、正規のテキスト形式で参照するか、各要素を個別に射影します。 ```sql SELECT ID, A_I32, A_I32[1], A_I32[2], A_I32[3] FROM SDK_ARRAY_SAMPLE ORDER BY ID; ``` ### JDBC JDBCは`java.sql.Array`を返します。`UINT64`は`BigInteger`、`DECIMAL`は`BigDecimal`で保持します。 ```java try (Connection con = DriverManager.getConnection( "jdbc:machbase://127.0.0.1:5656/machbasedb", "SYS", "MANAGER"); Statement st = con.createStatement(); ResultSet rs = st.executeQuery( "SELECT A_I32 FROM SDK_ARRAY_SAMPLE ORDER BY ID")) { rs.next(); java.sql.Array sqlArray = rs.getArray(1); Object[] values = (Object[])sqlArray.getArray(); // [Integer(1), null, Integer(-3)] rs.next(); assert rs.getArray(1) == null && rs.wasNull(); } ``` メタデータのJDBC型は`Types.ARRAY`、precisionはcardinality、`DECIMAL`のscaleは要素のscaleです。 `Connection.createArrayOf()`で作成した値を`PreparedStatement.setArray()`に渡せます。 ### Python PythonはARRAYを`list`、要素のNULLをリスト内の`None`、配列全体のNULLを列自体の`None`として返します。 `UINT64`は任意精度の`int`、`DECIMAL`は`Decimal`です。 ```python from decimal import Decimal from machbaseAPI import connect conn = connect(host="127.0.0.1", port=5656, user="SYS", password="MANAGER") try: rows = conn.cursor(dictionary=True).execute( "SELECT A_I32,A_U64,A_DEC FROM SDK_ARRAY_SAMPLE ORDER BY ID" ).fetchall() assert rows[0]["A_I32"] == [1, None, -3] assert rows[0]["A_U64"][2] == 18446744073709551614 assert rows[0]["A_DEC"][0] == Decimal("1.2500") assert rows[1]["A_I32"] is None finally: conn.close() ``` プリペアド`execute()`と`executemany()`は`list`や`tuple`をARRAYとしてエンコードします。 `cursor.column_metadata`でARRAY型コード、cardinality、`DECIMAL`要素のメタデータを確認できます。 ### Node.js Node.jsはARRAYをJavaScriptの`Array`で返します。`INT64`と`UINT64`は`bigint`、 `DECIMAL`は精度保持のため文字列で返します。 ```javascript const { createConnection } = require('@machbase/ts-client'); const conn = createConnection({ host: '127.0.0.1', port: 5656, user: 'SYS', password: 'MANAGER', }); await conn.connect(); try { const [rows] = await conn.query( 'SELECT A_I32,A_U64,A_DEC FROM SDK_ARRAY_SAMPLE ORDER BY ID', ); console.log(rows[0].A_I32); // [1, null, -3] console.log(rows[0].A_U64); // [1n, null, 18446744073709551614n] console.log(rows[1].A_I32); // null: whole NULL } finally { await conn.end(); } ``` `JSON.stringify()`の前に`bigint`を文字列へ変換してください。`DECIMAL`文字列を`Number`へ強制変換しないでください。 プリペアドステートメントの`getColumns()`で、ARRAYのcardinalityと要素のprecision/scaleメタデータを確認できます。 ### .NET full/legacy provider MachConnector40 full/legacyプロバイダーはARRAYを`object[]`で返します。要素のNULLは配列内の`null`、 配列全体のNULLは`IsDBNull()`で区別します。 ```csharp using Mach.Data.MachClient; using var conn = new MachConnection( "SERVER=127.0.0.1;PORT_NO=5656;UID=SYS;PWD=MANAGER"); conn.Open(); using var cmd = new MachCommand( "SELECT A_I32 FROM SDK_ARRAY_SAMPLE ORDER BY ID", conn); using var reader = cmd.ExecuteReader(); reader.Read(); var values = (object[])reader.GetValue(0); Console.WriteLine((int)values[0]); Console.WriteLine(values[1] is null); reader.Read(); Console.WriteLine(reader.IsDBNull(0)); ``` 各要素は`short`、`ushort`、`int`、`uint`、`long`、`ulong`、`float`、`double`、`decimal`です。 CLRの`decimal`の範囲外の値は、カルチャに依存しない文字列で返します。`GetSchemaTable()`は プロバイダー型、cardinality、要素のscale、`object[]`フィールド型を提供します。 ### Go neo-client この項目は、`neo-client`がMachbase DBMSへ直接接続するSDK経路を扱い、Machbase Neoサーバーは対象外です。 0始まりのARRAY APIは、[`neo-client` PR #17](https://github.com/machbase/neo-client/pull/17)以降の v2モジュールソースにあります。公開v2リリースが指定されるまでは、該当ソースのチェックアウトと `go.work`や`replace`などによる明示的なローカルモジュール接続が必要です。公開v1リリースに 機能が含まれていると仮定しないでください。 ```go import ( "context" "database/sql" "fmt" client "github.com/machbase/neo-client/v2" "github.com/machbase/neo-client/v2/api" ) db, err := sql.Open(client.DefaultDriverName, dsn) if err != nil { return err } defer db.Close() dense, err := api.NewArray(api.SqlTypeInt32, int32(10), nil, int32(30)) if err != nil { return err } if _, err = db.ExecContext(context.Background(), "INSERT INTO SDK_ARRAY_SAMPLE(ID,A_I32) VALUES(3,?)", dense); err != nil { return err } rows, err := db.QueryContext(context.Background(), "SELECT A_I32 FROM SDK_ARRAY_SAMPLE WHERE ID=3") if err != nil { return err } defer rows.Close() for rows.Next() { var raw sql.NullString if err := rows.Scan(&raw); err != nil { return err } fmt.Println(raw.String) // [10,null,30] } return rows.Err() ``` `database/sql`の結果は正規の文字列形式です。`sql.NullString`で配列全体のNULLを確認し、有効な値は `array.Scan(raw.String)`、配列全体のNULLは`array.Scan(nil)`で解析します。元の幅の狭い整数型と `FLOAT`型も保持するには、要素のメタデータから受け取り先を事前に作成します。 `DECIMAL`のprecision/scaleは`NewSparseArrayWithMeta()`で指定します。 `ColumnTypes()`の`DatabaseTypeName()`はARRAY型名を、`DecimalSize()`は`DECIMAL`要素のprecision/scaleを 提供します。現在の`Length()`はエンコードされたペイロードのバイト長であり、cardinalityとして使用しないでください。 標準の`database/sql`メタデータだけではcardinalityを直接取得できません。 ## コマンドラインツールとデータ移動 ### machsql `machsql`は正規の`ARRAY`文字列を出力します。 ```sql SELECT ID, CHANNELS, ARRAY_LENGTH(CHANNELS), CHANNELS[1] FROM SENSOR_ARRAY ORDER BY ID; ``` SQLファイルに保存し、次のように実行できます。 ```bash machsql -s 127.0.0.1 -P 5656 -u SYS -p MANAGER -f array_query.sql ``` ### machloader machloaderのテキスト入出力は正規の`[value,null,value]`形式を使用します。ARRAY内部に区切り文字や 引用符が含まれるため、CSVではARRAYフィールドを囲み文字で囲みます。 ```csv 1,"[1.5,null,3.5,4.5]" ``` 配列全体のNULLと、全要素がNULLの`ARRAY`が相互に変わらないことを、エクスポートと再インポートで確認します。 CSVのテーブル自動作成では`ARRAY`を推論しないため、事前にテーブルを明示的に作成してください。 ### バックアップ、復元、マウント バックアップと復元は、要素型、cardinality、`DECIMAL`のprecision/scale、NULL情報を保持します。 マウント後のクエリも同じ結果とメタデータを提供します。ARRAYを含むデータのバックアップ、復元、マウントは Machbase DBMS 8.7.0環境で実行してください。 ## バージョンとエラー処理 - `ARRAY`型はMachbase DBMS 8.7.0でサポートします。 - ARRAYのSQL要素位置とMachbase専用SDKのpositionは0始まりです。従来の1始まりのSQLやSDK呼び出しでは、各位置を1減らしてください。 - Machbase DBMS 8.7.0サーバーとARRAY機能を含むSDKビルドを併用します。 - 非対応のサーバーやSDKは、ARRAYを他の型へ自動変換せずエラーを返します。 - cardinality、position、要素変換のエラーは文全体を失敗させ、ARRAYの一部だけを保存することはありません。 - アプリケーションでは配列全体のNULLと全要素がNULLの`ARRAY`を別の値として扱ってください。 - このドキュメントはMachbase DBMSのSQLとSDK機能を扱い、Machbase Neo、HTTP、TQL、ILPは対象外です。 --- title: "16.1.3 関数辞典" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/ language: ja kind: section --- # 16.1.3 関数辞典 組み込み関数をカテゴリー別に示します。 | カテゴリー | 説明 | |----------|------| | [集約関数](aggregation/) | COUNT、SUM、AVG、MIN、MAX、STDDEV、FIRST、LASTなどのグループ集約関数 | | [ウィンドウ/系列関数](series/) | ROWNUM、SERIESNUMなどのウィンドウ・系列分析関数 | | [日付/時刻関数](datetime/) | TO_DATE、TO_CHAR、DATE_TRUNC、ADD_TIMEなどの日付・時刻処理関数 | | [JSON関数とJSONドット表記](operators-json/) | JSONデータの抽出・操作関数とメンバーアクセス構文 | | [正規表現関数](regex/) | REGEXP_LIKE、REGEXP_SUBSTRなどの正規表現による検索・変換関数 | | [NEXTVAL関数](nextval/) | LookupテーブルのSequence列用の自動増分値生成関数 | | [ユーザーコンテキスト関数](functions-full/#current-session-user) | CURRENT_USER、SESSION_USER、内部ユーザーIDの参照 | | [完全な関数リファレンス](functions-full/) | 既存の関数とCASTを含む完全な関数リファレンス | ## 共通規則 - 特に記載がない場合、入力値が`NULL`なら結果も`NULL`です。 - 引数の型が一致しない場合は`ERR-02036`または`ERR-02037`エラーが発生します。 --- title: "集約関数" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/aggregation/ language: ja kind: page --- # 集約関数 集約関数は複数行の値から1つの結果を計算します。`GROUP BY`句と併用するとグループ別の集計結果を取得できます。`NULL`値は集計で無視します(COUNT(*)を除く)。 ## クイックリファレンス | 関数 | 構文 | 説明 | |------|------|------| | COUNT | `COUNT(*) / COUNT(col)` | 全行数、またはNULLでない行数 | | SUM | `SUM(col)` | 合計 | | AVG | `AVG(col)` | 平均 | | MIN | `MIN(col)` | 最小値 | | MAX | `MAX(col)` | 最大値 | | STDDEV | `STDDEV(col)` | 標本標準偏差 | | STDDEV_POP | `STDDEV_POP(col)` | 母標準偏差 | | VARIANCE | `VARIANCE(col)` | 標本分散 | | VAR_POP | `VAR_POP(col)` | 母分散 | | FIRST | `FIRST(sort_expr, return_expr)` | ソート基準で最初のレコードの値 | | LAST | `LAST(sort_expr, return_expr)` | ソート基準で最後のレコードの値 | | SUMSQ | `SUMSQ(col)` | 二乗和 | | MEDIAN | `MEDIAN(col)` | 中央値 | | MODE | `MODE(col)` | 最頻値 | | AREA | `AREA(y, x)` | 曲線の下の面積(台形積分) | | SLOPE | `SLOPE(y, x)` | 線形回帰の傾き | | GROUP_CONCAT | `GROUP_CONCAT(col ...)` | グループ内の値を文字列として連結 | | TS_CHANGE_COUNT | `TS_CHANGE_COUNT(col)` | 値の変更回数 | | TOP_K | `TOP_K(col, k)` | 頻度上位k個の値 | | PERCENTILE_CONT | `PERCENTILE_CONT(col, ratio)` | 連続分位点 | | PERCENTILE_DISC | `PERCENTILE_DISC(col, ratio)` | 離散分位点 | | APPROX_PERCENTILE | `APPROX_PERCENTILE(col, ratio)` | 近似分位点 | | CUME_DIST | `CUME_DIST(value, threshold)` | 累積分布比率 | --- ## COUNT 指定列のレコード数を求めます。`COUNT(*)`はNULLを含む全行数を、`COUNT(col)`は列の値がNULLでない行数を返します。 ```sql COUNT(*) COUNT(column_name) ``` ```sql Mach> CREATE LOG TABLE count_table (id1 INTEGER, id2 INTEGER); Mach> INSERT INTO count_table VALUES(1, 1); Mach> INSERT INTO count_table VALUES(2, 2); Mach> INSERT INTO count_table VALUES(null, 4); Mach> SELECT COUNT(*) FROM count_table; COUNT(*) --------- 3 Mach> SELECT COUNT(id1) FROM count_table; COUNT(id1) ----------- 2 ``` --- ## SUM 数値列の合計を返します。 ```sql SUM(column_name) ``` ```sql Mach> SELECT c1, SUM(c2) FROM sum_table GROUP BY c1; c1 SUM(c2) -------------------- 1 6 2 6 3 4 ``` --- ## AVG 数値列の平均値を返します。 ```sql AVG(column_name) ``` ```sql Mach> SELECT id1, AVG(id2) FROM avg_table GROUP BY id1; id1 AVG(id2) --------------------- 1 2 2 2 NULL 4 ``` --- ## MIN 指定した数値列の最小値を返します。 ```sql MIN(column_name) ``` ```sql Mach> SELECT MIN(c1) FROM min_table; MIN(c1) -------- 1 ``` --- ## MAX 指定した数値列の最大値を返します。 ```sql MAX(column_name) ``` ```sql Mach> SELECT MAX(c) FROM max_table; MAX(c) ------- 30 ``` --- ## STDDEV / STDDEV_POP 入力列の標本標準偏差(STDDEV)と母標準偏差(STDDEV_POP)を返します。 ```sql STDDEV(column) STDDEV_POP(column) ``` ```sql Mach> SELECT c2, STDDEV(c1) FROM stddev_table GROUP BY c2; c2 STDDEV(c1) ----------------------- 1 0.707107 2 0.707107 Mach> SELECT c2, STDDEV_POP(c1) FROM stddev_table GROUP BY c2; c2 STDDEV_POP(c1) --------------------------- 1 0.5 2 0.5 ``` --- ## VARIANCE / VAR_POP 標本分散(VARIANCE)と母分散(VAR_POP)を返します。 ```sql VARIANCE(column_name) VAR_POP(column_name) ``` ```sql Mach> SELECT VARIANCE(c1) FROM var_table; VARIANCE(c1) -------------- 0.333333 Mach> SELECT VAR_POP(c1) FROM var_table; VAR_POP(c1) ------------- 0.25 ``` --- ## FIRST / LAST 各グループを`sort_expr`でソートしたとき、最初(FIRST)または最後(LAST)のレコードの`return_expr`値を返します。時系列データの特定時点の値を取得する場合に便利です。 ```sql FIRST(sort_expr, return_expr) LAST(sort_expr, return_expr) ``` ```sql Mach> SELECT group_no, FIRST(id, name) FROM firstlast_table GROUP BY group_no; group_no first(id, name) ---------------------------- 0 John 1 Grey Mach> SELECT group_no, LAST(id, name) FROM firstlast_table GROUP BY group_no; group_no last(id, name) --------------------------- 0 Ryan 1 Kyle ``` --- ## SUMSQ 数値の二乗和を返します。 ```sql SUMSQ(value) ``` ```sql Mach> SELECT c1, SUMSQ(c2) FROM sumsq_table GROUP BY c1; c1 SUMSQ(c2) ---------------------- 1 14 2 41 ``` --- ## MEDIAN 数値式の正確な中央値を返します。 ```sql MEDIAN(value) ``` ```sql SELECT MEDIAN(temp_c) FROM sensor_log; ``` --- ## MODE 入力集合で最も頻度の高い数値(最頻値)を返します。最頻値が複数ある場合は最小の値を返します。 ```sql MODE(value) ``` ```sql SELECT MODE(alarm_code) FROM event_log; ``` --- ## AREA 数値の`(x, y)`点からなる曲線の下の面積を台形積分で計算します。有効な点が2つ未満の場合はNULLを返します。 ```sql AREA(y, x) ``` ```sql SELECT AREA(power_kw, sample_sec) FROM power_log; ``` --- ## SLOPE 数値の`(x, y)`点に対する線形回帰直線の傾きを計算します。`x`の分散が0、または有効なデータが不足する場合はNULLを返します。 ```sql SLOPE(y, x) ``` ```sql SELECT SLOPE(temp_c, sample_sec) FROM sensor_log; ``` --- ## GROUP_CONCAT グループ内の列値を文字列として連結して返します。 {{< callout type="warning" >}} Cluster Editionでは使用できません。 {{< /callout >}} ```sql GROUP_CONCAT( [DISTINCT] column [ORDER BY column [ASC | DESC] [, ...]] [SEPARATOR str_val] ) ``` ```sql Mach> SELECT GROUP_CONCAT(name) FROM concat_table GROUP BY id2; G_NAMES --------- Jack,Jack,Ram Jill,Zara,John Mach> SELECT GROUP_CONCAT(DISTINCT name SEPARATOR '.') FROM concat_table GROUP BY id2; G_NAMES --------- Jack.Ram Jill.Zara.John ``` --- ## TS_CHANGE_COUNT 時刻順に取り込まれた列値の変更回数を返します。VARCHAR型は非対応です。 {{< callout type="warning" >}} Cluster Editionでは使用できません。 {{< /callout >}} ```sql TS_CHANGE_COUNT(column) ``` ```sql Mach> SELECT id, TS_CHANGE_COUNT(ip) FROM ipcount_table GROUP BY id; id TS_CHANGE_COUNT(ip) -------------------------------- 1 4 2 2 ``` --- ## TOP_K 頻度の高い`k`個の数値を`value:count`形式の文字列で返します。頻度の降順、頻度が同じ場合は値の昇順でソートします。 ```sql TOP_K(value, k) ``` ```sql SELECT TOP_K(alarm_code, 3) FROM event_log; -- 結果例: 101:532,205:317,301:90 ``` --- ## PERCENTILE_CONT / PERCENTILE_DISC 正確な分位点を計算する集約関数です。`ratio`は0.0以上1.0以下の定数である必要があります。 - `PERCENTILE_CONT`: ソート済みの隣接値の間を補間します。 - `PERCENTILE_DISC`: 実際の観測値の1つを選択します。 ```sql PERCENTILE_CONT(value, ratio) PERCENTILE_DISC(value, ratio) ``` 短縮形として`P05`、`P10`、`P90`、`P95`関数も提供します。 ```sql SELECT PERCENTILE_CONT(latency_ms, 0.95) AS p95, PERCENTILE_DISC(latency_ms, 0.50) AS p50 FROM api_log; -- 短縮形 SELECT P05(response_ms), P95(response_ms) FROM web_log; ``` --- ## APPROX_PERCENTILE 近似分位点関数です。データ量が非常に多く、わずかな誤差を許容できる場合に便利です。`APPROX_MEDIAN`、`APPROX_P05`、`APPROX_P10`、`APPROX_P90`、`APPROX_P95`の短縮形もあります。 ```sql APPROX_PERCENTILE(value, ratio) APPROX_MEDIAN(value) APPROX_P95(value) ``` ```sql SELECT APPROX_PERCENTILE(latency_ms, 0.95) AS ap95, APPROX_MEDIAN(latency_ms) AS amedian FROM api_log; ``` --- ## CUME_DIST `value`が`threshold`以下の行の累積比率(0.0 ~ 1.0)を返します。ウィンドウ関数ではなく集約関数です。 ```sql CUME_DIST(value, threshold) ``` ```sql SELECT CUME_DIST(latency_ms, 100) FROM api_log; ``` --- title: "ウィンドウ/系列関数" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/series/ language: ja kind: page --- # ウィンドウ/系列関数 このページでは、結果行に番号を付ける`ROWNUM()`と連続区間を区別する`SERIESNUM()`を説明します。 `SERIES BY`は、ソート済みデータ内で条件を連続して満たす区間の分析に使用します。 `LAG()`や`LEAD()`など`OVER`句を使用する関数は、 [ウィンドウ関数構文](../../syntax/window-function-over-syntax/)を参照してください。 ## クイックリファレンス | 関数 | 構文 | 説明 | |------|------|------| | ROWNUM | `ROWNUM()` | SELECT結果の行番号を付与 | | SERIESNUM | `SERIESNUM()` | 行が属する連続区間の番号(同じ区間の行は同じ番号) | --- ## ROWNUM `SELECT`の結果行に連番を付けます。サブクエリやインラインビュー内でも使用できます。インラインビューの選択リストで使用する場合は、外部から参照できるように別名を指定してください。 ```sql ROWNUM() ``` ### 使用できる句 | 使用可能 | 使用不可 | |-----------|----------| | SELECT Target List, GROUP BY, ORDER BY | WHERE, HAVING | `WHERE` / `HAVING`で行番号を使って絞り込むには、インラインビューで`ROWNUM()`を計算し、外側のクエリから参照します。 ```sql -- 先頭2行のみ選択 Mach> SELECT INNER_RANK, c3 AS NAME FROM (SELECT ROWNUM() AS INNER_RANK, * FROM rownum_table) WHERE INNER_RANK < 3; INNER_RANK NAME -------------------------- 1 Fourth Row 2 Third Row ``` ### ORDER BYとの併用 `ORDER BY`を含むクエリをインラインビューにし、外側の`SELECT`で`ROWNUM()`を呼び出すと、ソート順に番号が付きます。 ```sql Mach> SELECT ROWNUM(), c2 AS SORT, c3 AS NAME FROM (SELECT * FROM rownum_table ORDER BY c3); ROWNUM() SORT NAME -------------------------- 1 1 NULL 2 2 John 3 4.3 Micheal 4 3.3 Sarah ``` --- ## SERIESNUM `SERIES BY`句でグループ化された系列で、各レコードが属する系列の番号を返します。`SERIES BY`句を使用しない場合は常に1を返します。戻り値の型は`BIGINT`です。 ```sql SERIESNUM() ``` ```sql Mach> CREATE LOG TABLE T1 (C1 INTEGER, C2 INTEGER); Mach> INSERT INTO T1 VALUES (0, 1); Mach> INSERT INTO T1 VALUES (1, 2); Mach> INSERT INTO T1 VALUES (2, 3); Mach> INSERT INTO T1 VALUES (3, 2); Mach> INSERT INTO T1 VALUES (4, 1); Mach> INSERT INTO T1 VALUES (5, 2); Mach> INSERT INTO T1 VALUES (6, 3); Mach> INSERT INTO T1 VALUES (7, 1); -- C2 > 1を満たす連続区間を系列に分割 Mach> SELECT SERIESNUM(), C1, C2 FROM T1 ORDER BY C1 SERIES BY C2 > 1; SERIESNUM() C1 C2 -------------------- 1 1 2 1 2 3 1 3 2 2 5 2 2 6 3 [5] row(s) selected. ``` - `C1=1,2,3`(C2>1を満たす連続区間)→ 系列1 - `C1=4`(C2=1、条件を満たさない)→ 系列の境界 - `C1=5,6`(C2>1を満たす連続区間)→ 系列2 --- ## SERIES BY句の概要 `SERIES BY`句は`ORDER BY`と併用し、指定した条件を連続して満たす行を1つの系列にまとめます。`SERIESNUM()`で各系列を区別し、集約関数と組み合わせて連続区間別の統計を計算できます。 区間別統計は、内側のクエリで区間番号を生成し、外側のクエリで集計します。 次の例の`threshold`は、比較するしきい値に置き換えてください。 ```sql SELECT series_id, COUNT(*), AVG(value) FROM ( SELECT value, SERIESNUM() AS series_id FROM sensor_log ORDER BY ts SERIES BY value > threshold ) GROUP BY series_id ORDER BY series_id; ``` --- title: "正規表現関数" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/regex/ language: ja kind: page --- # 正規表現関数 MachbaseはPCRE(Perl Compatible Regular Expressions)に基づく正規表現関数を提供します。すべての正規表現関数は`VARCHAR`型の列でのみ動作します。 ## クイックリファレンス | 関数 | 構文 | 説明 | |------|------|------| | REGEXP_LIKE | `REGEXP_LIKE(src, pat [, flag])` | パターンの一致を確認 | | REGEXP_INSTR | `REGEXP_INSTR(src, pat [, pos [, occ [, ret [, flag]]]])` | パターンが一致する位置を返す | | REGEXP_SUBSTR | `REGEXP_SUBSTR(src, pat [, pos [, occ [, flag]]])` | パターンに一致する部分文字列を抽出 | | REGEXP_REPLACE | `REGEXP_REPLACE(src, pat [, repl [, pos [, occ [, flag]]]])` | パターンに一致する文字列を置換 | ### match_param (共通パラメーター) | 値 | 説明 | |----|------| | `'c'` | 大文字小文字を区別(デフォルト) | | `'i'` | 大文字小文字を区別しない | --- ## REGEXP_LIKE 文字列が正規表現パターンに一致するか検査します。主に`WHERE`句で使用し、Boolean(1/0)を返します。 ```sql REGEXP_LIKE(source, pattern) REGEXP_LIKE(source, pattern, match_param) ``` - `source`: 検査する`VARCHAR`列または式 - `pattern`: 定数の`VARCHAR`正規表現 - `match_param`: `'c'`(大文字小文字を区別、デフォルト)または`'i'`(区別しない) ```sql -- 'error'または'warn'を含むメッセージを参照(大文字小文字を区別しない) SELECT * FROM sensor_text WHERE REGEXP_LIKE(message, 'error|warn', 'i'); -- 数字で始まるコードを参照 SELECT * FROM event_log WHERE REGEXP_LIKE(code, '^[0-9]+'); -- メールアドレス形式の検証 SELECT name FROM users WHERE REGEXP_LIKE(email, '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'); ``` --- ## REGEXP_INSTR 正規表現に一致する位置を返します。一致する値がなければ`0`を返します。位置は1始まりです。 ```sql REGEXP_INSTR(source, pattern) REGEXP_INSTR(source, pattern, position) REGEXP_INSTR(source, pattern, position, occurrence) REGEXP_INSTR(source, pattern, position, occurrence, return_pos) REGEXP_INSTR(source, pattern, position, occurrence, return_pos, match_param) ``` | パラメーター | 説明 | |---------|------| | `source` | 検査する`VARCHAR` | | `pattern` | 定数の`VARCHAR`正規表現 | | `position` | 検索開始位置(1以上、デフォルト値: 1) | | `occurrence` | 何番目の一致を探すか(1以上、デフォルト値: 1) | | `return_pos` | `0`: 開始位置、`1`: 一致文字列の直後の位置 | | `match_param` | `'c'`または`'i'` | ```sql -- 最初の'The'の一致直後の位置を返す(大文字小文字を区別しない) SELECT REGEXP_INSTR('TechOnTheNet', 'The', 1, 1, 1, 'i'); -- 結果: 10(一致文字列'The'の直後の位置) ``` --- ## REGEXP_SUBSTR 正規表現に一致する部分文字列を返します。一致する値がなければNULLを返します。 ```sql REGEXP_SUBSTR(source, pattern) REGEXP_SUBSTR(source, pattern, position) REGEXP_SUBSTR(source, pattern, position, occurrence) REGEXP_SUBSTR(source, pattern, position, occurrence, match_param) ``` | パラメーター | 説明 | |---------|------| | `source` | 検査する`VARCHAR` | | `pattern` | 定数の`VARCHAR`正規表現 | | `position` | 検索開始位置(1以上、デフォルト値: 1) | | `occurrence` | 何番目の一致を探すか(1以上、デフォルト値: 1) | | `match_param` | `'c'`または`'i'` | ```sql -- 2番目の母音を抽出(大文字小文字を区別しない) SELECT REGEXP_SUBSTR('TechOnTheNet', 'a|e|i|o|u', 1, 2, 'i'); -- 結果: 'O' -- IPアドレスから最初のオクテットを抽出 SELECT REGEXP_SUBSTR(ip_str, '[0-9]+', 1, 1) FROM log_table; -- ログからエラーコードを抽出 SELECT REGEXP_SUBSTR(message, 'ERR-[0-9]+') FROM event_log; ``` --- ## REGEXP_REPLACE 正規表現に一致する文字列を指定の文字列に置き換えます。 ```sql REGEXP_REPLACE(source, pattern) REGEXP_REPLACE(source, pattern, replacement) REGEXP_REPLACE(source, pattern, replacement, position) REGEXP_REPLACE(source, pattern, replacement, position, occurrence) REGEXP_REPLACE(source, pattern, replacement, position, occurrence, match_param) ``` | パラメーター | 説明 | |---------|------| | `source` | 対象の`VARCHAR` | | `pattern` | 定数の`VARCHAR`正規表現 | | `replacement` | 置換文字列(省略すると一致文字列を削除) | | `position` | 検索開始位置(1以上、デフォルト値: 1) | | `occurrence` | `0`: すべての一致を置換、正数n: n番目の一致のみ置換(デフォルト値: 0) | | `match_param` | `'c'`または`'i'` | ```sql -- 2番目の母音を'Z'に置換(大文字小文字を区別しない) SELECT REGEXP_REPLACE('TechOnTheNet', 'a|e|i|o|u', 'Z', 1, 2, 'i'); -- 結果: 'TechZnTheNet' -- すべての数字を削除 SELECT REGEXP_REPLACE(code, '[0-9]', '') FROM log_table; -- 空白の正規化(連続する空白を1つにする) SELECT REGEXP_REPLACE(message, '\s+', ' ') FROM event_log; ``` --- ## PCRE正規表現の基礎 | パターン | 説明 | 例 | |------|------|------| | `.` | 任意の1文字 | `a.c` → abc, aXc | | `*` | 0回以上の繰り返し | `ab*c` → ac, abc, abbc | | `+` | 1回以上の繰り返し | `ab+c` → abc, abbc | | `?` | 0回または1回 | `colou?r` → color, colour | | `^` | 文字列の先頭 | `^error` | | `$` | 文字列の末尾 | `\.log$` | | `[abc]` | 文字クラス | `[aeiou]` | | `[^abc]` | 否定文字クラス | `[^0-9]` | | `\d` | 数字(`[0-9]`) | `\d+` | | `\w` | 単語文字 | `\w+` | | `\s` | 空白文字 | `\s+` | | `a\|b` | aまたはb | `error\|warn` | | `(abc)` | グループ | `(foo)+` | | `{n,m}` | n~m回の繰り返し | `\d{3,5}` | --- ## SEARCH / ESEARCHとの違い | 機能 | REGEXP_LIKE | SEARCH / ESEARCH | |------|:-----------:|:----------------:| | 適用する型 | `VARCHAR` | `TEXT` (全文検索インデックス) | | 正規表現のサポート | O (PCRE) | X (キーワード検索) | | インデックスの利用 | X | O | | 大量のテキスト | 限定的 | 推奨 | 大量のテキストでキーワード検索を行う場合は、`TEXT`型と`SEARCH`句が性能面で有利です。正規表現のパターン照合が必要な場合は、`VARCHAR`列と`REGEXP_LIKE`を使用します。 --- title: "JSON関数とJSONドット表記" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/operators-json/ language: ja kind: page --- # JSON関数とJSONドット表記 Machbaseは、`JSON`型の列に保存されたデータを操作・参照する関数とJSONドット表記を提供します。 ## クイックリファレンス | 関数/表記 | 構文 | 説明 | |-------------|------|------| | JSONドット表記 | `col.key` | JSONオブジェクトからキーの値を抽出 | | `JSON_EXTRACT` | `JSON_EXTRACT(doc, path)` | JSONパスの値をJSON文字列として抽出 | | `JSON_EXTRACT_STRING` | `JSON_EXTRACT_STRING(doc, path)` | JSONパスの値を文字列として抽出 | | `JSON_EXTRACT_INTEGER` | `JSON_EXTRACT_INTEGER(doc, path)` | JSONパスの値を整数として抽出 | | `JSON_EXTRACT_DOUBLE` | `JSON_EXTRACT_DOUBLE(doc, path)` | JSONパスの値を実数として抽出 | | `JSON_TYPEOF` | `JSON_TYPEOF(doc, path)` | 指定したJSONパスの値の型を確認 | | `JSON_IS_VALID` | `JSON_IS_VALID(json_text)` | JSON文字列の妥当性を確認 | | `JSON_SET` | `JSON_SET(doc, path, scalar)` | JSONパスにスカラー値を設定 | | `JSON_SET_JSON` | `JSON_SET_JSON(doc, path, json_text)` | JSONパスにJSONサブツリーを設定 | | `JSON_REMOVE` | `JSON_REMOVE(doc, path)` | JSONパスのメンバーを削除 | `JSON_TYPEOF`の`path`は必須引数です。JSONドキュメント全体の型は`JSON_TYPEOF(doc, '$')`で確認します。 --- ## JSONドット表記 JSON列の後にドット(`.`)とキー名を付けて、そのキーの値を参照します。 JSONPath文字列を書かずにJSON列のメンバーへアクセスする場合に使用します。 ```sql json_column.key ``` ```sql -- JSON列から特定キーの値を抽出 SELECT data.temperature AS temp FROM sensor_log; -- WHERE句で使用 SELECT * FROM sensor_log WHERE data.status = 'active'; ``` JSONPath文字列を直接指定する場合は、`data -> '$.temperature'`のように`->`演算子を使用します。 上記のJSONドット表記とは区別して記述してください。 --- ## JSON_SET JSONドキュメントの指定パスにSQLスカラー値をJSONスカラーとして保存します。 ```sql JSON_SET(json_doc, path, scalar) ``` - `path`には完全なJSONPath(`$.key.subkey`形式)を使用してください。 - `JSON_SET(..., path, NULL)`はJSONの`null`を保存します。 - JSONドキュメント引数がSQL `NULL`なら、結果はSQL `NULL`です。 - 配列要素の更新(`$.items[0]`)はサポートしません。 ```sql Mach> SELECT JSON_SET('{"ship":{"status":"READY"}}', '$.ship.status', 'DONE') FROM dual; {"ship":{"status":"DONE"}} Mach> SELECT JSON_SET('{"count":0}', '$.count', 42) FROM dual; {"count":42} ``` --- ## JSON_SET_JSON 第3引数をJSON文字列として解析し、オブジェクトまたは配列のサブツリーを保存します。 ```sql JSON_SET_JSON(json_doc, path, json_text) ``` - 第3引数がSQL `NULL`なら、結果はSQL `NULL`です。 - 無効なJSON文字列はエラーになります。 - 配列要素の更新はサポートしません。 ```sql Mach> SELECT JSON_SET_JSON('{"ship":{}}', '$.ship.owner', '{"name":"machbase"}') FROM dual; {"ship":{"owner":{"name":"machbase"}}} Mach> SELECT JSON_SET_JSON('{"tags":{}}', '$.tags.sensors', '[1,2,3]') FROM dual; {"tags":{"sensors":[1,2,3]}} ``` --- ## JSON_REMOVE JSONドキュメントから特定のメンバーまたは下位パスを削除します。 ```sql JSON_REMOVE(json_doc, path) ``` - `path`には完全なJSONPathを使用してください。 - 存在しないパスは何も変更しません。 - `JSON_REMOVE(..., '$')`は許可しません。 - JSONドキュメント引数がSQL `NULL`なら、結果はSQL `NULL`です。 ```sql Mach> SELECT JSON_REMOVE('{"owner":{"name":"machbase","team":"db"}}', '$.owner.team') FROM dual; {"owner":{"name":"machbase"}} Mach> SELECT JSON_REMOVE('{"a":1,"b":2}', '$.a') FROM dual; {"b":2} ``` --- ## JSONデータの挿入例 ```sql -- JSON型の列を含むLOGテーブル CREATE LOG TABLE device_log ( ts DATETIME, data JSON ); -- JSONデータの挿入 INSERT INTO device_log VALUES (NOW, '{"temperature":23.5,"humidity":60,"status":"active"}'); -- JSONドット表記で値を抽出 SELECT ts, data.temperature AS temp FROM device_log WHERE data.status = 'active'; ``` --- ## テーブルタイプ別のJSONサポート状況 | テーブルタイプ | JSON列 | JSON path query | 備考 | |------------|:---------:|:---------------:|------| | TAG | O | O | JSON列とJSON関数をサポート。JSON PKは非対応 | | LOG | O | O | 完全にサポート | | LOOKUP | O | O | 通常の列としてサポート。JSONパスインデックスは非対応 | | VOLATILE | X | X | JSON列の作成不可 | | TRANSACTION | O | O | 完全にサポート | 詳細は[JSON型のテーブルタイプ別サポート範囲](/ja/dbms/lookup-table-usage/json-column-query/)を参照してください。 --- title: "日付/時刻関数" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/datetime/ language: ja kind: page --- # 日付/時刻関数 Machbaseの`DATETIME`型は、1970-01-01 00:00:00 UTCからの経過時間をナノ秒値で内部保存します。日付/時刻関数は、この値を読みやすい形式へ変換したり、算術演算を行ったりします。 ## クイックリファレンス | 関数 | 構文 | 説明 | |------|------|------| | SYSDATE / NOW | `SYSDATE`, `NOW` | 現在のシステム時刻を返す | | TO_DATE | `TO_DATE(str [, fmt])` | 文字列をDATETIMEへ変換 | | TO_DATE_SAFE | `TO_DATE_SAFE(str [, fmt])` | 変換失敗時にNULLを返す | | TO_CHAR | `TO_CHAR(col [, fmt])` | DATETIMEを文字列へ変換 | | ADD_TIME | `ADD_TIME(col, diff)` | 日付/時刻の加減算 | | DATE_TRUNC | `DATE_TRUNC(unit, col [, count])` | 指定単位で時刻を切り捨て | | DATE_BIN | `DATE_BIN(unit, count, col [, origin])` | 指定した基準で時刻をバケット化 | | DAYOFWEEK | `DAYOFWEEK(col)` | 曜日番号を返す(0=日曜日) | | YEAR / MONTH / DAY | `YEAR(col)`, `MONTH(col)`, `DAY(col)` | 年、月、日を抽出 | | FROM_UNIXTIME | `FROM_UNIXTIME(unix_ts)` | Unixタイムスタンプ(32ビット)をDATETIMEへ変換 | | UNIX_TIMESTAMP | `UNIX_TIMESTAMP(col)` | DATETIMEをUnixタイムスタンプ(32ビット)へ変換 | | FROM_TIMESTAMP | `FROM_TIMESTAMP(ns)` | ナノ秒整数をDATETIMEへ変換 | | TO_TIMESTAMP | `TO_TIMESTAMP(col)` | DATETIMEをナノ秒整数へ変換 | --- ## SYSDATE / NOW 現在のシステム時刻を返す疑似列です。`SYSDATE`と`NOW`は同じ値を返します。 ```sql SYSDATE NOW ``` ```sql Mach> SELECT SYSDATE, NOW FROM t1; SYSDATE NOW ------------------------------------------------------------------- 2017-01-16 14:14:53 310:973:000 2017-01-16 14:14:53 310:973:000 ``` --- ## TO_DATE 指定した書式文字列に従って文字列を`DATETIME`型へ変換します。書式を省略すると、デフォルトの`YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn`を使用します。 ```sql TO_DATE(date_string [, format_string]) ``` ```sql Mach> SELECT TO_DATE('2014-12-30 11:22:33 444:555:666'); 2014-12-30 11:22:33 444:555:666 Mach> SELECT TO_DATE('1999-12-31 13:12:32', 'YYYY-MM-DD HH24:MI:SS'); 1999-12-31 13:12:32 000:000:000 Mach> SELECT TO_DATE('1999', 'YYYY'); 1999-01-01 00:00:00 000:000:000 ``` 変換失敗時にエラーではなくNULLを返す`TO_DATE_SAFE()`も提供します。 ```sql Mach> SELECT TO_DATE_SAFE('2016-12-32', 'YYYY-MM-DD'); NULL ``` --- ## TO_CHAR (DATETIME) `DATETIME`列の値を指定形式の文字列へ変換します。書式を省略すると、デフォルトの`YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn`を使用します。 ```sql TO_CHAR(datetime_col [, format_string]) ``` ### 書式文字列 | 書式指定子 | 説明 | |------------|------| | `YYYY` | 4桁の年 | | `YY` | 2桁の年 | | `MM` | 2桁の月(`01~12`) | | `MON` | 月の英語3文字略称(JAN, FEB, ...) | | `DD` | 2桁の日 | | `DAY` | 曜日の英語3文字略称(SUN, MON, ...) | | `IW` | ISO 8601の週番号(`1~53`、月曜日基準) | | `WW` | 年内の週番号(`1~53`、曜日に依存しない) | | `W` | 月内の週番号(`1~5`、曜日に依存しない) | | `HH` | 2桁の時 | | `HH12` | 12時間制の時(`1~12`) | | `HH24` | 24時間制の時(`0~23`) | | `HH2`, `HH3`, `HH6` | 指定単位で時刻を切り捨て | | `MI` | 2桁の分 | | `MI2`, `MI5`, `MI10`, `MI20`, `MI30` | 指定単位で分を切り捨て | | `SS` | 2桁の秒 | | `SS2`, `SS5`, `SS10`, `SS20`, `SS30` | 指定単位で秒を切り捨て | | `AM` | AM/PM | | `mmm` | 3桁のミリ秒(`0~999`) | | `uuu` | 3桁のマイクロ秒(`0~999`) | | `nnn` | 3桁のナノ秒(`0~999`) | ```sql Mach> SELECT TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS') FROM datetime_table; 2014-12-30 11:22:33 2013-11-11 01:02:03 Mach> SELECT TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS mmm.uuu.nnn') FROM datetime_table; 2014-12-30 11:22:33 444.555.666 ``` --- ## ADD_TIME `DATETIME`列に年/月/日/時/分/秒単位の加減算を行います。ミリ秒・マイクロ秒・ナノ秒単位はサポートしません。 ```sql ADD_TIME(column, time_diff_format) ``` `time_diff_format`形式: `"Year/Month/Day Hour:Minute:Second"`(各項目は正数または負数) ```sql -- 1年後 Mach> SELECT ADD_TIME(dt, '1/0/0 0:0:0') FROM t; -- 1時間1分1秒後 Mach> SELECT ADD_TIME(dt, '0/0/0 1:1:1') FROM t; -- 1年1か月1日前 Mach> SELECT ADD_TIME(dt, '-1/-1/-1 0:0:0') FROM t; ``` --- ## DATE_TRUNC `DATETIME`値を指定時間単位に切り捨てて返します。`count`を指定すると、その倍数単位で切り捨てます。 ```sql DATE_TRUNC(field, date_val [, count]) ``` ### 対応する時間単位と最大範囲 | 時間単位 | 最大範囲 | |-----------|----------| | `nanosecond` (`nsec`) | 1,000,000,000 (1秒) | | `microsecond` (`usec`) | 60,000,000 (60秒) | | `millisecond` (`msec`) | 60,000 (60秒) | | `second` (`sec`) | 86,400 (1日) | | `minute` (`min`) | 1,440 (1日) | | `hour` | 24 (1日) | | `day` | 1 | | `week` | 1 (日曜日開始) | | `month` | 1 | | `year` | 1 | ```sql -- 秒単位で切り捨て Mach> SELECT COUNT(*), DATE_TRUNC('second', i2) tm FROM t GROUP BY tm ORDER BY 2; -- 2秒単位で切り捨て Mach> SELECT COUNT(*), DATE_TRUNC('second', i2, 2) tm FROM t GROUP BY tm ORDER BY 2; -- 2分単位で切り捨て(DATE_TRUNC('second', time, 120)と同じ) Mach> SELECT COUNT(*), DATE_TRUNC('minute', ts, 2) tm FROM t GROUP BY tm; ``` --- ## DATE_BIN 基準時刻`origin`を基点に、`DATETIME`値を指定した時間単位と幅のバケットへ割り当てます。`origin`を省略すると、ローカルタイムゾーンの`1970-01-01 00:00:00`を使用します。 ```sql DATE_BIN(field, count, source [, origin]) ``` ```sql -- 2時間バケット(指定したorigin基準) SELECT DATE_BIN('hour', 2, time, TO_DATE('2020-01-01 00:00:00')) FROM log ORDER BY time; -- 3時間バケット(ローカルタイムゾーンの境界基準) SELECT DATE_BIN('hour', 3, ts) FROM t ORDER BY ts; ``` --- ## DAYOFWEEK `DATETIME`値の曜日を整数で返します。 ```sql DAYOFWEEK(date_val) ``` | 戻り値 | 曜日 | |--------|------| | 0 | 日曜日 | | 1 | 月曜日 | | 2 | 火曜日 | | 3 | 水曜日 | | 4 | 木曜日 | | 5 | 金曜日 | | 6 | 土曜日 | ```sql SELECT DAYOFWEEK(dt) FROM log_table; ``` --- ## YEAR / MONTH / DAY 入力`DATETIME`値から年、月、日を抽出して整数で返します。 ```sql YEAR(datetime_col) MONTH(datetime_col) DAY(datetime_col) ``` ```sql Mach> SELECT YEAR(c1), MONTH(c1), DAY(c1) FROM extract_table; year(c1) month(c1) day(c1) --------------------------------- 2001 1 1 ``` --- ## FROM_UNIXTIME / UNIX_TIMESTAMP `FROM_UNIXTIME`は32ビットのUnixタイムスタンプ整数を`DATETIME`へ変換します。`UNIX_TIMESTAMP`は逆に`DATETIME`を32ビットのUnixタイムスタンプへ変換します。 ```sql FROM_UNIXTIME(unix_timestamp_value) UNIX_TIMESTAMP(datetime_value) ``` ```sql Mach> SELECT FROM_UNIXTIME(315540671); 1980-01-01 11:11:11 000:000:000 Mach> INSERT INTO unix_table VALUES (UNIX_TIMESTAMP('2001-01-01')); Mach> SELECT * FROM unix_table; C1 ----------- 978274800 ``` --- ## FROM_TIMESTAMP / TO_TIMESTAMP `FROM_TIMESTAMP`は1970-01-01 00:00:00 UTCからの経過ナノ秒数を表す整数を`DATETIME`へ変換します。 `TO_TIMESTAMP`は逆に`DATETIME`を同じ基準時点からの経過ナノ秒数の整数へ変換します。 基準時点はUTC+09:00では1970-01-01 09:00:00と表示されます。 次の例の日付と時刻はUTC+09:00基準です。 ```sql FROM_TIMESTAMP(nanosecond_time_value) TO_TIMESTAMP(datetime_value) ``` ```sql Mach> SELECT FROM_TIMESTAMP(1562302560007248869); 2019-07-05 13:56:00 007:248:869 Mach> SELECT TO_TIMESTAMP(c1) FROM datetime_tbl; to_timestamp(c1) ----------------------- 1262308210000000000 ``` ナノ秒単位の算術演算例: ```sql -- 現在時刻の1ms(1,000,000 ns)前 SELECT FROM_TIMESTAMP(SYSDATE - 1000000) FROM t; ``` --- title: "NEXTVAL関数" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/nextval/ language: ja kind: page --- # NEXTVAL関数 `NEXTVAL`は、LOOKUPテーブルのSEQUENCE列の次の自動増分値を`INT64`で返します。 `INSERT`の値の式でのみ使用できます。 ## 構文 ```sql NEXTVAL(sequence_column) ``` - `sequence_column`は`PROPERTY(SEQUENCE=...)`プロパティで作成された列である必要があります。 - `INSERT`以外の文脈(SELECT、WHEREなど)では使用できません。 - 引数は正確に1つで、同じINSERT対象テーブルのSEQUENCE列を指定します。 --- ## Sequence列の作成 SEQUENCE列は、LOOKUPテーブルの`LONG`または`INT64`列でサポートします。 `PROPERTY(SEQUENCE=1)`は開始値を1に指定します。 ```sql CREATE LOOKUP TABLE seq_lookup ( id LONG PROPERTY(SEQUENCE=1) PRIMARY KEY, name VARCHAR(64) ); ``` --- ## NEXTVALの使用 ```sql -- NEXTVALで自動増分IDを挿入 INSERT INTO seq_lookup (id, name) VALUES (NEXTVAL(id), 'sensor-a'); INSERT INTO seq_lookup (id, name) VALUES (NEXTVAL(id), 'sensor-b'); INSERT INTO seq_lookup (id, name) VALUES (NEXTVAL(id), 'sensor-c'); -- 結果の確認 SELECT * FROM seq_lookup; id name ---------- 1 sensor-a 2 sensor-b 3 sensor-c DROP TABLE seq_lookup; ``` --- ## 注意事項 - `NEXTVAL`は`INSERT`文でのみ使用できます。 - SEQUENCE列は**LOOKUPテーブル**専用です。TAG、LOG、VOLATILE、TRANSACTIONテーブルでは使用できません。 - `LONG`・`INT64`以外の型、通常の列、`SELECT`・`WHERE`からの呼び出しはエラーです。 - Sequence番号はトランザクションのロールバックやエラー発生後も再利用されない場合があり、欠番が生じることがあります。 - DDLの詳細は[DDL - Sequence Column](../../syntax/)を参照してください。 --- title: "完全な関数リファレンス" url: https://docs.machbase.com/ja/dbms/reference/sql/functions/functions-full/ language: ja kind: page --- # 完全な関数リファレンス ## エラー処理 | エラーの種類 | コード | 発生条件 | |---|---|---| | 引数の型エラー | `ERR-02036`, `ERR-02037` | 非数値を渡した場合、または`PI`に引数を渡した場合 | | 実行エラー | `ERR-02317` | `SQRT`への負数入力、`MOD`の0除算、`LOG`の無効な底/値、`EXP`/`POWER`の範囲超過など | 入力が`NULL`なら結果も`NULL`です。 ## ABS 数値列の絶対値を実数で返します。 ```sql ABS(column_expr) ``` ```sql Mach> CREATE LOG TABLE abs_table (c1 INTEGER, c2 DOUBLE, c3 VARCHAR(10)); Created successfully. Mach> INSERT INTO abs_table VALUES(1, 1.0, ''); 1 row(s) inserted. Mach> INSERT INTO abs_table VALUES(2, 2.0, 'sqltest'); 1 row(s) inserted. Mach> INSERT INTO abs_table VALUES(3, 3.0, 'sqltest'); 1 row(s) inserted. Mach> SELECT ABS(c1), ABS(c2) FROM abs_table; SELECT ABS(c1), ABS(c2) from abs_table; ABS(c1) ABS(c2) ----------------------------------------------------------- 3 3 2 2 1 1 [3] row(s) selected. ``` ## ADD_TIME DATETIME列に年/月/日/時/分/秒単位の加減算を行います。ミリ秒、マイクロ秒、ナノ秒単位はサポートしません。Diffの形式は`"Year/Month/Day Hour:Minute:Second"`で、各項目は正数または負数を使用できます。 ```sql ADD_TIME(column,time_diff_format) ``` ```sql Mach> CREATE LOG TABLE add_time_table (id INTEGER, dt DATETIME); Created successfully. Mach> INSERT INTO add_time_table VALUES(1, TO_DATE('1999-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO add_time_table VALUES(2, TO_DATE('2000-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO add_time_table VALUES(3, TO_DATE('2012-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO add_time_table VALUES(4, TO_DATE('2013-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO add_time_table VALUES(5, TO_DATE('2014-12-30 11:22:33 444:555:666')); 1 row(s) inserted. Mach> INSERT INTO add_time_table VALUES(6, TO_DATE('2014-12-30 23:22:33 444:555:666')); 1 row(s) inserted. Mach> SELECT ADD_TIME(dt, '1/0/0 0:0:0') FROM add_time_table; ADD_TIME(dt, '1/0/0 0:0:0') ---------------------------------- 2015-12-30 23:22:33 444:555:666 2015-12-30 11:22:33 444:555:666 2014-11-11 01:02:03 004:005:006 2013-11-11 01:02:03 004:005:006 2001-11-11 01:02:03 004:005:006 2000-11-11 01:02:03 004:005:006 [6] row(s) selected. Mach> SELECT ADD_TIME(dt, '0/0/0 1:1:1') FROM add_time_table; ADD_TIME(dt, '0/0/0 1:1:1') ---------------------------------- 2014-12-31 00:23:34 444:555:666 2014-12-30 12:23:34 444:555:666 2013-11-11 02:03:04 004:005:006 2012-11-11 02:03:04 004:005:006 2000-11-11 02:03:04 004:005:006 1999-11-11 02:03:04 004:005:006 [6] row(s) selected. Mach> SELECT ADD_TIME(dt, '1/1/1 0:0:0') FROM add_time_table; ADD_TIME(dt, '1/1/1 0:0:0') ---------------------------------- 2016-01-31 23:22:33 444:555:666 2016-01-31 11:22:33 444:555:666 2014-12-12 01:02:03 004:005:006 2013-12-12 01:02:03 004:005:006 2001-12-12 01:02:03 004:005:006 2000-12-12 01:02:03 004:005:006 [6] row(s) selected. Mach> SELECT ADD_TIME(dt, '-1/0/0 0:0:0') FROM add_time_table; ADD_TIME(dt, '-1/0/0 0:0:0') ---------------------------------- 2013-12-30 23:22:33 444:555:666 2013-12-30 11:22:33 444:555:666 2012-11-11 01:02:03 004:005:006 2011-11-11 01:02:03 004:005:006 1999-11-11 01:02:03 004:005:006 1998-11-11 01:02:03 004:005:006 [6] row(s) selected. Mach> SELECT ADD_TIME(dt, '0/0/0 -1:-1:-1') FROM add_time_table; ADD_TIME(dt, '0/0/0 -1:-1:-1') ---------------------------------- 2014-12-30 22:21:32 444:555:666 2014-12-30 10:21:32 444:555:666 2013-11-11 00:01:02 004:005:006 2012-11-11 00:01:02 004:005:006 2000-11-11 00:01:02 004:005:006 1999-11-11 00:01:02 004:005:006 [6] row(s) selected. Mach> SELECT ADD_TIME(dt, '-1/-1/-1 0:0:0') FROM add_time_table; ADD_TIME(dt, '-1/-1/-1 0:0:0') ---------------------------------- 2013-11-29 23:22:33 444:555:666 2013-11-29 11:22:33 444:555:666 2012-10-10 01:02:03 004:005:006 2011-10-10 01:02:03 004:005:006 1999-10-10 01:02:03 004:005:006 1998-10-10 01:02:03 004:005:006 [6] row(s) selected. Mach> SELECT * FROM add_time_table WHERE dt > ADD_TIME(TO_DATE('2014-12-30 11:22:33 444:555:666'), '-1/-1/-1 0:0:0'); ID DT ----------------------------------------------- 6 2014-12-30 23:22:33 444:555:666 5 2014-12-30 11:22:33 444:555:666 [2] row(s) selected. Mach> SELECT * FROM add_time_table WHERE dt > ADD_TIME(TO_DATE('2014-12-30 11:22:33 444:555:666'), '-1/-2/-1 0:0:0'); ID DT ----------------------------------------------- 6 2014-12-30 23:22:33 444:555:666 5 2014-12-30 11:22:33 444:555:666 4 2013-11-11 01:02:03 004:005:006 [3] row(s) selected. Mach> SELECT ADD_TIME(TO_DATE('2000-12-01 00:00:00 000:000:001'), '-1/0/0 0:0:-1') FROM add_time_table; ADD_TIME(TO_DATE('2000-12-01 00:00:00 000:000:001'), '-1/0/0 0:0:-1') ------------------------------------------ 1999-11-30 23:59:59 000:000:001 1999-11-30 23:59:59 000:000:001 1999-11-30 23:59:59 000:000:001 1999-11-30 23:59:59 000:000:001 1999-11-30 23:59:59 000:000:001 1999-11-30 23:59:59 000:000:001 [6] row(s) selected. Mach> SELECT * FROM add_time_table WHERE dt > ADD_TIME(TO_DATE('2014-12-30 11:22:33 444:555:666'), '-1/-2/-1 0:0:0'); ID DT ----------------------------------------------- 6 2014-12-30 23:22:33 444:555:666 5 2014-12-30 11:22:33 444:555:666 4 2013-11-11 01:02:03 004:005:006 [3] row(s) selected. ``` ## APPROX_PERCENTILE {#approx_percentile-family} ``` APPROX_PERCENTILE APPROX_MEDIAN APPROX_P05 APPROX_P10 APPROX_P90 APPROX_P95 ``` これらの関数は、元の値をすべてソートせず、サイズを制限した要約情報を保持して分位点を近似します。入力データ量が非常に多く、わずかな誤差を許容できる場合に便利です。 ```sql APPROX_PERCENTILE(value, ratio) APPROX_MEDIAN(value) APPROX_P05(value) APPROX_P10(value) APPROX_P90(value) APPROX_P95(value) ``` - `value`は数値型である必要があります。 - `ratio`は`0.0`以上`1.0`以下の定数である必要があります。 - 戻り値の型は`DOUBLE`です。 - `NULL`値は無視します。 `APPROX_MEDIAN(value)`は近似中央値です。`APPROX_P05`、`APPROX_P10`、`APPROX_P90`、`APPROX_P95`はよく使う分位点の短縮形です。 ```sql SELECT APPROX_PERCENTILE(latency_ms, 0.95) AS ap95, APPROX_MEDIAN(latency_ms) AS amedian, APPROX_P05(latency_ms) AS ap05 FROM api_log; ``` ## ARRAY_LENGTH `ARRAY_LENGTH(array_value)`は非NULLの`ARRAY`の宣言された要素数(cardinality)を返します。 ```sql SELECT ARRAY_LENGTH(ARRAY[10, NULL, 30]); -- 3 ``` 全要素がNULLでもcardinalityを返します。配列全体がNULLならNULLを返し、型情報のない`ARRAY_LENGTH(NULL)`はエラーになります。ARRAYの構文と制約の詳細は[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ## ARRAY_SPARSE `ARRAY_SPARSE`は固定長`ARRAY`で値のある位置だけを指定します。位置は0始まりで、省略した位置は要素のNULLになります。 ```sql -- 対象列で型とcardinalityを決定します。 INSERT INTO sensor_array (id, channels) VALUES (1, ARRAY_SPARSE(0 => 10, 3 => 40)); -- 対象列のない式では型とcardinalityを明示します。 SELECT ARRAY_SPARSE(INT32[4], 0 => 10, 3 => 40); -- 角括弧の省略形は最大position + 1からcardinalityを推論します。 SELECT [1 => 12, 33 => 23]; ``` 角括弧の省略形は、対象ARRAYがあればその型とcardinalityを使用します。単独の式では密なARRAYと同じ共通数値型を使用し、最大positionに1を加えてcardinalityを決定します。対象列のない全要素NULLの疎な配列、重複したposition、範囲外のpositionはエラーです。取り込み方法とSDKの疎なオブジェクトは[Sparse ARRAYと選択列Append API](/ja/dbms/development-tools-integration/data-input-load-export/array-append/)を参照してください。 ## AREA {#area} `AREA(y, x)`は数値の`(x, y)`点からなる曲線の下の面積を正確に計算する集約関数です。 ```sql AREA(y, x) ``` - 両方の引数が数値型である必要があります。 - どちらかが`NULL`の行は無視します。 - 有効な点が2つ未満なら結果は`NULL`です。 - 戻り値の型は`DOUBLE`です。 ```sql SELECT AREA(power_kw, sample_sec) FROM power_log; ``` ## AVG 数値列の平均値を返す集約関数です。 ```sql AVG(column_name) ``` ```sql Mach> CREATE LOG TABLE avg_table (id1 INTEGER, id2 INTEGER); Created successfully. Mach> INSERT INTO avg_table VALUES(1, 1); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(1, 2); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(1, 3); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(2, 1); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(2, 2); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(2, 3); 1 row(s) inserted. Mach> INSERT INTO avg_table VALUES(null, 4); 1 row(s) inserted. Mach> SELECT id1, AVG(id2) FROM avg_table GROUP BY id1; id1 AVG(id2) ------------------------------------------- 2 2 NULL 4 1 2 ``` ## BITAND / BITOR 2つの整数値を64ビット符号付き整数へ変換し、ビット単位のAND/OR演算の結果を返します。入力は整数型である必要があり、出力も64ビット符号付き整数です。 0未満の整数ではプラットフォームによって結果が異なる場合があるため、uintegerとushort型のみの使用を推奨します。 ```sql BITAND (, ) BITOR (, ) ``` ```sql Mach> CREATE LOG TABLE bit_table (i1 INTEGER, i2 UINTEGER, i3 FLOAT, i4 DOUBLE, i5 SHORT, i6 VARCHAR(10)); Created successfully. Mach> INSERT INTO bit_table VALUES (-1, 1, 1, 1, 2, 'aaa'); 1 row(s) inserted. Mach> INSERT INTO bit_table VALUES (-2, 2, 2, 2, 3, 'bbb'); 1 row(s) inserted. Mach> SELECT BITAND(i1, i2) FROM bit_table; BITAND(i1, i2) ----------------------- 2 1 [2] row(s) selected. Mach> SELECT * FROM bit_table WHERE BITAND(i2, 1) = 1; I1 I2 I3 I4 I5 I6 --------------------------------------------------------------------------------------------------------------- -1 1 1 1 2 aaa [1] row(s) selected. Mach> SELECT BITOR(i5, 1) FROM bit_table WHERE BITOR(i5, 1) = 3; BITOR(i5, 1) ----------------------- 3 3 [2] row(s) selected. Mach> SELECT * FROM bit_table WHERE BITOR(i2, 1) = 1; I1 I2 I3 I4 I5 I6 --------------------------------------------------------------------------------------------------------------- -1 1 1 1 2 aaa [1] row(s) selected. Mach> SELECT * FROM bit_table WHERE BITAND(i3, 1) = 1; I1 I2 I3 I4 I5 I6 --------------------------------------------------------------------------------------------------------------- [ERR-02037 : Function [BITAND] argument data type is mismatched.] [0] row(s) selected. Mach> SELECT * FROM bit_table WHERE BITAND(i4, 1) = 1; I1 I2 I3 I4 I5 I6 --------------------------------------------------------------------------------------------------------------- [ERR-02037 : Function [BITAND] argument data type is mismatched.] [0] row(s) selected. Mach> SELECT BITAND(i5, 1) FROM bit_table WHERE BITAND(i5, 1) = 1; BITAND(i5, 1) ----------------------- 1 [1] row(s) selected. Mach> SELECT * FROM bit_table WHERE BITOR(i6, 1) = 1; I1 I2 I3 I4 I5 I6 --------------------------------------------------------------------------------------------------------------- [ERR-02037 : Function [BITOR] argument data type is mismatched.] [0] row(s) selected. Mach> SELECT BITOR(i1, i2) FROM bit_table; BITOR(i1, i2) ----------------------- -2 -1 [2] row(s) selected. Mach> SELECT BITAND(i1, i3) FROM bit_table; BITAND(i1, i3) ----------------------- [ERR-02037 : Function [BITAND] argument data type is mismatched.] [0] row(s) selected. Mach> SELECT BITOR(i1, i6) FROM bit_table; BITOR(i1, i6) ----------------------- [ERR-02037 : Function [BITOR] argument data type is mismatched.] [0] row(s) selected. ``` ## CAST Machbase 8.7.0以降でサポート `CAST`は値、列、式を指定したデータ型へ明示的に変換します。`SELECT`、述語、`CASE`、`UNION ALL`、VIEW定義、プリペアドステートメントで使用できます。 ### 構文 ```sql CAST(expression AS data_type) CAST(expression AS data_type(length)) CAST(expression AS DECIMAL(precision[, scale])) CAST(array_expression AS numeric_type[cardinality]) CAST(array_expression AS DECIMAL(precision[, scale])[cardinality]) ``` - `expression`は変換する値、列、SQL式です。 - `array_expression`は数値`ARRAY`またはSQL `NULL`です。 - `data_type`は次の表の変換先の型または別名です。 - 型名は大文字小文字を区別しません。 - `length`、`precision`、`scale`は変換先の型で許可する場合のみ指定できます。 - ARRAYの入力と変換先の`cardinality`は完全に一致する必要があります。 ### 対応する型と別名 | 分類 | 変換先の型 | 使用できる名前 | |------|-----------|---------------------| | 符号付き整数 | 16ビット | `INT16`, `SHORT` | | | 32ビット | `INT32`, `INT`, `INTEGER` | | | 64ビット | `INT64`, `LONG` | | 符号なし整数 | 16ビット | `UINT16`, `USHORT` | | | 32ビット | `UINT32`, `UINTEGER` | | | 64ビット | `UINT64`, `ULONG` | | 実数 | 単精度・倍精度 | `FLOAT`, `DOUBLE` | | 固定小数点 | DECIMAL | `DECIMAL`, `NUMERIC`, `DEC`, `FIXED`, `NUMBER` | | 文字 | 固定長・可変長 | `CHAR`, `VARCHAR` | | 文字LOB | テキスト | `TEXT`, `CLOB` | | 日付と時刻 | ナノ秒精度 | `DATETIME` | | ネットワークアドレス | IPアドレス | `IPV4`, `IPV6` | | バイナリ | バイナリ・バイナリLOB | `BINARY`, `BLOB` | | ドキュメント | JSON | `JSON` | 同じ行の名前は同じ型として動作します。例えば`INTEGER`、`INT`、`INT32`はいずれも32ビット符号付き整数です。結果列の型メタデータには標準型名が表示される場合があります。 ### 長さと精度 #### CHAR, VARCHAR, BINARY | 型 | 長さ省略時のデフォルト値 | 許容する長さ | 長さ超過時の処理 | |------|-------------------:|-----------|----------------| | `CHAR(n)` | 1 byte | 1~32,767 byte | 先頭から`n` byteを保持 | | `VARCHAR(n)` | 32,767 byte | 1~32,767 byte | 先頭から`n` byteを保持 | | `BINARY(n)` | 1 byte | 1~67,108,864 byte | 先頭から`n` byteを保持 | 長さは文字数ではなくバイト数です。UTF-8文字列の変換ではマルチバイト文字が途中で切れる場合があるため、十分な長さを指定してください。`CHAR`は余った領域を空白で埋めません。`CAST(... AS CHAR(n))`の結果メタデータは現在`VARCHAR(n)`と表示されます。 ```sql SELECT '[' || CAST('abc' AS CHAR) || ']' AS char_default; -- [a] SELECT '[' || CAST('abc' AS CHAR(5)) || ']' AS char_value; -- [abc](空白を追加しない) SELECT CAST('abcdef' AS VARCHAR(3)) AS varchar_value; -- abc SELECT CAST('414243' AS BINARY(2)) AS binary_value; -- 4142 ``` `TEXT`、`CLOB`、`BLOB`、`JSON`には`length`を指定できません。これらの型のCAST結果は現在最大32,767 byteをサポートします。許容長を超えて結果の意味が損なわれる場合は、自動で切り詰めずエラーを返します。 #### DECIMAL | 構文 | 解釈 | |------|------| | `DECIMAL` | `DECIMAL(10,0)` | | `DECIMAL(p)` | `DECIMAL(p,0)` | | `DECIMAL(p,s)` | precision `p`, scale `s` | - precision `p`は`1~65`です。 - scale `s`は`0~30`で、precisionを超えることはできません。 - 入力値の小数桁数がscaleを超える場合、中間値を0から遠ざかる方向へ丸めます。 - DECIMAL系以外の型にはprecisionやscaleを指定できません。 ```sql SELECT CAST('12.34' AS DECIMAL(5,2)); -- 12.34 SELECT CAST(123.456 AS NUMERIC(6,2)); -- 123.46 ``` ### NULLと空文字列 - 入力が`NULL`なら変換先の型の`NULL`を返します。 - Machbaseは長さ0の文字列リテラル`''`をSQL `NULL`として扱います。 - `''''`は単一引用符1文字を表す文字列であり、空文字列ではありません。 ```sql SELECT CAST(NULL AS INTEGER) AS null_integer; SELECT CAST('' AS VARCHAR(10)) AS empty_value; SELECT CAST('''' AS VARCHAR(10)) AS quote_value; ``` ### 数値変換 数値型同士の変換や、数値として解釈できる文字列から数値型への変換ができます。 ```sql SELECT CAST('123' AS INTEGER); SELECT CAST('1.25' AS DOUBLE); SELECT CAST(12.9 AS SHORT); -- 12 SELECT CAST(-12.9 AS INTEGER); -- -12 SELECT CAST('9223372036854775806e0' AS LONG); ``` - 実数から整数への変換では、小数部を丸めず0方向へ切り捨てます。 - 整数文字列の指数表記も整数精度を維持して解釈します。 - 変換先の型の範囲外の値はエラーです。 - 符号なし整数への変換では負数の結果は許可しません。小数部を切り捨てた結果が0になる値は、0に変換できます。 - `NaN`、正の無限大、負の無限大は整数へ変換できません。 CASTで生成できる整数の範囲は次のとおりです。各型のNULL予約値は有効な結果範囲には含まれません。 | 変換先の型 | CAST結果の範囲 | |-----------|----------------| | `INT16`, `SHORT` | -32,767~32,767 | | `UINT16`, `USHORT` | 0~65,534 | | `INT32`, `INT`, `INTEGER` | -2,147,483,647~2,147,483,647 | | `UINT32`, `UINTEGER` | 0~4,294,967,294 | | `INT64`, `LONG` | -9,223,372,036,854,775,807~9,223,372,036,854,775,807 | | `UINT64`, `ULONG` | 0~18,446,744,073,709,551,614 | ### 数値ARRAY全体の変換 同じcardinalityの数値`ARRAY`は全要素の型を変換できます。変換先には`INT16`、`UINT16`、`INT32`、`UINT32`、`INT64`、`UINT64`、`FLOAT`、`DOUBLE`、`DECIMAL`と、対応する型の表の数値別名を使用します。 ```sql SELECT CAST([1.9, NULL, -3.9] AS INT32[3]); SELECT CAST([1.235, NULL, -2.345] AS DECIMAL(6,2)[3]); ``` - 配列全体のNULLは変換後も配列全体のNULLです。 - 要素のNULLは同じ位置の要素のNULLとして保持します。 - 各非NULL要素には、対応するスカラー数値CASTの切り捨て、丸め、範囲の規則を適用します。 - 1つでも変換できない要素があればCASTとそれを含む文全体が失敗します。変換済みの一部の要素や行を結果として残しません。 - `DECIMAL[N]`は`DECIMAL(10,0)[N]`、`DECIMAL(p)[N]`は`DECIMAL(p,0)[N]`として扱います。 プリペアドステートメントでもCASTの変換先がパラメーターの要素型、cardinality、DECIMALのprecision/scaleを決定します。同じステートメントに密なARRAY、疎なARRAY、配列全体のNULLを再バインドできます。 ```sql SELECT CAST(? AS INT32[3]); SELECT CAST(? AS DECIMAL(12,4)[3]); ``` スカラーからARRAYへの展開やARRAYからスカラーへの縮小はできません。異なるcardinality間で埋め合わせや切り詰めは行わず、文字列、日付、IP、BINARY、JSONのARRAYを変換先に指定することはできません。 ### 文字列とLOBの変換 数値、日付と時刻、IPアドレス、バイナリ、JSONを文字型へ変換できます。 - 整数とDECIMALは値の10進表現を返します。 - `FLOAT`は最大9桁、`DOUBLE`は最大17桁の有効数字で表します。 - `DATETIME`はセッションの日付形式とタイムゾーンに従って文字列化します。 - `IPV4`と`IPV6`は標準化されたアドレス文字列で表します。 - `BINARY`と`BLOB`は接頭辞なしの大文字16進文字列で表します。 - JSONは元のJSON表現を維持します。 ```sql SELECT CAST(123456 AS VARCHAR(8)); -- 123456 SELECT CAST(CAST('2001:db8::1' AS IPV6) AS VARCHAR(64)); SELECT CAST(CAST('0x00ff10' AS BLOB) AS VARCHAR(8)); -- 00FF10 ``` 文字列から`BINARY`または`BLOB`への変換には、接頭辞なしの偶数長16進数、または`0x`/`0X`接頭辞付きの偶数長16進数を使用します。 ```sql SELECT CAST('414243' AS BINARY(3)); SELECT CAST('0x00ff10' AS BLOB); SELECT CAST(X'414243' AS VARCHAR(6)); ``` `BINARY(n)`は先頭から`n` byteのみを保持します。16進数以外の文字や奇数長の16進数はエラーです。 ### DATETIME変換 文字列または数値を`DATETIME`へ変換できます。 - 文字列はセッションのデフォルトの日付形式とタイムゾーンで解釈します。 - 数値はUnix epochからのナノ秒数として解釈します。 - 数値`-1`はDATETIMEのNULL表示用予約値のため変換できません。 - `DATETIME`から数値へ変換すると、Unix epochからのナノ秒値を返します。 ```sql SELECT CAST('2026-08-15 12:34:56' AS DATETIME); SELECT CAST(1000000000 AS DATETIME); SELECT CAST(CAST(1000000000 AS DATETIME) AS VARCHAR(40)); ``` 同じepoch値でも、セッションのタイムゾーンが異なれば文字列表示される日付と時刻が異なる場合があります。 ### IPV4とIPV6への変換 文字列を`IPV4`または`IPV6`へ変換できます。アドレス全体が正しい形式である必要があります。 ```sql SELECT CAST('127.0.0.1' AS IPV4); SELECT CAST('2001:db8::1' AS IPV6); ``` 無効なアドレスや、変換先の型に一致しないアドレス形式はエラーです。 ### JSON変換 文字列を`JSON`へ変換するには、入力全体が有効なJSONである必要があります。オブジェクトと配列に加えて、JSON文字列、数値、`true`、`false`、`null`も使用できます。 ```sql SELECT CAST('{"ok":true}' AS JSON); SELECT CAST('[1,2,3]' AS JSON); SELECT CAST('"abc"' AS JSON); SELECT CAST(CAST('"abc"' AS JSON) AS VARCHAR(16)); -- "abc" ``` 一部のみ有効なJSONや、末尾にJSON以外の文字が残る入力は変換できません。 ### 式と結果メタデータ CASTは通常のSQL式のため、WHERE条件、`CASE`、`UNION ALL`、VIEW定義でも使用できます。 ```sql SELECT CASE WHEN reading >= 0 THEN CAST(reading AS VARCHAR(32)) ELSE 'invalid' END AS reading_text FROM sensor_log; CREATE VIEW sensor_cast_view AS SELECT CAST(sensor_id AS VARCHAR(100)) AS sensor_id_text, CAST(value AS DECIMAL(12,3)) AS value_decimal FROM sensor_log; ``` プリペアドステートメントでもCAST構文は同じです。入力値は`?`またはSDKの名前付きマーカーで渡し、変換先の型とprecision/scaleはSQLで宣言します。 ```sql SELECT CAST(? AS DECIMAL(12,2)) AS amount; ``` CAST結果の型、バイト長、DECIMALのprecisionとscaleは、結果メタデータとVIEW列情報に反映されます。結果のNULL許容性は入力式のNULL許容性に従います。 `CASE`や`UNION ALL`でARRAY結果を組み合わせるには、要素型、cardinality、DECIMALのprecision/scaleがすべて一致する必要があります。異なる場合は、各結果を明示的に同じARRAY型へCASTしてから組み合わせます。 各SDKは既存の結果メタデータAPIでCAST結果を確認します。CAST専用のSDK APIは提供しません。 | SDK | CAST結果メタデータAPI | |-----|------------------------| | Machbase SQLCLI | `SQLDescribeCol()`, `SQLColAttribute()` | | ODBC | `SQLDescribeCol()`, `SQLColAttribute()` | | JDBC | `ResultSetMetaData` | | Python | `cursor.description` | | Node.js | `ColumnMeta` | | .NET | `GetSchemaTable()` | | Go (native) | native column metadata | | Go (`database/sql`) | `ColumnTypeNullable()` および `ColumnType` API | ### エラーが発生する場合 | 原因 | 例 | |------|-----| | 非対応の変換先の型 | `CAST('1' AS UNKNOWN_TYPE)` | | 許容されないlengthまたはprecision/scale | `CAST('1' AS INTEGER(2))`, `CAST('1' AS DECIMAL(2,3))` | | 数値の範囲超過またはNULL予約値 | `CAST('65535' AS USHORT)` | | 符号なし整数へ変換する負数 | `CAST('-1' AS UINTEGER)` | | 数値へ変換できない文字列 | `CAST('12x' AS INTEGER)` | | スカラーとARRAY間の変換 | `CAST(1 AS INT32[1])`, `CAST([1] AS INT32)` | | ARRAYのcardinality不一致 | `CAST([1, 2] AS INT32[3])` | | 非対応のARRAY変換先の型 | `CAST([1] AS VARCHAR[1])` | | 無効なIPアドレス | `CAST('999.1.1.1' AS IPV4)` | | 奇数長または16進数以外のバイナリ文字列 | `CAST('123' AS BINARY(4))`, `CAST('GG' AS BLOB)` | | 無効なJSON | `CAST('{bad}' AS JSON)` | | 許容サイズを超えるLOBまたはJSON結果 | 32,767 byteを超える `TEXT`, `CLOB`, `BLOB`, `JSON` 結果 | ### 互換性 CAST関数と数値ARRAY全体のCASTはMachbase 8.7.0でサポートします。Standard EditionとCluster Editionで使用できます。Cluster Editionでは、全ノードをCASTに対応した同じバージョンにそろえる必要があります。CASTに非対応の旧ノードとの混在実行はサポートしません。 ### 関連ドキュメント - [SQL構文辞典](../../syntax/) - [データ型辞典](../../types/) - [数値ARRAY型](../../types/array/) - [DECIMALとNUMERIC固定小数点型](../../types/decimal-numeric-fixed-point/) ## COUNT 列のレコード数を求める集約関数です。 ```sql COUNT(column_name) ``` ```sql Mach> CREATE LOG TABLE count_table (id1 INTEGER, id2 INTEGER); Created successfully. Mach> INSERT INTO count_table VALUES(1, 1); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(1, 2); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(1, 3); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(2, 1); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(2, 2); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(2, 3); 1 row(s) inserted. Mach> INSERT INTO count_table VALUES(null, 4); 1 row(s) inserted. Mach> SELECT COUNT(*) FROM count_table; COUNT(*) ----------------------- 7 [1] row(s) selected. Mach> SELECT COUNT(id1) FROM count_table; COUNT(id1) ----------------------- 6 [1] row(s) selected. ``` ## CUME_DIST {#cume_dist} `CUME_DIST(value, threshold)`は、`value`が`threshold`以下の行の累積比率を返します。 ```sql CUME_DIST(value, threshold) ``` - ウィンドウ関数ではなく集約関数です。 - 両方の引数が数値型である必要があります。 - `threshold`は定数である必要があります。 - 戻り値は`0.0`以上`1.0`以下の`DOUBLE`です。 ```sql SELECT CUME_DIST(latency_ms, 100) FROM api_log; ``` ## CURRENT_USER / SESSION_USER / CURRENT_USER_ID / SESSION_USER_ID Machbase 8.7.0以降でサポート 現在のSQL実行に適用される実効権限ユーザーと接続セッションユーザーを、名前または内部IDで参照します。Standard EditionとCluster Editionの両方でサポートします。 | 関数 | 戻り値の型 | 説明 | |---|---|---| | `CURRENT_USER()` | `VARCHAR` | 現在のSQL実行に適用する実効権限ユーザー名 | | `SESSION_USER()` | `VARCHAR` | 現在の接続セッションの認証ユーザー名 | | `CURRENT_USER_ID()` | `INTEGER` | 実効権限ユーザーの内部ID | | `SESSION_USER_ID()` | `INTEGER` | 認証セッションユーザーの内部ID | 4つの関数は引数を取らず、括弧を付けて呼び出します。括弧なしの`CURRENT_USER`キーワードや、`USER`、`SYSTEM_USER`、`CURRENT_SCHEMA`の別名はサポートしません。 ```sql SELECT CURRENT_USER() AS current_name, SESSION_USER() AS session_name, CURRENT_USER_ID() AS current_id, SESSION_USER_ID() AS session_id; ``` 通常のSQLでは、current userとsession userは同じです。 ```text CURRENT_NAME SESSION_NAME CURRENT_ID SESSION_ID SYS SYS 1 1 ``` ### VIEWのユーザーコンテキスト 別のユーザーが所有する定義者権限のVIEWを参照すると、VIEW内部のSQLは所有者の権限で実行されます。 - `CURRENT_USER()`と`CURRENT_USER_ID()`はVIEW所有者を返します。 - `SESSION_USER()`と`SESSION_USER_ID()`はVIEWを呼び出した接続セッションユーザーを返します。 再現可能な所有者/呼び出し元の例は、[VIEW構文](../../syntax/view-syntax/#view-user-context)を参照してください。 ### ユーザーが削除されたアクティブセッション 別の管理者セッションが現在接続中のユーザーを`DROP USER`しても、既存の接続は即座には終了しません。既存セッションの4つの関数は、ログイン時に保持したユーザー名とIDを返し続けます。削除されたユーザーは新規接続できず、`M$SYS_USERS`にも表示されません。 ユーザーIDはMachbaseメタデータの内部識別子です。長期保存する業務用ユーザーキーとして使用せず、現在のメタデータの比較や結合にのみ使用します。 ```sql SELECT COUNT(*) FROM M$SYS_USERS WHERE NAME = SESSION_USER() AND USER_ID = SESSION_USER_ID(); ``` ### エラー 関数に引数を渡すと`ERR-02036`を返します。他の3つの関数も同じ規則を適用します。 ```sql SELECT CURRENT_USER(1); -- ERR-02036: Function [CURRENT_USER] has an invalid argument. ``` 関連するアカウントのライフサイクルは[アカウント管理](../../../../security-access-control/account/)を参照してください。 ## DATE_TRUNC DATETIME値を指定時間単位に切り捨てて返します。 ```sql DATE_TRUNC (field, date_val [, count]) ``` ```sql Mach> CREATE LOG TABLE trunc_table (i1 INTEGER, i2 DATETIME); Created successfully. Mach> INSERT INTO trunc_table VALUES (1, TO_DATE('1999-11-11 1:2:0 4:5:1')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (2, TO_DATE('1999-11-11 1:2:0 5:5:2')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (3, TO_DATE('1999-11-11 1:2:1 6:5:3')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (4, TO_DATE('1999-11-11 1:2:1 7:5:4')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (5, TO_DATE('1999-11-11 1:2:2 8:5:5')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (6, TO_DATE('1999-11-11 1:2:2 9:5:6')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (7, TO_DATE('1999-11-11 1:2:3 10:5:7')); 1 row(s) inserted. Mach> INSERT INTO trunc_table VALUES (8, TO_DATE('1999-11-11 1:2:3 11:5:8')); 1 row(s) inserted. Mach> SELECT COUNT(*), DATE_TRUNC('second', i2) tm FROM trunc_table group by tm ORDER BY 2; COUNT(*) tm -------------------------------------------------------- 2 1999-11-11 01:02:00 000:000:000 2 1999-11-11 01:02:01 000:000:000 2 1999-11-11 01:02:02 000:000:000 2 1999-11-11 01:02:03 000:000:000 [4] row(s) selected. Mach> SELECT COUNT(*), DATE_TRUNC('second', i2, 2) tm FROM trunc_table group by tm ORDER BY 2; COUNT(*) tm -------------------------------------------------------- 4 1999-11-11 01:02:00 000:000:000 4 1999-11-11 01:02:02 000:000:000 [2] row(s) selected. Mach> SELECT COUNT(*), DATE_TRUNC('nanosecond', i2, 2) tm FROM trunc_table group by tm ORDER BY 2; COUNT(*) tm -------------------------------------------------------- 1 1999-11-11 01:02:00 004:005:000 1 1999-11-11 01:02:00 005:005:002 1 1999-11-11 01:02:01 006:005:002 1 1999-11-11 01:02:01 007:005:004 1 1999-11-11 01:02:02 008:005:004 1 1999-11-11 01:02:02 009:005:006 1 1999-11-11 01:02:03 010:005:006 1 1999-11-11 01:02:03 011:005:008 [8] row(s) selected. Mach> SELECT COUNT(*), DATE_TRUNC('nsec', i2, 1000000000) tm FROM trunc_table group by tm ORDER BY 2; //Same as DATE_TRUNC('sec', i2, 1) COUNT(*) tm -------------------------------------------------------- 2 1999-11-11 01:02:00 000:000:000 2 1999-11-11 01:02:01 000:000:000 2 1999-11-11 01:02:02 000:000:000 2 1999-11-11 01:02:03 000:000:000 [4] row(s) selected. ``` 時間単位別に許容する範囲は次のとおりです。 * nanosecond、microsecond、millisecond単位とその略称は5.5.6以降で使用できます。 * weekは日曜日から始まります。 |時間単位|時間範囲| |--|--| |nanosecond (nsec)|1000000000 (1 second)| |microsecond (usec)|60000000 (60 seconds)| |millisecond (msec)|60000 (60 seconds)| |second (sec)|86400 (1 day)| |minute (min)|1440 (1 day)| |hour|24 (1 day)| |day|1| |week|1| |month|1| |year|1| 例えばDATE_TRUNC('second', time, 120)の結果は**2分単位**となり、DATE_TRUNC('minute', time, 2)と同じです。 ## DATE_BIN 指定した基準時刻`origin`を基点に、DATETIME値を`time unit`と`time range`の区間(bin)に割り当てます。 ```sql DATE_BIN(field, count, source [, origin]) ``` - `origin`を指定すると、その時刻を基点にバケットを計算します。 - `origin`を省略すると、サーバーのローカルタイムゾーンの`1970-01-01 00:00:00`を基点に計算します。 - `count`は1以上の整数である必要があります。 `DATE_TRUNC()`や`ROLLUP()`と同じローカルタイムゾーンの境界にそろえるには、`origin`を省略した3引数形式を使用します。サーバーのタイムゾーンに関係なく常に同じ境界を使用するには、4引数形式で`origin`を明示してください。 例えばサーバーのタイムゾーンが`UTC+09:00`の場合、従来は`DATE_BIN(..., 0)`の代わりにタイムゾーン補正済みの`origin`値を直接指定してローカル時刻の境界にそろえる必要がありました。現在は`DATE_BIN(field, count, source)`だけで同じ結果を得られます。 ```sql Mach> CREATE LOG TABLE log (time DATETIME); Created successfully. Mach> INSERT INTO log VALUES (TO_DATE('2000-01-01 00:00:00')); 1 row(s) inserted. Mach> INSERT INTO log VALUES (TO_DATE('2000-01-01 01:00:00')); 1 row(s) inserted. Mach> INSERT INTO log VALUES (TO_DATE('2000-01-01 02:00:00')); 1 row(s) inserted. Mach> INSERT INTO log VALUES (TO_DATE('2000-01-01 03:00:00')); 1 row(s) inserted. Mach> INSERT INTO log VALUES (TO_DATE('2000-01-01 04:00:00')); 1 row(s) inserted. Mach> SELECT TIME, DATE_BIN('hour', 2, time, TO_DATE('2020-01-01 00:00:00')) FROM log ORDER BY time; TIME DATE_BIN('hour', 2, time, TO_DATE('2020-01-01 00:00:00')) --------------------------------------------------------------------------------------------- 2000-01-01 00:00:00 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 01:00:00 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 02:00:00 000:000:000 2000-01-01 02:00:00 000:000:000 2000-01-01 03:00:00 000:000:000 2000-01-01 02:00:00 000:000:000 2000-01-01 04:00:00 000:000:000 2000-01-01 04:00:00 000:000:000 [5] row(s) selected. ``` ローカルタイムゾーンの境界でバケットを計算する例は次のとおりです。 ```sql Mach> CREATE LOG TABLE t3521 (ts DATETIME); Created successfully. Mach> INSERT INTO t3521 VALUES (TO_DATE('2000-01-01 00:30:00')); 1 row(s) inserted. Mach> INSERT INTO t3521 VALUES (TO_DATE('2000-01-01 02:59:59')); 1 row(s) inserted. Mach> INSERT INTO t3521 VALUES (TO_DATE('2000-01-01 03:00:00')); 1 row(s) inserted. Mach> INSERT INTO t3521 VALUES (TO_DATE('2000-01-01 08:00:00')); 1 row(s) inserted. Mach> SELECT ts, DATE_BIN('hour', 3, ts) AS date_bin_3arg, DATE_TRUNC('hour', ts, 3) AS date_trunc_3arg FROM t3521 ORDER BY ts; ts date_bin_3arg date_trunc_3arg ---------------------------------------------------------------------------------------------------- 2000-01-01 00:30:00 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 02:59:59 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 00:00:00 000:000:000 2000-01-01 03:00:00 000:000:000 2000-01-01 03:00:00 000:000:000 2000-01-01 03:00:00 000:000:000 2000-01-01 08:00:00 000:000:000 2000-01-01 06:00:00 000:000:000 2000-01-01 06:00:00 000:000:000 [4] row(s) selected. ``` 時間単位別の許容範囲は次のとおりです。 * nanosecond、microsecond、millisecond単位とその略称は5.5.6以降で使用できます。 * weekは7日と同じです。 |時間単位| |----:| |nanosecond (nsec)| |microsecond (usec)| |millisecond (msec)| |second (sec)| |minute (min)| |hour| |day| |week| |month| |year| ## DAYOFWEEK DATETIME値の曜日を整数で返します。 [TO_CHAR (time, 'DAY')](#to_char)と意味は同じですが、この関数は整数を返します。 ```sql DAYOFWEEK(date_val) ``` 返される整数は、次の表の曜日を表します。 | 戻り値 | 曜日 | |--|--| |0|日曜日| |1|月曜日| |2|火曜日| |3|水曜日| |4|木曜日| |5|金曜日| |6|土曜日| ## DECODE 列値をsearch値と比較し、一致すると対応するreturn値を返します。一致するsearch値がなければdefault値を、defaultを省略した場合はNULLを返します。 ```sql DECODE(column, [search, return],.. default) ``` ```sql Mach> CREATE LOG TABLE decode_table (id1 VARCHAR(11)); Created successfully. Mach> INSERT INTO decode_table VALUES('decodetest1'); 1 row(s) inserted. Mach> INSERT INTO decode_table VALUES('decodetest2'); 1 row(s) inserted. Mach> SELECT id1, DECODE(id1, 'decodetest1', 'result1', 'decodetest2', 'result2', 'DEFAULT') FROM decode_table; id1 DECODE(id1, 'decodetest1', 'result1', 'decodetest2', 'result2', 'DEFAULT') --------------------------------------------------------- decodetest2 result2 decodetest1 result1 [2] row(s) selected. Mach> SELECT id1, DECODE(id1, 'codetest', 2, 99) FROM decode_table; id1 DECODE(id1, 'codetest', 2, 99) ----------------------------------------------- decodetest2 99 decodetest1 99 [2] row(s) selected. Mach> SELECT DECODE(id1, 'decodetest1', 2) FROM decode_table; DECODE(id1, 'decodetest1', 2) -------------------------------- NULL 2 [2] row(s) selected. Mach> SELECT DECODE(id1, 'codetest', 2) FROM decode_table; DECODE(id1, 'codetest', 2) ----------------------------- NULL NULL [2] row(s) selected. ``` ## EXTRACT_* バイナリフレームからビットを抽出する関数群です。`EXTRACT_*`はビッグエンディアン、`EXTRACT_LE_*`はリトルエンディアンを使用します。すべての関数は`BINARY/VARBINARY`を入力に取り、frameがNULLなら結果もNULLです。 **エンディアンモデル** - `EXTRACT_*`: MSB優先(`bit 0`は`byte[0]`のMSB) - `EXTRACT_LE_*`: LSB優先(`bit 0`は`byte[0]`のLSB) - ビットの添字はフレーム全体を基準とする0始まりです。 **共通規則** - 単一ビット: `0 <= bit_pos < frame_bits` - 範囲抽出: `start_bit >= 0`、`1 <= bit_count <= 64`、`start_bit + bit_count <= frame_bits` - `EXTRACT_FLOAT*`は32ビット、`EXTRACT_DOUBLE*`は64ビットを読み取ります。 - 符号付き抽出は2の補数(two's complement)として解釈し、64ビットへ符号拡張します。 - 範囲エラー: `ERR_QP_INVALID_ARG_VALUE`(`ERR-02229`系) - 引数の型エラー: `ERR_QP_FUNCTION_ARG_TYPE` ### EXTRACT_BIT ``` EXTRACT_BIT(frame, bit_pos) / EXTRACT_LE_BIT(frame, bit_pos) → TINYINT ``` 単一ビットを0または1で返します。 ```sql -- frame = 0x80 (1000 0000) SELECT EXTRACT_BIT(frame, 0) AS be_bit0, EXTRACT_LE_BIT(frame, 0) AS le_bit0 FROM t; ``` ### EXTRACT_LONG, EXTRACT_ULONG ``` EXTRACT_ULONG(frame, start_bit, bit_count) → BIGINT UNSIGNED EXTRACT_LE_ULONG(frame, start_bit, bit_count) → BIGINT UNSIGNED EXTRACT_LONG(frame, start_bit, bit_count) → BIGINT EXTRACT_LE_LONG(frame, start_bit, bit_count) → BIGINT ``` 1~64ビットを符号なし整数、または2の補数の整数として読み取ります。 ```sql -- frame = 0x12 34 SELECT EXTRACT_ULONG(frame, 0, 16) AS be_u16, -- 0x1234 EXTRACT_LE_ULONG(frame, 0, 16) AS le_u16 -- 0x3412 FROM t; ``` ### EXTRACT_FLOAT,EXTRACT_DOUBLE ``` EXTRACT_FLOAT(frame, start_bit) → FLOAT EXTRACT_LE_FLOAT(frame, start_bit) → FLOAT EXTRACT_DOUBLE(frame, start_bit) → DOUBLE EXTRACT_LE_DOUBLE(frame, start_bit) → DOUBLE ``` 32/64ビットをIEEE754のfloat/doubleとして再解釈します。指定したビット範囲はframe内に収まる必要があります。 ```sql SELECT EXTRACT_FLOAT(frame, 0) AS be_f32, EXTRACT_LE_FLOAT(frame, 0) AS le_f32, EXTRACT_DOUBLE(frame, 64) AS be_f64, EXTRACT_LE_DOUBLE(frame, 64) AS le_f64 FROM sensor_bin; ``` ### EXTRACT_SCALED_DOUBLE ``` EXTRACT_SCALED_DOUBLE(frame, start_bit, bit_count, signed, scale, offset) → DOUBLE EXTRACT_LE_SCALED_DOUBLE(frame, start_bit, bit_count, signed, scale, offset) → DOUBLE ``` 1~64ビットを、`signed=0`なら符号なし値、`signed=1`なら2の補数の符号付き値として読み取り、`raw * scale + offset`を返します。 ```sql -- 20ビットのセンサー値、scale 0.01、offset -40.0 SELECT EXTRACT_SCALED_DOUBLE(frame, 0, 20, 0, 0.01, -40.0) AS be_value, EXTRACT_LE_SCALED_DOUBLE(frame, 0, 20, 0, 0.01, -40.0) AS le_value FROM t_bin; ``` ## FIRST / LAST 各グループを基準値でソートしたとき、最初または最後のレコードの特定の値を返す集約関数です。 * FIRST: ソート順で最初のレコードの値を返します。 * LAST: ソート順で最後のレコードの値を返します。 ```sql FIRST(sort_expr, return_expr) LAST(sort_expr, return_expr) ``` ```sql Mach> create table firstlast_table (id integer, name varchar(20), group_no integer); Created successfully. Mach> insert into firstlast_table values (1, 'John', 0); 1 row(s) inserted. Mach> insert into firstlast_table values (2, 'Grey', 1); 1 row(s) inserted. Mach> insert into firstlast_table values (5, 'Ryan', 0); 1 row(s) inserted. Mach> insert into firstlast_table values (4, 'Andrew', 0); 1 row(s) inserted. Mach> insert into firstlast_table values (7, 'Kyle', 1); 1 row(s) inserted. Mach> insert into firstlast_table values (6, 'Ross', 1); 1 row(s) inserted. Mach> select group_no, first(id, name) from firstlast_table group by group_no; group_no first(id, name) ------------------------------------- 1 Grey 0 John [2] row(s) selected. Mach> select group_no, last(id, name) from firstlast_table group by group_no; group_no last(id, name) ------------------------------------- 1 Kyle 0 Ryan ``` ## FROM_TIMESTAMP 1970-01-01 00:00:00 UTCからの経過ナノ秒数をdatetime型へ変換します。 TO_TIMESTAMP()は、datetime型を同じ基準時点からの経過ナノ秒数へ変換します。 基準時点はUTC+09:00では1970-01-01 09:00:00と表示されます。次の例の日付と時刻はUTC+09:00基準です。 ```sql FROM_TIMESTAMP(nanosecond_time_value) ``` ```sql Mach> SELECT FROM_TIMESTAMP(1562302560007248869); FROM_TIMESTAMP(1562302560007248869) -------------------------------------- 2019-07-05 13:56:00 007:248:869 ``` `SYSDATE`と`NOW`は現在時刻を表すDATETIME値です。次の例は現在時刻をそのまま変換する場合と、1ミリ秒(1,000,000ナノ秒)を引く場合を示します。 ```sql Mach> select sysdate, from_timestamp(sysdate) from test_tbl; sysdate from_timestamp(sysdate) ------------------------------------------------------------------- 2019-07-05 14:00:59 722:822:443 2019-07-05 14:00:59 722:822:443 [1] row(s) selected. Mach> select sysdate, from_timestamp(sysdate-1000000) from test_tbl; sysdate from_timestamp(sysdate-1000000) ------------------------------------------------------------------- 2019-07-05 14:01:05 130:939:525 2019-07-05 14:01:05 129:939:525 -- 1 ms (1,000,000 ns) の差がある [1] row(s) selected. ``` ## FROM_UNIXTIME 整数で入力した32ビットUNIXTIME値をdatetime型へ変換します。UNIX_TIMESTAMPはdatetimeデータを32ビットUNIXTIME整数へ変換します。 次の例の日付と時刻はUTC+09:00基準です。 ```sql FROM_UNIXTIME(unix_timestamp_value) ``` ```sql Mach> SELECT FROM_UNIXTIME(315540671) FROM TEST; FROM_UNIXTIME(315540671) ---------------------------------- 1980-01-01 11:11:11 000:000:000 Mach> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP('2001-01-01')) FROM unix_table; FROM_UNIXTIME(UNIX_TIMESTAMP('2001-01-01')) ------------------------------------------ 2001-01-01 00:00:00 000:000:000 ``` ## GROUP_CONCAT グループ内の列値を文字列として連結して返す集約関数です。 {{< callout type="warning" >}} Cluster Editionでは使用できません。 {{< /callout >}} ```sql GROUP_CONCAT( [DISTINCT] column [ORDER BY { unsigned_integer | column } [ASC | DESC] [, column ...]] [SEPARATOR str_val] ) ``` * DISTINCT: 重複値は1回のみ連結します。 * ORDER BY: 指定列の値で連結順序をソートします。 * SEPARATOR: 列値の連結に使用する区切り文字列です。デフォルトはカンマ(,)です。 構文に関する注意事項は次のとおりです。 * 指定できる列は1つのみです。複数列を連結する場合は、TO_CHAR()とCONCAT演算子(||)で1つの式にまとめてください。 * ORDER BYには連結対象以外の列も指定でき、複数列の指定も可能です。 * SEPARATORには文字列定数のみ指定でき、文字列列は指定できません。 ```sql Mach> CREATE LOG TABLE concat_table(id1 INTEGER, id2 DOUBLE, name VARCHAR(10)); Created successfully. Mach> INSERT INTO concat_table VALUES (1, 2, 'John'); 1 row(s) inserted. Mach> INSERT INTO concat_table VALUES (2, 1, 'Ram'); 1 row(s) inserted. Mach> INSERT INTO concat_table VALUES (3, 2, 'Zara'); 1 row(s) inserted. Mach> INSERT INTO concat_table VALUES (4, 2, 'Jill'); 1 row(s) inserted. Mach> INSERT INTO concat_table VALUES (5, 1, 'Jack'); 1 row(s) inserted. Mach> INSERT INTO concat_table VALUES (6, 1, 'Jack'); 1 row(s) inserted. Mach> SELECT GROUP_CONCAT(name) AS G_NAMES FROM concat_table GROUP BY id2; G_NAMES ------------------------------------------------------------------------------------ Jack,Jack,Ram Jill,Zara,John [2] row(s) selected. Mach> SELECT GROUP_CONCAT(DISTINCT name) AS G_NAMES FROM concat_table GROUP BY Id2; G_NAMES ------------------------------------------------------------------------------------ Jack,Ram Jill,Zara,John [2] row(s) selected. Mach> SELECT GROUP_CONCAT(name SEPARATOR '.') G_NAMES FROM concat_table GROUP BY Id2; G_NAMES ------------------------------------------------------------------------------------ Jack.Jack.Ram Jill.Zara.John [2] row(s) selected. Mach> SELECT GROUP_CONCAT(name ORDER BY id1) G_NAMES, GROUP_CONCAT(id1 ORDER BY id1) G_SORTID FROM concat_table GROUP BY id2; G_NAMES ------------------------------------------------------------------------------------ G_SORTID ------------------------------------------------------------------------------------ Ram,Jack,Jack 2,5,6 John,Zara,Jill 1,3,4 [2] row(s) selected. ``` ## INSTR 対象文字列内でパターン文字列が始まる位置を返します。位置は1始まりです。 * パターンがなければ0を返します。 * 検索パターンの長さが0、またはNULLの場合はNULLを返します。 ```sql INSTR(target_string, pattern_string) ``` ```sql Mach> CREATE LOG TABLE string_table(c1 VARCHAR(20)); Created successfully. Mach> INSERT INTO string_table VALUES ('abstract'); 1 row(s) inserted. Mach> INSERT INTO string_table VALUES ('override'); 1 row(s) inserted. Mach> SELECT c1, INSTR(c1, 'act') FROM string_table; c1 INSTR(c1, 'act') ------------------------------------------ override 0 abstract 6 [2] row(s) selected. ``` ## LEAST / GREATEST 複数の列/値を入力すると、LEASTは最小値、GREATESTは最大値を返します。 入力値が1つ、またはない場合はエラーです。入力値がNULLならNULLを返すため、入力が列の場合は事前に関数で変換してください。比較できない列(BLOB、TEXTなど)が含まれる場合や、比較のための型変換ができない場合はエラーです。 ```sql LEAST(value_list, value_list,...) GREATEST(value_list, value_list,...) ``` ```sql Mach> CREATE LOG TABLE lgtest_table(c1 INTEGER, c2 LONG, c3 VARCHAR(10), c4 VARCHAR(5)); Created successfully. Mach> INSERT INTO lgtest_table VALUES (1, 2, 'abstract', 'ace'); 1 row(s) inserted. Mach> INSERT INTO lgtest_table VALUES (null, 100, null, 'bag'); 1 row(s) inserted. Mach> SELECT LEAST (c1, c2) FROM lgtest_table; LEAST (c1, c2) ----------------------- NULL 1 [2] row(s) selected. Mach> SELECT LEAST (c1, c2, -1) FROM lgtest_table; LEAST (c1, c2, -1) ----------------------- NULL -1 [2] row(s) selected. Mach> SELECT GREATEST(c3, c4) FROM lgtest_table; GREATEST(c3, c4) -------------------- NULL ace [2] row(s) selected. Mach> SELECT LEAST(c3, c4) FROM lgtest_table; LEAST(c3, c4) ----------------- NULL abstract [2] row(s) selected. Mach> SELECT LEAST(NVL(c3, 'aa'), c4) FROM lgtest_table; LEAST(NVL(c3, 'aa'), c4) ---------------------------- aa abstract [2] row(s) selected. ``` ## LENGTH 文字列列の長さを返します。戻り値は英字(ASCII)を基準とするバイト数です。 ```sql LENGTH(column_name) ``` ```sql Mach> CREATE LOG TABLE length_table (id1 INTEGER, id2 DOUBLE, name VARCHAR(15)); Created successfully. Mach> INSERT INTO length_table VALUES(1, 10, 'Around the Horn'); 1 row(s) inserted. Mach> INSERT INTO length_table VALUES(NULL, 20, 'Alfreds Futterkiste'); 1 row(s) inserted. Mach> INSERT INTO length_table VALUES(3, NULL, 'Antonio Moreno'); 1 row(s) inserted. Mach> INSERT INTO length_table VALUES(4, 40, NULL); 1 row(s) inserted. Mach> select * FROM length_table; ID1 ID2 NAME ------------------------------------------------------------- 4 40 NULL 3 NULL Antonio Moreno NULL 20 Alfreds Futterk 1 10 Around the Horn [4] row(s) selected. Mach> select id1 * 10 FROM length_table; id1 * 10 ----------------------- 40 30 NULL 10 [4] row(s) selected. Mach> select * FROM length_table Where id1 > 1 and id2 < 50; ID1 ID2 NAME ------------------------------------------------------------- 4 40 NULL [1] row(s) selected. Mach> select name || ' with null concat' FROM length_table; name || ' with null concat' ------------------------------------ NULL Antonio Moreno with null concat Alfreds Futterk with null concat Around the Horn with null concat [4] row(s) selected. Mach> select LENGTH(name) FROM length_table; LENGTH(name) --------------- NULL 14 15 15 [4] row(s) selected. ``` ## LOWER 英字文字列を小文字へ変換します。 ```sql LOWER(column_name) ``` ```sql Mach> CREATE LOG TABLE lower_table (name VARCHAR(20)); Created successfully. Mach> INSERT INTO lower_table VALUES(''); 1 row(s) inserted. Mach> INSERT INTO lower_table VALUES('James Backley'); 1 row(s) inserted. Mach> INSERT INTO lower_table VALUES('Alfreds Futterkiste'); 1 row(s) inserted. Mach> INSERT INTO lower_table VALUES('Antonio MORENO'); 1 row(s) inserted. Mach> INSERT INTO lower_table VALUES (NULL); 1 row(s) inserted. Mach> SELECT LOWER(name) FROM lower_table; LOWER(name) ------------------------ NULL antonio moreno alfreds futterkiste james backley NULL [5] row(s) selected. ``` ## LPAD / RPAD 入力文字列が指定の長さになるまで、左側(LPAD)または右側(RPAD)に文字を埋めます。 最後のパラメーターcharは省略可能で、省略すると空白(' ')で埋めます。入力が指定長より長い場合は文字を追加せず、先頭から指定の長さだけ返します。 ```sql LPAD(str, len, padstr) RPAD(str, len, padstr) ``` ```sql Mach> CREATE LOG TABLE pad_table (c1 integer, c2 varchar(15)); Created successfully. Mach> INSERT INTO pad_table VALUES (1, 'Antonio'); 1 row(s) inserted. Mach> INSERT INTO pad_table VALUES (25, 'Johnathan'); 1 row(s) inserted. Mach> INSERT INTO pad_table VALUES (30, 'M'); 1 row(s) inserted. Mach> SELECT LPAD(to_char(c1), 5, '0') FROM pad_table; LPAD(to_char(c1), 5, '0') ----------------------------- 00030 00025 00001 [3] row(s) selected. Mach> SELECT RPAD(to_char(c1), 5, '0') FROM pad_table; RPAD(to_char(c1), 5, '0') ----------------------------- 30000 25000 10000 [3] row(s) selected. Mach> SELECT LPAD(c2, 5) FROM pad_table; LPAD(c2, 5) --------------- M Johna Anton [3] row(s) selected. Mach> SELECT RPAD(c2, 5) FROM pad_table; RPAD(c2, 5) --------------- M Johna Anton [3] row(s) selected. Mach> SELECT RPAD(c2, 10, '***') FROM pad_table; RPAD(c2, 10, '***') ----------------------- M********* Johnathan* Antonio*** [3] row(s) selected. ``` ## LTRIM / RTRIM 第1引数からパターン文字列に含まれる文字を削除します。LTRIMは左から、RTRIMは右から検査し、パターンにない文字に達すると停止します。すべての文字がパターンに含まれる場合はNULLを返します。 パターンを省略すると、空白(' ')を削除します。 ```sql LTRIM(column_name, pattern) RTRIM(column_name, pattern) ``` ```sql Mach> CREATE LOG TABLE trim_table1(name VARCHAR(10)); Created successfully. Mach> INSERT INTO trim_table1 VALUES (' smith '); 1 row(s) inserted. Mach> SELECT ltrim(name) FROM trim_table1; ltrim(name) --------------- smith [1] row(s) selected. Mach> SELECT rtrim(name) FROM trim_table1; rtrim(name) --------------- smith [1] row(s) selected. Mach> SELECT ltrim(name, ' s') FROM trim_table1; ltrim(name, ' s') --------------------- mith [1] row(s) selected. Mach> SELECT rtrim(name, 'h ') FROM trim_table1; rtrim(name, 'h ') --------------------- smit [1] row(s) selected. Mach> CREATE LOG TABLE trim_table2 (name VARCHAR(10)); Created successfully. Mach> INSERT INTO trim_table2 VALUES ('ddckaaadkk'); 1 row(s) inserted. Mach> SELECT ltrim(name, 'dc') FROM trim_table2; ltrim(name, 'dc') --------------------- kaaadkk [1] row(s) selected. Mach> SELECT rtrim(name, 'dk') FROM trim_table2; rtrim(name, 'dk') --------------------- ddckaaa [1] row(s) selected. Mach> SELECT ltrim(name, 'dckak') FROM trim_table2; ltrim(name, 'dckak') ------------------------ NULL [1] row(s) selected. Mach> SELECT rtrim(name, 'dckak') FROM trim_table2; rtrim(name, 'dckak') ------------------------ NULL [1] row(s) selected. ``` ## MAX 指定した数値列の最大値を返す集約関数です。 ```sql MAX(column_name) ``` ```sql Mach> CREATE LOG TABLE max_table (c INTEGER); Created successfully. Mach> INSERT INTO max_table VALUES(10); 1 row(s) inserted. Mach> INSERT INTO max_table VALUES(20); 1 row(s) inserted. Mach> INSERT INTO max_table VALUES(30); 1 row(s) inserted. Mach> SELECT MAX(c) FROM max_table; MAX(c) -------------- 30 [1] row(s) selected. ``` ## MEDIAN {#median} `MEDIAN(value)`は数値式の正確な中央値を返し、`PERCENTILE_CONT(value, 0.5)`と同じ方式で動作します。 ```sql MEDIAN(value) ``` - `value`は数値型である必要があります。 - `NULL`値は無視します。 - 戻り値の型は`DOUBLE`です。 ```sql SELECT MEDIAN(temp_c) FROM sensor_log; ``` ## MIN 指定した数値列の最小値を返す集約関数です。 ```sql MIN(column_name) ``` ```sql Mach> CREATE LOG TABLE min_table(c1 INTEGER); Created successfully. Mach> INSERT INTO min_table VALUES(1); 1 row(s) inserted. Mach> INSERT INTO min_table VALUES(22); 1 row(s) inserted. Mach> INSERT INTO min_table VALUES(33); 1 row(s) inserted. Mach> SELECT MIN(c1) FROM min_table; MIN(c1) -------------- 1 [1] row(s) selected. ``` ## NVL 列値がNULLなら指定値で置き換え、NULLでなければ元の値を返します。 ```sql NVL(string1, replace_with) ``` ```sql Mach> CREATE LOG TABLE nvl_table (c1 varchar(10)); Created successfully. Mach> INSERT INTO nvl_table VALUES ('Johnathan'); 1 row(s) inserted. Mach> INSERT INTO nvl_table VALUES (NULL); 1 row(s) inserted. Mach> SELECT NVL(c1, 'Thomas') FROM nvl_table; NVL(c1, 'Thomas') --------------------- Thomas Johnathan ``` ## NEXTVAL `NEXTVAL(sequence_column)`は、LookupテーブルのSequence列の次の値を返します。 ```sql NEXTVAL(sequence_column) ``` - `NEXTVAL`は`INSERT`文でのみ使用できます。 - 引数は`PROPERTY(SEQUENCE=...)`で設定された列である必要があります。 - Sequence列の作成と例は[Sequence Column](/ja/dbms/lookup-table-usage/sequence-column/)を参照してください。 ```sql INSERT INTO seq_lookup (id, name) VALUES (NEXTVAL(id), 'sensor-a'); ``` ## ROUND 入力値の指定桁(入力桁数+1)を丸めた結果を返します。桁数を省略すると小数点以下0桁に丸めます。負数を指定して整数部の桁で丸めることもできます。 ```sql ROUND(column_name, [decimals]) ``` ```sql Mach> CREATE LOG TABLE round_table (c1 DOUBLE); Created successfully. Mach> INSERT INTO round_table VALUES (1.994); 1 row(s) inserted. Mach> INSERT INTO round_table VALUES (1.995); 1 row(s) inserted. Mach> SELECT c1, ROUND(c1, 2) FROM round_table; c1 ROUND(c1, 2) ----------------------------------------------------------- 1.995 2 1.994 1.99 ``` ## ROWNUM SELECTの結果行に番号を付けます。 SELECTで使用するサブクエリやインラインビュー内でも使用できます。インラインビューの選択リストでROWNUM()を使用する場合は、外側から参照できるように別名を指定してください。 ```sql ROWNUM() ``` **使用できる句** SELECTの選択リスト、GROUP BY、ORDER BY句で使用できます。WHEREとHAVING句では使用できません。結果の番号でWHERE/HAVINGを制御するには、インラインビューでROWNUM()を計算してから外側のクエリで参照します。 |使用できる句|使用できない句| |--|--| |Target List / GROUP BY / ORDER BY|WHERE / HAVING| ```sql Mach> CREATE LOG TABLE rownum_table(c1 INTEGER, c2 DOUBLE, c3 VARCHAR(10)); Created successfully. Mach> INSERT INTO rownum_table VALUES(1, 1.0, ''); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(2, 2.0, 'Second Row'); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(3, 3.3, 'Third Row'); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(4, 4.3, 'Fourth Row'); 1 row(s) inserted. Mach> SELECT INNER_RANK, c3 AS NAME 2 FROM (SELECT ROWNUM() AS INNER_RANK, * FROM rownum_table) 3 WHERE INNER_RANK < 3; INNER_RANK NAME ------------------------------------ 1 Fourth Row 2 Third Row [2] row(s) selected. ``` **ソートによる結果番号の変化** SELECTにORDER BY句がある場合、選択リストのROWNUM()結果が連番にならない場合があります。ROWNUM()がORDER BYより先に処理されるためです。連番が必要な場合は、ORDER BYを含むクエリをインラインビューにして、外側のSELECTでROWNUM()を呼び出してください。 ```sql Mach> CREATE LOG TABLE rownum_table(c1 INTEGER, c2 DOUBLE, c3 VARCHAR(10)); Created successfully. Mach> INSERT INTO rownum_table VALUES(1, 1.0, ''); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(2, 2.0, 'John'); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(3, 3.3, 'Sarah'); 1 row(s) inserted. Mach> INSERT INTO rownum_table VALUES(4, 4.3, 'Micheal'); 1 row(s) inserted. Mach> SELECT ROWNUM(), c2 AS SORT, c3 AS NAME 2 FROM ( SELECT * FROM rownum_table ORDER BY c3 ); ROWNUM() SORT NAME ----------------------------------------------------------------- 1 1 NULL 2 2 John 3 4.3 Micheal 4 3.3 Sarah [4] row(s) selected. ``` ## SERIESNUM `SERIES BY`で区別した連続区間のうち、各行が属する区間の番号を返します。同じ区間の行には同じ番号を付けるため、区間内の行番号とは異なります。戻り値の型はBIGINTで、`SERIES BY`句を使用しない場合は常に1を返します。 ```sql SERIESNUM() ``` ```sql Mach> CREATE LOG TABLE T1 (C1 INTEGER, C2 INTEGER); Created successfully. Mach> INSERT INTO T1 VALUES (0, 1); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (1, 2); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (2, 3); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (3, 2); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (4, 1); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (5, 2); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (6, 3); 1 row(s) inserted. Mach> INSERT INTO T1 VALUES (7, 1); 1 row(s) inserted. Mach> SELECT SERIESNUM(), C1, C2 FROM T1 ORDER BY C1 SERIES BY C2 > 1; SERIESNUM() C1 C2 ------------------------------------------------- 1 1 2 1 2 3 1 3 2 2 5 2 2 6 3 [5] row(s) selected. ``` ## STDDEV / STDDEV_POP 入力列の標本標準偏差(STDDEV)と母標準偏差(STDDEV_POP)を返す集約関数です。それぞれVARIANCE、VAR_POPの平方根です。 ```sql STDDEV(column) STDDEV_POP(column) ``` ```sql Mach> CREATE LOG TABLE stddev_table(c1 INTEGER, C2 DOUBLE); Mach> INSERT INTO stddev_table VALUES (1, 1); 1 row(s) inserted. Mach> INSERT INTO stddev_table VALUES (2, 1); 1 row(s) inserted. Mach> INSERT INTO stddev_table VALUES (3, 2); 1 row(s) inserted. Mach> INSERT INTO stddev_table VALUES (4, 2); 1 row(s) inserted. Mach> SELECT c2, STDDEV(c1) FROM stddev_table GROUP BY c2; c2 STDDEV(c1) ----------------------------------------------------------- 1 0.707107 2 0.707107 [2] row(s) selected. Mach> SELECT c2, STDDEV_POP(c1) FROM stddev_table GROUP BY c2; c2 STDDEV_POP(c1) ----------------------------------------------------------- 1 0.5 2 0.5 [2] row(s) selected. ``` ## SUBSTR 文字列列のSTART位置からSIZEの長さの部分文字列を返します。 * STARTは1始まりで、0の場合はNULLを返します。 * SIZEがSTART位置からの残りの文字列長より大きい場合は、START位置から末尾まで返します。 SIZEは省略可能で、省略すると文字列長を使用します。 ```sql SUBSTRING(column_name, start, [length]) ``` ```sql Mach> CREATE LOG TABLE substr_table (c1 VARCHAR(10)); Created successfully. Mach> INSERT INTO substr_table values('ABCDEFG'); 1 row(s) inserted. Mach> INSERT INTO substr_table values('abstract'); 1 row(s) inserted. Mach> SELECT SUBSTR(c1, 1, 1) FROM substr_table; SUBSTR(c1, 1, 1) -------------------- a A [2] row(s) selected. Mach> SELECT SUBSTR(c1, 3, 3) FROM substr_table; SUBSTR(c1, 3, 3) -------------------- str CDE [2] row(s) selected. Mach> SELECT SUBSTR(c1, 2) FROM substr_table; SUBSTR(c1, 2) ----------------- bstract BCDEFG [2] row(s) selected. Mach> drop table substr_table; Dropped successfully. Mach> CREATE LOG TABLE substr_table (c1 VARCHAR(10)); Created successfully. Mach> INSERT INTO substr_table values('ABCDEFG'); 1 row(s) inserted. Mach> SELECT SUBSTR(c1, 1, 1) FROM substr_table; SUBSTR(c1, 1, 1) -------------------- A [1] row(s) selected. Mach> SELECT SUBSTR(c1, 3, 3) FROM substr_table; SUBSTR(c1, 3, 3) -------------------- CDE [1] row(s) selected. Mach> SELECT SUBSTR(c1, 2) FROM substr_table; SUBSTR(c1, 2) ----------------- BCDEFG [1] row(s) selected. ``` ## SUBSTRING_INDEX 指定したcount回だけ区切り文字delimを見つけるまでの部分文字列を返します。countが負数の場合は文字列の末尾から区切り文字を探し、見つけた位置から末尾まで返します。 countが0ならNULLを返します。countが0以外で文字列に区切り文字がなければ、入力文字列全体を返します。 ```sql SUBSTRING_INDEX(expression, delim, count) ``` ```sql Mach> CREATE LOG TABLE substring_table (url VARCHAR(30)); Created successfully. Mach> INSERT INTO substring_table VALUES('www.machbase.com'); 1 row(s) inserted. Mach> SELECT SUBSTRING_INDEX(url, '.', 1) FROM substring_table; SUBSTRING_INDEX(url, '.', 1) ---------------------------------- www [1] row(s) selected. Mach> SELECT SUBSTRING_INDEX(url, '.', 2) FROM substring_table; SUBSTRING_INDEX(url, '.', 2) ---------------------------------- www.machbase [1] row(s) selected. Mach> SELECT SUBSTRING_INDEX(url, '.', -1) FROM substring_table; SUBSTRING_INDEX(url, '.', -1) ---------------------------------- com [1] row(s) selected. Mach> SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(url, '.', 2), '.', -1) FROM substring_table; SUBSTRING_INDEX(SUBSTRING_INDEX(url, '.', 2), '.', -1) ------------------------------------------- machbase [1] row(s) selected. Mach> SELECT SUBSTRING_INDEX(url, '.', 0) FROM substring_table; SUBSTRING_INDEX(url, '.', 0) ---------------------------------- NULL [1] row(s) selected. ``` ## SUM 数値列の合計を返す集約関数です。 ```sql SUM(column_name) ``` ```sql Mach> CREATE LOG TABLE sum_table (c1 INTEGER, c2 INTEGER); Created successfully. Mach> INSERT INTO sum_table VALUES(1, 1); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(1, 2); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(1, 3); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(2, 1); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(2, 2); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(2, 3); 1 row(s) inserted. Mach> INSERT INTO sum_table VALUES(3, 4); 1 row(s) inserted. Mach> SELECT c1, SUM(c1) from sum_table group by c1; c1 SUM(c1) ------------------------------------ 2 6 3 3 1 3 [3] row(s) selected. Mach> SELECT c1, SUM(c2) from sum_table group by c1; c1 SUM(c2) ------------------------------------ 2 6 3 4 1 6 [3] row(s) selected. ``` ## SUMSQ SUMSQは数値の二乗和を返します。 ```sql SUMSQ(value) ``` ```sql Mach> CREATE LOG TABLE sumsq_table (c1 INTEGER, c2 INTEGER); Created successfully. Mach> INSERT INTO sumsq_table VALUES (1, 1); 1 row(s) inserted. Mach> INSERT INTO sumsq_table VALUES (1, 2); 1 row(s) inserted. Mach> INSERT INTO sumsq_table VALUES (1, 3); 1 row(s) inserted. Mach> INSERT INTO sumsq_table VALUES (2, 4); 1 row(s) inserted. Mach> INSERT INTO sumsq_table VALUES (2, 5); 1 row(s) inserted. Mach> SELECT c1, SUMSQ(c2) FROM sumsq_table GROUP BY c1; c1 SUMSQ(c2) ------------------------------------ 2 41 1 14 [2] row(s) selected. ``` ## SYSDATE / NOW SYSDATEは関数ではなく疑似列で、現在のシステム時刻を返します。 NOWはSYSDATEと同じ機能で、利便性のために提供します。 ```sql SYSDATE NOW ``` ```sql Mach> SELECT SYSDATE, NOW FROM t1; SYSDATE NOW ------------------------------------------------------------------- 2017-01-16 14:14:53 310:973:000 2017-01-16 14:14:53 310:973:000 ``` ## TO_CHAR 指定データ型を文字列型へ変換します。型に応じてformat_stringを指定できますが、バイナリ型には使用できません。 ```sql TO_CHAR(column) ``` **TO_CHAR: 基本データ型** 基本データ型は次のように文字列へ変換します。 ```sql Mach> CREATE LOG TABLE fixed_table (id1 SHORT, id2 INTEGER, id3 LONG, id4 FLOAT, id5 DOUBLE, id6 IPV4, id7 IPV6, id8 VARCHAR (128)); Created successfully. Mach> INSERT INTO fixed_table values(200, 19234, 1234123412, 3.14, 7.8338, '192.168.0.1', '::127.0.0.1', 'log varchar'); 1 row(s) inserted. Mach> SELECT '[ ' || TO_CHAR(id1) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id1) || ' ]' ------------------------------------------------------------------------------------ [ 200 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id2) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id2) || ' ]' ------------------------------------------------------------------------------------ [ 19234 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id3) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id3) || ' ]' ------------------------------------------------------------------------------------ [ 1234123412 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id4) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id4) || ' ]' ------------------------------------------------------------------------------------ [ 3.140000 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id5) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id5) || ' ]' ------------------------------------------------------------------------------------ [ 7.833800 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id6) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id6) || ' ]' ------------------------------------------------------------------------------------ [ 192.168.0.1 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id7) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id7) || ' ]' ------------------------------------------------------------------------------------ [ 0000:0000:0000:0000:0000:0000:7F00:0001 ] [1] row(s) selected. Mach> SELECT '[ ' || TO_CHAR(id8) || ' ]' FROM fixed_table; '[ ' || TO_CHAR(id8) || ' ]' ------------------------------------------------------------------------------------ [ log varchar ] [1] row(s) selected. ``` **TO_CHAR: 浮動小数点数** * バージョン5.5.6以降でサポート floatとdouble値を文字列へ変換します。書式指定子は繰り返して使用できず、'[letter][number]'形式で指定します。 | 書式指定子 | 説明 | |--|--| |F / f|列値の小数桁数を指定します。最大値は30です。| |N / n|小数桁数を指定し、整数部の3桁ごとにカンマ(,)を挿入します。最大値は30です。| ```sql Mach> create table float_table (i1 float, i2 double); Created successfully. Mach> insert into float_table values (1.23456789, 1234.5678901234567890); 1 row(s) inserted. Mach> select TO_CHAR(i1, 'f8'), TO_CHAR(i2, 'N9') from float_table; TO_CHAR(i1, 'f8') TO_CHAR(i2, 'N9') -------------------------------------------------------------- 1.23456788 1,234.567890123 [1] row(s) selected. ``` **TO_CHAR: DATETIME型** datetime列の値を指定形式の文字列へ変換する関数です。さまざまな文字列を生成し、組み合わせることができます。 format_stringを省略すると、デフォルトは"YYYY-MM-DD HH24: MI: SS mmm: uuu: nnn"です。 | 書式指定子 | 説明 | |--|--| |YYYY|年を4桁の数値へ変換します。| |YY|年を2桁の数値へ変換します。| |MM|月を2桁の数値へ変換します。| |MON|月を英語3文字の略称へ変換します(例: JAN, FEB, MAY, ...)。| |DD|日を2桁の数値へ変換します。| |DAY|曜日を英語3文字の略称へ変換します(例: SUN, MON, ...)。| |IW|ISO 8601に従い、曜日を考慮して年内の週番号を`1~53`へ変換します。
- 週は月曜日から始まります。
- 最初の週を前年の最終週とみなす場合があります。同様に、最終週を翌年の最初の週とみなす場合もあります。
詳細はISO 8601を参照してください。| |WW|曜日を考慮せず、年内の週番号を`1~53`へ変換します。
例えば`1月1日~1月7日`は1になります。| |W|曜日を考慮せず、月内の週番号を`1~5`へ変換します。
例えば`3月1日~3月7日`は1になります。| |HH|時を2桁の数値へ変換します。| |HH12|時を`1~12`の範囲の2桁の数値へ変換します。| |HH24|時を`00~23`の範囲の2桁の数値へ変換します。| |HH2, HH3, HH6|HHの後の数値単位で時を切り捨てます。

例えばHH6では`0~5`を0、`6~11`を6と表示します。
時系列統計の計算に便利です。
24時間制で表示します。| |MI|分を2桁の数値で表示します。| |MI2, MI5, MI10, MI20, MI30|MIの後の数値単位で分を切り捨てます。

例えばMI30では`0~29`分を0、`30~59`分を30と表示します。
時系列統計の計算に便利です。| |SS|秒を2桁の数値で表示します。| |SS2, SS5, SS10, SS20, SS30|SSの後の数値単位で秒を切り捨てます。

例えばSS30では`0~29`秒を0、`30~59`秒を30と表示します。
時系列統計の計算に便利です。| |AM|時刻をAM/PMで表示します。| |mmm|ミリ秒を3桁の数値で表示します。

範囲は`0~999`です。| |uuu|マイクロ秒を3桁の数値で表示します。

範囲は`0~999`です。| |nnn|ナノ秒を3桁の数値で表示します。

範囲は`0~999`です。| ```sql Mach> CREATE LOG TABLE datetime_table (id integer, dt datetime); Created successfully. Mach> INSERT INTO datetime_table values(1, TO_DATE('1999-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO datetime_table values(2, TO_DATE('2012-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO datetime_table values(3, TO_DATE('2013-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO datetime_table values(4, TO_DATE('2014-12-30 11:22:33 444:555:666')); 1 row(s) inserted. Mach> SELECT id, dt FROM datetime_table WHERE dt > TO_DATE('2000-11-11 1:2:3 4:5:0'); id dt ----------------------------------------------- 4 2014-12-30 11:22:33 444:555:666 3 2013-11-11 01:02:03 004:005:006 2 2012-11-11 01:02:03 004:005:006 [3] row(s) selected. Mach> SELECT id, dt FROM datetime_table WHERE dt > TO_DATE('2013-11-11 1:2:3') and dt < TO_DATE('2014-11-11 1:2:3'); id dt ----------------------------------------------- 3 2013-11-11 01:02:03 004:005:006 [1] row(s) selected. Mach> SELECT id, TO_CHAR(dt) FROM datetime_table; id TO_CHAR(dt) ------------------------------------------------------------------------------------------------- 4 2014-12-30 11:22:33 444:555:666 3 2013-11-11 01:02:03 004:005:006 2 2012-11-11 01:02:03 004:005:006 1 1999-11-11 01:02:03 004:005:006 [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY') FROM datetime_table; id TO_CHAR(dt, 'YYYY') ------------------------------------------------------------------------------------------------- 4 2014 3 2013 2 2012 1 1999 [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY-MM') FROM datetime_table; id TO_CHAR(dt, 'YYYY-MM') ------------------------------------------------------------------------------------------------- 4 2014-12 3 2013-11 2 2012-11 1 1999-11 [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY-MM-DD') FROM datetime_table; id TO_CHAR(dt, 'YYYY-MM-DD') ------------------------------------------------------------------------------------------------- 4 2014-12-30 3 2013-11-11 2 2012-11-11 1 1999-11-11 [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY-MM-DD TO_CHAR') FROM datetime_table; id TO_CHAR(dt, 'YYYY-MM-DD TO_CHAR') ------------------------------------------------------------------------------------------------- 4 2014-12-30 TO_CHAR 3 2013-11-11 TO_CHAR 2 2012-11-11 TO_CHAR 1 1999-11-11 TO_CHAR [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS') FROM datetime_table; id TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS') ------------------------------------------------------------------------------------------------- 4 2014-12-30 11:22:33 3 2013-11-11 01:02:03 2 2012-11-11 01:02:03 1 1999-11-11 01:02:03 [4] row(s) selected. Mach> SELECT id, TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS mmm.uuu.nnn') FROM datetime_table; id TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS mmm. ------------------------------------------------------------------------------------------------- 4 2014-12-30 11:22:33 444.555.666 3 2013-11-11 01:02:03 004.005.006 2 2012-11-11 01:02:03 004.005.006 1 1999-11-11 01:02:03 004.005.006 [4] row(s) selected. ``` **TO_CHAR: 非対応の型** 現在TO_CHARはバイナリ型をサポートしません。 通常の文字列に変換できないためです。画面で確認するには、TO_HEX()関数で16進値を表示してください。 ## TO_DATE 指定した書式文字列に従って文字列をdatetime型へ変換します。 format_stringを省略すると、デフォルトは"YYYY-MM-DD HH24: MI: SS mmm: uuu: nnn"です。 ```sql -- default format is "YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn" if no format exists. TO_DATE(date_string [, format_string]) ``` ```sql Mach> CREATE LOG TABLE to_date_table (id INTEGER, dt datetime); Created successfully. Mach> INSERT INTO to_date_table VALUES(1, TO_DATE('1999-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO to_date_table VALUES(2, TO_DATE('2012-11-11 1:2:3 4:5:6')); 1 row(s) inserted. Mach> INSERT INTO to_date_table VALUES(3, TO_DATE('2014-12-30 11:22:33 444:555:666')); 1 row(s) inserted. Mach> INSERT INTO to_date_table VALUES(4, TO_DATE('2014-12-30 23:22:34 777:888:999', 'YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn')); 1 row(s) inserted. Mach> SELECT id, dt FROM to_date_table WHERE dt > TO_DATE('1999-11-11 1:2:3 4:5:0'); id dt ----------------------------------------------- 4 2014-12-30 23:22:34 777:888:999 3 2014-12-30 11:22:33 444:555:666 2 2012-11-11 01:02:03 004:005:006 1 1999-11-11 01:02:03 004:005:006 [4] row(s) selected. Mach> SELECT id, dt FROM to_date_table WHERE dt > TO_DATE('2000-11-11 1:2:3 4:5:0'); id dt ----------------------------------------------- 4 2014-12-30 23:22:34 777:888:999 3 2014-12-30 11:22:33 444:555:666 2 2012-11-11 01:02:03 004:005:006 [3] row(s) selected. Mach> SELECT id, dt FROM to_date_table WHERE dt > TO_DATE('2012-11-11 1:2:3','YYYY-MM-DD HH24:MI:SS') and dt < TO_DATE('2014-11-11 1:2:3','YYYY-MM-DD HH24:MI:SS'); id dt ----------------------------------------------- 2 2012-11-11 01:02:03 004:005:006 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999', 'YYYY') FROM to_date_table LIMIT 1; id TO_DATE('1999', 'YYYY') ----------------------------------------------- 4 1999-01-01 00:00:00 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12', 'YYYY-MM') FROM to_date_table LIMIT 1; id TO_DATE('1999-12', 'YYYY-MM') ----------------------------------------------- 4 1999.12.01 00:00:00 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999', 'YYYY') FROM to_date_table LIMIT 1; id TO_DATE('1999', 'YYYY') ----------------------------------------------- 4 1999-01-01 00:00:00 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12', 'YYYY-MM') FROM to_date_table LIMIT 1; id TO_DATE('1999-12', 'YYYY-MM') ----------------------------------------------- 4 1999-12-01 00:00:00 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12-31 13:12', 'YYYY-MM-DD HH24:MI') FROM to_date_table LIMIT 1; id TO_DATE('1999-12-31 13:12', 'YYYY-MM-DD HH24:MI') ------------------------------------------------------- 4 1999-12-31 13:12:00 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12-31 13:12:32', 'YYYY-MM-DD HH24:MI:SS') FROM to_date_table LIMIT 1; id TO_DATE('1999-12-31 13:12:32', 'YYYY-MM-DD HH24:MI:SS') ------------------------------------------------------- 4 1999-12-31 13:12:32 000:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12-31 13:12:32 123', 'YYYY-MM-DD HH24:MI:SS mmm') FROM to_date_table LIMIT 1; id TO_DATE('1999-12-31 13:12:32 123', 'YYYY-MM-DD HH24:MI:SS mmm') ------------------------------------------------------- 4 1999-12-31 13:12:32 123:000:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12-31 13:12:32 123:456', 'YYYY-MM-DD HH24:MI:SS mmm:uuu') FROM to_date_table LIMIT 1; id TO_DATE('1999-12-31 13:12:32 123:456', 'YYYY-MM-DD HH24:MI:SS mmm:uuu') ------------------------------------------------------- 4 1999-12-31 13:12:32 123:456:000 [1] row(s) selected. Mach> SELECT id, TO_DATE('1999-12-31 13:12:32 123:456:789', 'YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn') FROM to_date_table LIMIT 1; id TO_DATE('1999-12-31 13:12:32 123:456:789', 'YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn') ------------------------------------------------------- 4 1999-12-31 13:12:32 123:456:789 [1] row(s) selected. ``` ## TO_DATE_SAFE TO_DATE()と同様ですが、変換に失敗するとエラーを出さずNULLを返します。 ```sql TO_DATE_SAFE(date_string [, format_string]) ``` ```sql Mach> CREATE LOG TABLE date_table (ts DATETIME); Created successfully. Mach> INSERT INTO date_table VALUES (TO_DATE_SAFE('2016-01-01', 'YYYY-MM-DD')); 1 row(s) inserted. Mach> INSERT INTO date_table VALUES (TO_DATE_SAFE('2016-01-02', 'YYYY')); 1 row(s) inserted. Mach> INSERT INTO date_table VALUES (TO_DATE_SAFE('2016-12-32', 'YYYY-MM-DD')); 1 row(s) inserted. Mach> SELECT ts FROM date_table; ts ---------------------------------- NULL NULL 2016-01-01 00:00:00 000:000:000 [3] row(s) selected. ``` ## TO_HEX 列値がNULLならNULLを返し、NULLでなければ元の値を16進文字列で返します。出力の一貫性のため、short、int、long型はBIG ENDIANへ変換します。 ```sql TO_HEX(column) ``` ```sql Mach> CREATE LOG TABLE hex_table (id1 SHORT, id2 INTEGER, id3 VARCHAR(10), id4 FLOAT, id5 DOUBLE, id6 LONG, id7 IPV4, id8 IPV6, id9 TEXT, id10 BINARY, id11 DATETIME); Created successfully. Mach> INSERT INTO hex_table VALUES(256, 65535, '0123456789', 3.141592, 1024 * 1024 * 1024 * 3.14, 13513135446, '192.168.0.1', '::192.168.0.1', 'textext', 'binary', TO_DATE('1999', 'YYYY')); 1 row(s) inserted. Mach> SELECT TO_HEX(id1), TO_HEX(id2), TO_HEX(id3), TO_HEX(id4), TO_HEX(id5), TO_HEX(id6), TO_HEX(id7), TO_HEX(id8), TO_HEX(id9), TO_HEX(id10), TO_HEX(id11) FROM hex_table; TO_HEX(id1) TO_HEX(id2) TO_HEX(id3) TO_HEX(id4) TO_HEX(id5) TO_HEX(id6) TO_HEX(id7) ------------------------------------------------------------------------------------------------------------------------- TO_HEX(id8) TO_HEX(id9) -------------------------------------------------------------------------------------------------------------------------- TO_HEX(id10) TO_HEX(id11) -------------------------------------------------------------------------------------------------------- 0100 0000FFFF 30313233343536373839 D80F4940 1F85EB51B81EE941 0000000325721556 04C0A80001 06000000000000000000000000C0A80001 74657874657874 62696E617279 0CB325846E226000 [1] row(s) selected. ``` ## TO_INET_STR `TO_INET_STR(ipv4_value)`は`IPV4`値をドット区切りの10進文字列へ変換します。 ```sql TO_INET_STR(ipv4_value) ``` ```sql SELECT TO_INET_STR(TO_IPV4('192.168.0.1')); ``` ## TO_IPV4 / TO_IPV4_SAFE 指定した文字列をIPv4型へ変換します。文字列を数値へ変換できない場合、TO_IPV4()はエラーを返して処理を停止します。 TO_IPV4_SAFE()はエラー時にNULLを返すため、処理を継続できます。 ```sql TO_IPV4(string_value) TO_IPV4_SAFE(string_value) ``` ```sql Mach> CREATE LOG TABLE ipv4_table (c1 varchar(100)); Created successfully. Mach> INSERT INTO ipv4_table VALUES('192.168.0.1'); 1 row(s) inserted. Mach> INSERT INTO ipv4_table VALUES(' 192.168.0.2 '); 1 row(s) inserted. Mach> INSERT INTO ipv4_table VALUES(NULL); 1 row(s) inserted. Mach> SELECT c1 FROM ipv4_table; c1 ------------------------------------------------------------------------------------ NULL 192.168.0.2 192.168.0.1 [3] row(s) selected. Mach> SELECT TO_IPV4(c1) FROM ipv4_table; TO_IPV4(c1) ------------------ NULL 192.168.0.2 192.168.0.1 [3] row(s) selected. Mach> INSERT INTO ipv4_table VALUES('192.168.0.1.1'); 1 row(s) inserted. Mach> SELECT TO_IPV4(c1) FROM ipv4_table limit 1; TO_IPV4(c1) ------------------ [ERR-02068 : Invalid IPv4 address format (192.168.0.1.1).] [0] row(s) selected. Mach> SELECT TO_IPV4_SAFE(c1) FROM ipv4_table; TO_IPV4_SAFE(c1) ------------------- NULL NULL 192.168.0.2 192.168.0.1 [4] row(s) selected. ``` ## TO_IPV6 / TO_IPV6_SAFE 指定した文字列をIPv6型へ変換します。文字列を数値型へ変換できない場合、TO_IPV6()はエラーを返して処理を停止します。 TO_IPV6_SAFE()はエラー時にNULLを返すため、処理を継続できます。 ```sql TO_IPV6(string_value) TO_IPV6_SAFE(string_value) ``` ```sql Mach> CREATE LOG TABLE ipv6_table (id varchar(100)); Created successfully. Mach> INSERT INTO ipv6_table VALUES('::0.0.0.0'); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES('::127.0.0.1'); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES('::127.0' || '.0.2'); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES(' ::127.0.0.3'); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES('::127.0.0.4 '); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES(' ::FFFF:255.255.255.255 '); 1 row(s) inserted. Mach> INSERT INTO ipv6_table VALUES('21DA:D3:0:2F3B:2AA:FF:FE28:9C5A'); 1 row(s) inserted. Mach> SELECT TO_IPV6(id) FROM ipv6_table; TO_IPV6(id) --------------------------------------------------------------- 21da:d3::2f3b:2aa:ff:fe28:9c5a ::ffff:255.255.255.255 ::127.0.0.4 ::127.0.0.3 ::127.0.0.2 ::127.0.0.1 :: [7] row(s) selected. Mach> INSERT INTO ipv6_table VALUES('127.0.0.10.10'); 1 row(s) inserted. Mach> SELECT TO_IPV6(id) FROM ipv6_table limit 1; TO_IPV6(id) --------------------------------------------------------------- [ERR-02148 : Invalid IPv6 address format.(127.0.0.10.10)] [0] row(s) selected. Mach> SELECT TO_IPV6_SAFE(id) FROM ipv6_table; TO_IPV6_SAFE(id) --------------------------------------------------------------- NULL 21da:d3::2f3b:2aa:ff:fe28:9c5a ::ffff:255.255.255.255 ::127.0.0.4 ::127.0.0.3 ::127.0.0.2 ::127.0.0.1 :: [8] row(s) selected. ``` ## TO_NUMBER / TO_NUMBER_SAFE 指定した文字列を数値(double)へ変換します。文字列を数値へ変換できない場合、TO_NUMBER()はエラーを返して処理を停止します。 TO_NUMBER_SAFE()はエラー時にNULLを返すため、処理を継続できます。 ```sql TO_NUMBER(string_value) TO_NUMBER_SAFE(string_value) ``` ```sql Mach> CREATE LOG TABLE number_table (id varchar(100)); Created successfully. Mach> INSERT INTO number_table VALUES('10'); 1 row(s) inserted. Mach> INSERT INTO number_table VALUES('20'); 1 row(s) inserted. Mach> INSERT INTO number_table VALUES('30'); 1 row(s) inserted. Mach> SELECT TO_NUMBER(id) from number_table; TO_NUMBER(id) ------------------------------ 30 20 10 [3] row(s) selected. Mach> CREATE LOG TABLE safe_table (id varchar(100)); Created successfully. Mach> INSERT INTO safe_table VALUES('invalidnumber'); 1 row(s) inserted. Mach> SELECT TO_NUMBER(id) from safe_table; TO_NUMBER(id) ------------------------------ [ERR-02145 : The string cannot be converted to number value.(invalidnumber)] [0] row(s) selected. Mach> SELECT TO_NUMBER_SAFE(id) from safe_table; TO_NUMBER_SAFE(id) ------------------------------ NULL [1] row(s) selected. ``` ## TOP_K {#top_k} `TOP_K(value, k)`は、頻度の高い`k`個の数値を`value:count`形式の文字列で返します。 ```sql TOP_K(value, k) ``` - `value`は数値型である必要があります。 - `k`は正の整数定数である必要があります。 - `NULL`値は無視します。 - 戻り値の型は`VARCHAR`です。 - 頻度の降順、頻度が同じ場合は値の昇順でソートします。 ```sql SELECT TOP_K(alarm_code, 3) FROM event_log; ``` 結果例: ```text 101:532,205:317,301:90 ``` ## TO_TIMESTAMP datetime型を1970-01-01 00:00:00 UTCからの経過ナノ秒数へ変換します。 次の例の日付と時刻はUTC+09:00基準です。 ```sql TO_TIMESTAMP(datetime_value) ``` ```sql Mach> create table datetime_tbl (c1 datetime); Created successfully. Mach> insert into datetime_tbl values ('2010-01-01 10:10:10'); 1 row(s) inserted. Mach> select to_timestamp(c1) from datetime_tbl; to_timestamp(c1) ----------------------- 1262308210000000000 [1] row(s) selected. ``` ## TRUNC TRUNC関数は、小数点以下n桁で切り捨てた値を返します。 nを省略すると0とみなし、小数部をすべて取り除きます。nが負数の場合は小数点より前の対応する桁で切り捨てます。 ```sql TRUNC(number [, n]) ``` ```sql Mach> CREATE LOG TABLE trunc_table (i1 DOUBLE); Created successfully. Mach> INSERT INTO trunc_table VALUES (158.799); 1 row(s) inserted. Mach> SELECT TRUNC(i1, 1), TRUNC(i1, -1) FROM trunc_table; TRUNC(i1, 1) TRUNC(i1, -1) ----------------------------------------------------------- 158.7 150 [1] row(s) selected. Mach> SELECT TRUNC(i1, 2), TRUNC(i1, -2) FROM trunc_table; TRUNC(i1, 2) TRUNC(i1, -2) ----------------------------------------------------------- 158.79 100 [1] row(s) selected. ``` ## TS_CHANGE_COUNT 特定列の値の変更回数を求める集約関数です。 入力データの時刻順を保証できないため、1) JOIN、2) インラインビューとは併用できません。VARCHAR型はサポートしません。 * **Cluster Editionでは使用できません。** ```sql TS_CHANGE_COUNT(column) ``` ```sql Mach> CREATE LOG TABLE ipcount_table (id INTEGER, ip IPV4); Created successfully. Mach> INSERT INTO ipcount_table VALUES (1, '192.168.0.1'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (1, '192.168.0.2'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (1, '192.168.0.1'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (1, '192.168.0.2'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (2, '192.168.0.3'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (2, '192.168.0.3'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (2, '192.168.0.4'); 1 row(s) inserted. Mach> INSERT INTO ipcount_table VALUES (2, '192.168.0.4'); 1 row(s) inserted. Mach> SELECT id, TS_CHANGE_COUNT(ip) from ipcount_table GROUP BY id; id TS_CHANGE_COUNT(ip) ------------------------------------ 2 2 1 4 [2] row(s) selected. ``` ## UNIX_TIMESTAMP UNIX_TIMESTAMPは、Unixのtime()システムコールを基準にdate型の値を32ビット整数へ変換する関数です。FROM_UNIXTIMEは逆に整数値をdate型へ変換します。 ```sql UNIX_TIMESTAMP(datetime_value) ``` ```sql Mach> CREATE table unix_table (c1 int); Created successfully. Mach> INSERT INTO unix_table VALUES (UNIX_TIMESTAMP('2001-01-01')); 1 row(s) inserted. Mach> SELECT * FROM unix_table; C1 -------------- 978274800 [1] row(s) selected. ``` ## UPPER 英字文字列を大文字へ変換します。 ```sql UPPER(string_value) ``` ```sql Mach> CREATE LOG TABLE upper_table(id INTEGER,name VARCHAR(10)); Created successfully. Mach> INSERT INTO upper_table VALUES(1, ''); 1 row(s) inserted. Mach> INSERT INTO upper_table VALUES(2, 'James'); 1 row(s) inserted. Mach> INSERT INTO upper_table VALUES(3, 'sarah'); 1 row(s) inserted. Mach> INSERT INTO upper_table VALUES(4, 'THOMAS'); 1 row(s) inserted. Mach> SELECT id, UPPER(name) FROM upper_table; id UPPER(name) ---------------------------- 4 THOMAS 3 SARAH 2 JAMES 1 NULL [4] row(s) selected. ``` ## VARIANCE / VAR_POP 指定した数値列の分散を返す集約関数です。VARIANCEは標本分散、VAR_POPは母分散を返します。 ```sql VARIANCE(column_name) VAR_POP(column_name) ``` ```sql Mach> CREATE LOG TABLE var_table(c1 INTEGER, c2 DOUBLE); Created successfully. Mach> INSERT INTO var_table VALUES (1, 1); 1 row(s) inserted. Mach> INSERT INTO var_table VALUES (2, 1); 1 row(s) inserted. Mach> INSERT INTO var_table VALUES (1, 2); 1 row(s) inserted. Mach> INSERT INTO var_table VALUES (2, 2); 1 row(s) inserted. Mach> SELECT VARIANCE(c1) FROM var_table; VARIANCE(c1) ------------------------------ 0.333333 [1] row(s) selected. Mach> SELECT VAR_POP(c1) FROM var_table; VAR_POP(c1) ------------------------------ 0.25 [1] row(s) selected. ``` ## YEAR / MONTH / DAY 入力datetime列から年、月、日をそれぞれ抽出して整数で返します。 ```sql YEAR(datetime_col) MONTH(datetime_col) DAY(datetime_col) ``` ```sql Mach> CREATE LOG TABLE extract_table(c1 DATETIME, c2 INTEGER); Created successfully. Mach> INSERT INTO extract_table VALUES (to_date('2001-01-01 12:30:00 000:000:000'), 1); 1 row(s) inserted. Mach> SELECT YEAR(c1), MONTH(c1), DAY(c1) FROM extract_table; year(c1) month(c1) day(c1) ---------------------------------------- 2001 1 1 ``` ## ISNAN / ISINF 引数の数値がNaNまたはInfか判定します。NaNまたはInfなら1、それ以外は0を返します。 ```sql ISNAN(number) ISINF(number) ``` 次の例は、テーブルにすでに`NaN`と`Inf`値がある場合を想定します。SQL `INSERT`文で`nan`や`inf`トークンを直接値として取り込むことはできません。 ```sql Mach> SELECT * FROM test; I1 I2 I3 ------------------------------------------------------------------------ 1 1 1 nan inf 0 NULL NULL NULL [3] row(s) selected. Mach> SELECT ISNAN(i1), ISNAN(i2), ISNAN(i3), i3 FROM test ; ISNAN(i1) ISNAN(i2) ISNAN(i3) i3 ----------------------------------------------------- 0 0 0 1 1 0 0 0 NULL NULL NULL NULL [3] row(s) selected. Mach> SELECT * FROM test WHERE ISNAN(i1) = 1; I1 I2 I3 ------------------------------------------------------------------------ nan inf 0 [1] row(s) selected. ``` ## JSON_SET JSONドキュメントの指定パスにSQLスカラー値をJSONスカラーとして保存します。 ```sql JSON_SET(json_doc, path, scalar) ``` ```sql Mach> SELECT JSON_SET('{"ship":{"status":"READY"}}', '$.ship.status', 'DONE') FROM dual; JSON_SET('{"ship":{"status":"READY"}}', '$.ship.status', 'DONE') -------------------------------------------------------------------------------- {"ship":{"status":"DONE"}} [1] row(s) selected. ``` 注意事項: - `path`には完全なJSONPathを使用してください。 - `JSON_SET(..., path, NULL)`はJSONの`null`を保存します。 - JSONドキュメント引数が`NULL`なら結果はSQL `NULL`です。 - `path`が`NULL`や空文字列ならエラーになります。 - オブジェクトのパスを中心にサポートします。 - 配列要素の更新(例: `$.items[0]`)はサポートしません。 ## JSON_SET_JSON 第3引数をJSON文字列として解析し、オブジェクトまたは配列のサブツリーを保存します。 ```sql JSON_SET_JSON(json_doc, path, json_text) ``` ```sql Mach> SELECT JSON_SET_JSON('{"ship":{}}', '$.ship.owner', '{"name":"machbase"}') FROM dual; JSON_SET_JSON('{"ship":{}}', '$.ship.owner', '{"name":"machbase"}') ---------------------------------------------------------------------------- {"ship":{"owner":{"name":"machbase"}}} [1] row(s) selected. ``` 注意事項: - `path`には完全なJSONPathを使用してください。 - 第3引数がSQL `NULL`なら結果はSQL `NULL`です。 - 無効なJSON文字列はエラーになります。 - オブジェクトのパスを中心にサポートします。 - 配列要素の更新はサポートしません。 ## JSON_REMOVE JSONドキュメントから指定メンバーまたは下位パスを削除します。 ```sql JSON_REMOVE(json_doc, path) ``` ```sql Mach> SELECT JSON_REMOVE('{"owner":{"name":"machbase","team":"db"}}', '$.owner.team') FROM dual; JSON_REMOVE('{"owner":{"name":"machbase","team":"db"}}', '$.owner.team') -------------------------------------------------------------------------- {"owner":{"name":"machbase"}} [1] row(s) selected. ``` 注意事項: - `path`には完全なJSONPathを使用してください。 - 存在しないパスは何も変更しません。 - `JSON_REMOVE(..., '$')`は許可しません。 - JSONドキュメント引数が`NULL`なら結果はSQL `NULL`です。 ## PI() {#pi} π定数を`DOUBLE`型で返します。 ```sql SELECT PI(); ``` ```sql Mach> SELECT PI(); PI() ------------------------------ 3.141592653589793 [1] row(s) selected. ``` ## SQRT() {#sqrt} 平方根を返します。 ```sql SELECT SQRT(9), SQRT(2.25), SQRT(16.0); ``` ```sql Mach> SELECT SQRT(9), SQRT(2.25), SQRT(16.0); SQRT(9) SQRT(2.25) SQRT(16.0) ----------------------------------------------- 3 1.5000000000000000 4 [1] row(s) selected. ``` ## POWER() {#power} `base`の`exponent`乗を返します。 ```sql SELECT POWER(2, 3), POWER(9, 0.5), POWER(4, -1); ``` ```sql Mach> SELECT POWER(2, 3), POWER(9, 0.5), POWER(4, -1); POWER(2, 3) POWER(9, 0.5) POWER(4, -1) ------------------------------------------------ 8 3.0000000000000000 0.2500000000000000 [1] row(s) selected. ``` ## POW() {#pow} `POWER()`の別名です。 ```sql SELECT POW(2, 3), POW(2, -1), POW(10, 0); ``` ```sql Mach> SELECT POW(2, 3), POW(2, -1), POW(10, 0); POW(2, 3) POW(2, -1) POW(10, 0) ----------------------------------------- 8 0.5 1 [1] row(s) selected. ``` ## LOG() {#log} `LOG(n)`は自然対数、`LOG(base, n)`は指定した底の対数を計算します。 ```sql SELECT LOG(2, 8), LOG(100), LOG(10, 1000); ``` ```sql Mach> SELECT LOG(2, 8), LOG(100), LOG(10, 1000); LOG(2, 8) LOG(100) LOG(10, 1000) ------------------------------------------------ 3 4.605170185988092 3 [1] row(s) selected. ``` ## LN() {#ln} 自然対数`ln(n)`を返します。 ```sql SELECT LN(1), LN(10), LN(1000); ``` ```sql Mach> SELECT LN(1), LN(10), LN(1000); LN(1) LN(10) LN(1000) ----------------------------------- 0 2.302585092994046 6.907755278982137 [1] row(s) selected. ``` ## EXP() {#exp} `e^n`を返します。 ```sql SELECT EXP(0), EXP(1), EXP(-1); ``` ```sql Mach> SELECT EXP(0), EXP(1), EXP(-1); EXP(0) EXP(1) EXP(-1) ----------------------------------- 1 2.718281828459045 0.36787944117144233 [1] row(s) selected. ``` ## FLOOR() {#floor} 負の無限大方向へ切り捨てます。 ```sql SELECT FLOOR(-1.2), FLOOR(3.9), FLOOR(-3.0); ``` ```sql Mach> SELECT FLOOR(-1.2), FLOOR(3.9), FLOOR(-3.0); FLOOR(-1.2) FLOOR(3.9) FLOOR(-3.0) ----------------------------------------- -2 3 -3 [1] row(s) selected. ``` ## CEIL() {#ceil} 正の無限大方向へ切り上げます。 ```sql SELECT CEIL(-1.2), CEIL(3.2), CEIL(-3.0); ``` ```sql Mach> SELECT CEIL(-1.2), CEIL(3.2), CEIL(-3.0); CEIL(-1.2) CEIL(3.2) CEIL(-3.0) ------------------------------------- -1 4 -3 [1] row(s) selected. ``` ## SIN() {#sin} ラジアンの入力から正弦を返します。 ```sql SELECT SIN(0), SIN(PI()/2), SIN(PI()); ``` ```sql Mach> SELECT SIN(0), SIN(PI()/2), SIN(PI()); SIN(0) SIN(PI()/2) SIN(PI()) ------------------------------------ 0 1 0 [1] row(s) selected. ``` ## SLOPE {#slope} `SLOPE(y, x)`は、数値の`(x, y)`点に対する線形回帰直線の傾きを計算します。 ```sql SLOPE(y, x) ``` - 両方の引数が数値型である必要があります。 - `NULL`値は無視します。 - 有効なデータが不足する場合や`x`の分散が0の場合、結果は`NULL`です。 - 戻り値の型は`DOUBLE`です。 ```sql SELECT SLOPE(temp_c, sample_sec) FROM sensor_log; ``` ## COS() {#cos} ラジアンの入力から余弦を返します。 ```sql SELECT COS(0), COS(PI()), COS(PI()/2); ``` ```sql Mach> SELECT COS(0), COS(PI()), COS(PI()/2); COS(0) COS(PI()) COS(PI()/2) ------------------------------------- 1 -1 0 [1] row(s) selected. ``` ## TAN() {#tan} ラジアンの入力から正接を返します。 ```sql SELECT TAN(0), TAN(PI()/4), TAN(PI()); ``` ```sql Mach> SELECT TAN(0), TAN(PI()/4), TAN(PI()); TAN(0) TAN(PI()/4) TAN(PI()) ----------------------------------- 0 1 0 [1] row(s) selected. ``` ## MOD() {#mod} 商を0方向へ切り捨てて余りを計算します。 ```sql SELECT MOD(10, 3), MOD(11, 4), MOD(-10, 3), MOD(3.5, 0.5); ``` ```sql Mach> SELECT MOD(10, 3), MOD(11, 4), MOD(-10, 3), MOD(3.5, 0.5); MOD(10, 3) MOD(11, 4) MOD(-10, 3) MOD(3.5, 0.5) ------------------------------------------------------- 1 3 -1 0 [1] row(s) selected. ``` ## MODE {#mode} `MODE(value)`は入力集合で最も頻度の高い数値を返します。 ```sql MODE(value) ``` - `value`は数値型である必要があります。 - `NULL`値は無視します。 - 最頻値が複数あれば、最小の値を返します。 - 戻り値の型は`DOUBLE`です。 ```sql SELECT MODE(alarm_code) FROM event_log; ``` ## P05 / P10 / P90 / P95 {#p05-p10-p90-p95} よく使う分位点を簡潔に表す、正確な分位点計算の短縮関数です。 ```sql P05(value) P10(value) P90(value) P95(value) ``` - `value`は数値型である必要があります。 - `NULL`値は無視します。 - 戻り値の型は`DOUBLE`です。 `P05`、`P10`、`P90`、`P95`はそれぞれ`PERCENTILE_CONT(value, 0.05)`、`0.10`、`0.90`、`0.95`と同じ意味です。 ```sql SELECT P05(response_ms), P10(response_ms), P90(response_ms), P95(response_ms) FROM web_log; ``` ## PERCENTILE_CONT / PERCENTILE_DISC {#percentile_cont-percentile_disc} 数値入力の正確な分位点を計算する集約関数です。 ```sql PERCENTILE_CONT(value, ratio) PERCENTILE_DISC(value, ratio) ``` - `value`は数値型である必要があります。 - `ratio`は`0.0`以上`1.0`以下の定数である必要があります。 - `PERCENTILE_CONT`は必要に応じてソート済みの隣接値間を補間します。 - `PERCENTILE_DISC`は対象順位に対応する実際の観測値を選択します。 - 両関数とも戻り値の型は`DOUBLE`です。 ```sql SELECT PERCENTILE_CONT(latency_ms, 0.95) AS pcont95, PERCENTILE_DISC(latency_ms, 0.95) AS pdisc95 FROM api_log; ``` ## QUANTILE {#quantile} `QUANTILE(value, ratio)`は数値入力の正確な連続分位点を計算します。 ```sql QUANTILE(value, ratio) ``` - `value`は数値型である必要があります。 - `ratio`は`0.0`以上`1.0`以下の定数である必要があります。 - 戻り値の型は`DOUBLE`です。 - `PERCENTILE_CONT`と同じ連続分位点の規則を使用します。 ```sql SELECT QUANTILE(cpu_usage, 0.75) FROM host_metric; ``` ## RAND() {#rand} 乱数値を生成します。 ```sql SELECT RAND(5) = RAND(5) AS same_seed, RAND(7) = RAND(8) AS diff_seed, RAND() = RAND() AS diff_default; ``` ```sql Mach> SELECT RAND(5) = RAND(5) AS same_seed, RAND(7) = RAND(8) AS diff_seed, RAND() = RAND() AS diff_default FROM m$sys_users WHERE name = 'SYS'; same_seed diff_seed diff_default ------------------------------------ 1 0 0 [1] row(s) selected. ``` `RAND(seed)`は同じシードで同じ値を返します。`RAND()`はセッションの内部状態に基づいて`[0,1)`の範囲の値を生成します。 ## REGEXP_LIKE `REGEXP_LIKE`は文字列が正規表現パターンに一致するか検査します。Boolean値を返し、主に`WHERE`句で使用します。 ```sql REGEXP_LIKE(source, pattern) REGEXP_LIKE(source, pattern, match_param) ``` - `source`は`VARCHAR`である必要があります。 - `pattern`は定数の`VARCHAR`正規表現である必要があります。 - `match_param`は省略可能で、定数の`VARCHAR`を指定します。`c`は大文字小文字を区別し、`i`は区別しません。デフォルトは`c`です。 ```sql SELECT * FROM sensor_text WHERE REGEXP_LIKE(message, 'error|warn', 'i'); ``` ## REGEXP_INSTR `REGEXP_INSTR`は正規表現に一致する位置を1始まりで返します。一致する値がなければ`0`を返します。 ```sql REGEXP_INSTR(source, pattern[, position[, occurrence[, return_pos[, match_param]]]]) ``` - `source`は`VARCHAR`である必要があります。 - `pattern`は定数の`VARCHAR`正規表現である必要があります。 - `position`と`occurrence`は`1`以上の整数定数です。 - `return_pos`は整数定数です。`0`は開始位置、`1`は一致した文字列の直後の位置を返します。 - `match_param`は`c`または`i`を使用できます。デフォルトは`c`です。 ```sql SELECT REGEXP_INSTR('TechOnTheNet', 'The', 1, 1, 1, 'i'); ``` ## REGEXP_SUBSTR `REGEXP_SUBSTR`は正規表現に一致する部分文字列を返します。 ```sql REGEXP_SUBSTR(source, pattern[, position[, occurrence[, match_param]]]) ``` - `source`は`VARCHAR`である必要があります。 - `pattern`は定数の`VARCHAR`正規表現である必要があります。 - `position`と`occurrence`は`1`以上の整数定数です。 - `match_param`は`c`または`i`を使用できます。デフォルトは`c`です。 ```sql SELECT REGEXP_SUBSTR('TechOnTheNet', 'a|e|i|o|u', 1, 2, 'i'); ``` ## REGEXP_REPLACE `REGEXP_REPLACE`は正規表現に一致する文字列を置換します。 ```sql REGEXP_REPLACE(source, pattern[, replacement[, position[, occurrence[, match_param]]]]) ``` - `source`は`VARCHAR`である必要があります。 - `pattern`と`replacement`は定数の`VARCHAR`値である必要があります。 - `replacement`を省略すると一致文字列を削除します。 - `position`は`1`以上の整数定数です。 - `occurrence`は整数定数です。`0`はすべての一致を置換し、正の値はその番号の一致のみ置換します。 - `match_param`は`c`または`i`を使用できます。デフォルトは`c`です。 ```sql SELECT REGEXP_REPLACE('TechOnTheNet', 'a|e|i|o|u', 'Z', 1, 2, 'i'); ``` ## 組み込み関数の対応する型 | |Short|Integer|Long|Float|Double|Varchar|Text|Ipv4|Ipv6|Datetime|Binary| |--|--|--|--|--|--|--|--|--|--|--|--| |ABS|o|o|o|o|o|x|x|x|x|x|x| |ADD_TIME|x|x|x|x|x|x|x|x|x|o|x| |APPROX_PERCENTILE / APPROX_MEDIAN / APPROX_P05 / APPROX_P10 / APPROX_P90 / APPROX_P95|o|o|o|o|o|x|x|x|x|x|x| |AREA|o|o|o|o|o|x|x|x|x|x|x| |AVG|o|o|o|o|o|x|x|x|x|x|x| |BITAND / BITOR|o|o|o|x|x|x|x|x|x|x|x| |COUNT|o|o|o|o|o|o|x|o|o|o|x| |CUME_DIST|o|o|o|o|o|x|x|x|x|x|x| |DATE_TRUNC|x|x|x|x|x|x|x|x|x|o|x| |DECODE|o|o|o|o|o|o|x|o|x|o|x| |FIRST / LAST|o|o|o|o|o|o|x|o|o|o|x| |FROM_TIMESTAMP|o|o|o|o|o|x|x|x|x|x|x| |FROM_UNIXTIME|o|o|o|o|o|x|x|x|x|x|x| |GROUP_CONCAT|o|o|o|o|o|o|x|o|o|o|x| |INSTR|x|x|x|x|x|o|o|x|x|x|x| |LEAST / GREATEST|o|o|o|o|o|o|x|x|x|x|x| |LENGTH|x|x|x|x|x|o|o|x|x|x|o| |LOWER|x|x|x|x|x|o|x|x|x|x|x| |LPAD / RPAD|x|x|x|x|x|o|x|x|x|x|x| |LTRIM / RTRIM|x|x|x|x|x|o|x|x|x|x|x| |MAX|o|o|o|o|o|o|x|o|o|o|x| |MEDIAN|o|o|o|o|o|x|x|x|x|x|x| |MIN|o|o|o|o|o|o|x|o|o|o|x| |MODE|o|o|o|o|o|x|x|x|x|x|x| |NVL|x|x|x|x|x|o|x|o|x|x|x| |P05 / P10 / P90 / P95|o|o|o|o|o|x|x|x|x|x|x| |PERCENTILE_CONT / PERCENTILE_DISC|o|o|o|o|o|x|x|x|x|x|x| |QUANTILE|o|o|o|o|o|x|x|x|x|x|x| |REGEXP_LIKE|x|x|x|x|x|o|x|x|x|x|x| |REGEXP_INSTR|x|x|x|x|x|o|x|x|x|x|x| |REGEXP_SUBSTR|x|x|x|x|x|o|x|x|x|x|x| |REGEXP_REPLACE|x|x|x|x|x|o|x|x|x|x|x| |SLOPE|o|o|o|o|o|x|x|x|x|x|x| |TOP_K|o|o|o|o|o|x|x|x|x|x|x| |ROUND|o|o|o|o|o|x|x|x|x|x|x| |ROWNUM|o|o|o|o|o|o|o|o|o|o|o| |SERIESNUM|o|o|o|o|o|o|o|o|o|o|o| |STDDEV / STDDEV_POP|o|o|o|o|o|x|x|x|x|x|x| |SUBSTR|x|x|x|x|x|o|x|x|x|x|x| |SUBSTRING_INDEX|x|x|x|x|x|o|o|x|x|x|x| |SUM|o|o|o|o|o|x|x|x|x|x|x| |SYSDATE / NOW|x|x|x|x|x|x|x|x|x|x|x| |TO_CHAR|o|o|o|o|o|o|x|o|o|o|x| |TO_DATE / TO_DATE_SAFE|x|x|x|x|x|o|x|x|x|x|x| |TO_HEX|o|o|o|o|o|o|o|o|o|o|o| |TO_INET_STR|x|x|x|x|x|x|x|o|x|x|x| |TO_IPV4 / TO_IPV4_SAFE|x|x|x|x|x|o|x|x|x|x|x| |TO_IPV6 / TO_IPV6_SAFE|x|x|x|x|x|o|x|x|x|x|x| |TO_NUMBER / TO_NUMBER_SAFE|x|x|x|x|x|o|x|x|x|x|x| |TO_TIMESTAMP|x|x|x|x|x|x|x|x|x|o|x| |TRUNC|o|o|o|o|o|x|x|x|x|x|x| |TS_CHANGE_COUNT|o|o|o|o|o|x|x|o|o|o|x| |UNIX_TIMESTAMP|x|x|x|x|x|x|x|x|x|o|x| |UPPER|x|x|x|x|x|o|x|x|x|x|x| |VARIANCE / VAR_POP|o|o|o|o|o|x|x|x|x|x|x| |YEAR / MONTH / DAY|x|x|x|x|x|x|x|x|x|o|x| |ISNAN / ISINF|o|o|o|o|o|x|x|x|x|x|x| ## JSON関連関数 これらの関数はJSONデータ型を引数に取ります。 | 関数名 | 説明 | 備考 | |--|--|--| |JSON_EXTRACT(JSON column name, 'json path')|値を文字列型で返します。
値がなければERRORを返します。| - JSON object or array: すべてのオブジェクトを文字列へ変換して返します。
- String type: そのまま返します。
- Numeric type: 文字列へ変換して返します。
- boolean type: "True"または"False"を返します。| |JSON_EXTRACT_DOUBLE(JSON column name, 'json path')|値を64ビットdouble型で返します。
値がなければNULLを返します。| - JSON object or array: NULLを返します。
- String type: 変換可能なら変換して返し、不可能ならNULLを返します。
- Numeric type: 64ビット実数で返します。
- boolean type: "True"は1.0、"False"は0.0を返します。| |JSON_EXTRACT_INTEGER(JSON column name, 'json path')|値を64ビット整数型で返します。
値がなければNULLを返します。| - JSON object or array: NULLを返します。
- String type: 変換可能なら変換して返し、不可能ならNULLを返します。
- Numeric type: 64ビット整数で返します。
- boolean type: "True"は1、"False"は0を返します。| |JSON_EXTRACT_STRING(JSON column name, 'json path')|値を文字列型で返します。
値がなければNULLを返します。
矢印演算子(→)と同じ結果を返します。| - JSON object or array: すべてのオブジェクトを文字列へ変換して返します。
- String type: そのまま返します。
- Numeric type: 文字列へ変換して返します。
- boolean type: "True"または"False"を返します。| |JSON_SET(json_doc, path, scalar)|指定パスにSQLスカラー値をJSONスカラーとして保存した新しいJSONドキュメントを返します。| - `path`は完全なJSONPathを使用します。
- `NULL`値はJSONの`null`として保存します。
- オブジェクトのパスのみサポートします。| |JSON_SET_JSON(json_doc, path, json_text)|指定パスにJSON文字列をオブジェクトまたは配列のサブツリーとして保存した新しいJSONドキュメントを返します。| - `path`は完全なJSONPathを使用します。
- 第3引数がSQL `NULL`なら結果はSQL `NULL`です。
- 無効なJSON文字列はエラーになります。| |JSON_REMOVE(json_doc, path)|指定パスのメンバーまたはサブツリーを削除した新しいJSONドキュメントを返します。| - `path`は完全なJSONPathを使用します。
- 存在しないパスは何も変更しません。
- `JSON_REMOVE(..., '$')`は許可しません。| |JSON_IS_VALID('json string')|JSON文字列が正しい形式か確認します。| - 0: False
- 1: True| |JSON_TYPEOF(JSON column name, 'json path')|値の型を返します。| - None: キーが存在しない
- Object: オブジェクト型
- Integer: 整数型
- Real: 実数型
- String: 文字列型
- True/False: Boolean
- Array: 配列型
- Null: NULL| ```sql Mach> CREATE LOG TABLE jsontbl (name VARCHAR(20), jval JSON); Created successfully. Mach> INSERT INTO jsontbl VALUES("name1", '{"name":"test1"}'); 1 row(s) inserted. Mach> INSERT INTO jsontbl VALUES("name2", '{"name":"test2", "value":123}'); 1 row(s) inserted. Mach> INSERT INTO jsontbl VALUES("name3", '{"name":{"class1": "test3"}}'); 1 row(s) inserted. Mach> INSERT INTO jsontbl VALUES("name4", '{"myarray": [1, 2, 3, 4]}'); 1 row(s) inserted. Mach> INSERT INTO jsontbl VALUES("name5", '{"name":"error"'); [ERR-02233: Error occurred at column (2): (Error in json load.)] Mach> SELECT name, JSON_EXTRACT_STRING(jval, '$.name') FROM jsontbl; name JSON_EXTRACT_STRING(jval, '$.name') ----------------------------------------------------------------------------------------------------------- name4 NULL name3 {"class1": "test3"} name2 test2 name1 test1 [4] row(s) selected. Mach> SELECT name, JSON_EXTRACT_INTEGER(jval, '$.myarray[1]') FROM jsontbl; name JSON_EXTRACT_INTEGER(jval, '$.myarray[1]') -------------------------------------------------------------------- name4 2 name3 NULL name2 NULL name1 NULL [4] row(s) selected. Mach> SELECT name, JSON_TYPEOF(jval, '$.name') FROM jsontbl; name JSON_TYPEOF(jval, '$.name') ----------------------------------------------------------------------------------------------------------- name4 None name3 Object name2 String name1 String [4] row(s) selected. ``` ## JSON演算子 `->`演算子はJSONデータのオブジェクトへのアクセスに使用します。 JSON_EXTRACT_STRING関数と同じ結果を返します。 ```sql json_col -> 'json path' ``` JSON列のメンバー値には、JSONPathを使用する`->`演算子とドットの省略構文でアクセスできます。 ```sql -- JSONPathの矢印構文 jval->'$.sensor.temperature' -- JSONドット省略構文 jval.sensor.temperature ``` 2つの式は同じJSON値を参照します。既存の`->`演算子は引き続き使用でき、ドット構文は同じ値をより短く表すための追加構文です。 ```sql Mach> SELECT name, jval->'$.name' FROM jsontbl; name JSON_EXTRACT_STRING(jval, '$.name') ----------------------------------------------------------------------------------------------------------- name4 NULL name3 {"class1": "test3"} name2 test2 name1 test1 [4] row(s) selected. Mach> SELECT name, jval->'$.myarray[1]' FROM jsontbl; name JSON_EXTRACT_INTEGER(jval, '$.myarray[1]') -------------------------------------------------------------------- name4 2 name3 NULL name2 NULL name1 NULL [4] row(s) selected. Mach> SELECT name, jval->'$.name.class1' FROM jsontbl; name jval->'$.name.class1' ----------------------------------------------------------------------------------------------------------- name4 NULL name3 test3 name2 NULL name1 NULL [4] row(s) selected ``` ### JSONPathの矢印構文 矢印構文はJSONPath文字列を使用します。 ```sql jval->'$.name' jval->'$.sensor.temperature' jval->'$.items[0].name' ``` 角括弧でJSONキーを直接指定することもできます。キー名にドット(`.`)を含む場合は角括弧構文を使用します。 ```sql -- キー名がa.bの場合 jval->'$["a.b"]' jval->'$[a.b]' -- 複数階層のキーを角括弧で指定 jval->'$[Plant1][Line1][Temperature]' -- ドットを含む1つのキー名 jval->'$[Plant1.Line1.Temperature]' ``` `$[Plant1.Line1.Temperature]`は`Plant1.Line1.Temperature`という1つのキーを検索します。`Plant1`、`Line1`、`Temperature`を階層ごとのキーとして検索するには、`$[Plant1][Line1][Temperature]`または`$.Plant1.Line1.Temperature`を使用します。 キー名に特殊文字やドットを含む場合は、次のように引用符付きの角括弧構文を推奨します。 ```sql jval->'$["a.b"]["c.d"]["e.f"]' ``` 次の構文はサポートしません。 ```sql jval->'$."a.b"' ``` ### JSONドット省略構文 JSON列の後にメンバー名を付けてJSON値を参照できます。 ```sql -- 単一メンバー jval.name -- 入れ子のメンバー jval.sensor.temperature -- 配列の添字 jval.items[0].name -- 特殊文字を含むキー jval.items[0]."product-id" ``` ドット構文で二重引用符で囲んだキーは、大文字小文字と特殊文字をそのまま保持します。 ```sql SELECT name, jval."Camel-Key", jval.items[0]."product-id" FROM jsontbl ORDER BY name; ``` ### WHERE句での型比較 JSONメンバーのアクセス結果は参照時に文字列のように表示されます。ただし、`WHERE`句で数値型の値と比較すると、JSON値を数値として解析し、数値比較を行います。 ```sql SELECT name FROM jsontbl WHERE jval->'$.value' > 100 ORDER BY name; SELECT name FROM jsontbl WHERE jval.value BETWEEN 10 AND 30 ORDER BY name; SELECT name FROM jsontbl WHERE jval.value IN (10, 20, 30) ORDER BY name; ``` 次の比較に対応します。 - JSON integer値とSQL integer値の比較 - JSON real/double値とSQL numeric値の比較 - JSON数値文字列とSQL numeric値の比較 - JSON boolean値と文字列`'true'`、`'false'`の比較 - `=`、`<>`、`<`、`<=`、`>`、`>=`、`BETWEEN`、リテラルの`IN (...)` SQL integer値との比較ではJSON integerを整数として比較するため、`9007199254740992`と`9007199254740993`のようにdoubleの精度範囲を超える値も区別できます。 文字型の値との比較では、従来どおり文字列比較を行います。 ```sql SELECT name FROM jsontbl WHERE jval->'$.name' = 'test1' ORDER BY name; ``` 数値比較でJSON値を数値として解釈できない場合、その条件には一致せず、エラーにはなりません。通常の`VARCHAR`列と数値の比較ポリシーは変更せず、自動数値比較はJSONメンバーアクセス式にのみ適用します。 ### 名前解決規則 通常のSQL列名の解決は、JSONドットの解釈より優先されます。 ```sql SELECT t.jval.name FROM jsontbl t; ``` 上記の式は、最初に通常の列名として解決を試みます。通常の列として解決できず、`jval`がJSON列であれば、`jval.name`をJSONメンバーへのアクセスとして扱います。 JSONドットアクセスは、JSON列を基点としてのみ使用できます。 ```sql -- 非対応 (jval->'$.sensor').temperature name.member ``` ### 制約 次の構文はサポートしません。 - ワイルドカード: `jval.items[*].name` - 再帰的下降: `jval..name` - フィルター式: `jval.items[?(@.price > 10)]` - 負数の配列添字: `jval.items[-1]` - 単一引用符のキー: `jval.'product-id'` - ドット構文と矢印構文の混在: `jval.items->'$.name'` - JSON以外の列へのドットアクセス: `name.member` - 任意の式の後のドットアクセス: `(jval->'$.sensor').temperature` - 矢印パス内の引用符付きメンバー: `jval->'$."a.b"'` `IN (SELECT ...)`形式のサブクエリINでは、JSONメンバー値の自動数値比較はサポートしません。リテラルの`IN (...)`を使用してください。 ## ウィンドウ関数 ウィンドウ関数は、行間の比較、計算、定義を行う関数で、分析関数やランキング関数とも呼ばれます。 SELECT文でのみ使用できます。 ### ウィンドウ関数の構文 ウィンドウ関数には必ずOVER句を含めます。 ``` WINDOW_FUNCTION (ARGUMENTS) OVER ([PARTITION BY column_name] [ORDER BY column_name]) ``` * WINDOW_FUNCTION: ウィンドウ関数名 * ARGUMENTS: 関数に応じて0~N個の引数を指定できます。 * PARTITION BY clause: 全体集合を基準に応じて小さなグループへ分割します(省略可能)。 * ORDER BY clause: ソート基準となるORDER BY句を指定します(省略可能)。 ### ウィンドウ関数一覧 #### LAG パーティションごとのウィンドウからN行前の値を取得します。 対象行がなければNULLを返します。 ``` LAG(column_name, N) OVER ([PARTITION BY column_name] [ORDER BY column_name]) ``` ``` Mach> CREATE LOG TABLE lag_table (name varchar(10), dt datetime, value INTEGER); Created successfully. Mach> INSERT INTO lag_table VALUES('name1', TO_DATE('2024-01-01'), 1); 1 row(s) inserted. Mach> INSERT INTO lag_table VALUES('name1', TO_DATE('2024-01-02'), 2); 1 row(s) inserted. Mach> INSERT INTO lag_table VALUES('name1', TO_DATE('2024-01-03'), 3); 1 row(s) inserted. -- Divide the set by name, sort by dt, and retrieve the first previous value. Mach> SELECT name, dt, value, LAG(value, 1) OVER(PARTITION BY name ORDER BY dt) FROM lag_table; name dt value LAG(value, 1) --------------------------------------------------------------------------- name1 2024-01-01 00:00:00 000:000:000 1 NULL name1 2024-01-02 00:00:00 000:000:000 2 1 name1 2024-01-03 00:00:00 000:000:000 3 2 [3] row(s) selected. ``` #### LEAD パーティションごとのウィンドウからN行後の値を取得します。 対象行がなければNULLを返します。 ``` LEAD(column_name, N) OVER ([PARTITION BY column_name] [ORDER BY column_name]) ``` ``` Mach> CREATE LOG TABLE lead_table (name varchar(10), dt datetime, value INTEGER); Created successfully. Mach> INSERT INTO lead_table VALUES('name1', TO_DATE('2024-01-01'), 1); 1 row(s) inserted. Mach> INSERT INTO lead_table VALUES('name1', TO_DATE('2024-01-02'), 2); 1 row(s) inserted. Mach> INSERT INTO lead_table VALUES('name1', TO_DATE('2024-01-03'), 3); 1 row(s) inserted. -- Divide the set by name, sort by dt, and retrieve the first and subsequent values. Mach> SELECT name, dt, value, LEAD(value, 1) OVER(PARTITION BY name ORDER BY dt) FROM lead_table; name dt value LEAD(value, 1) ---------------------------------------------------------------------------- name1 2024-01-01 00:00:00 000:000:000 1 2 name1 2024-01-02 00:00:00 000:000:000 2 3 name1 2024-01-03 00:00:00 000:000:000 3 NULL [3] row(s) selected. ``` #### NTILE `NTILE(n)`はソートされた行を可能な限り均等に`n`個のバケットへ分け、各行が属するバケット番号を返します。 ``` NTILE(n) OVER ([PARTITION BY column_name] ORDER BY column_name) ``` - `n`は正の定数である必要があります。 - `OVER (...)`内の`ORDER BY`は必須です。 - 行数が均等に分かれない場合、先頭側のバケットが1行ずつ多くなります。 ``` Mach> SELECT user_id, score, NTILE(4) OVER (ORDER BY score) AS score_band FROM exam_result; ``` --- title: "16.1.4 相対時間式" url: https://docs.machbase.com/ja/dbms/reference/sql/relative-time/ language: ja kind: page --- # 16.1.4 相対時間式 相対時間式を使用すると、`NOW`や`SYSDATE`などの基準時点からの差をSQL文に直接記述できます。関数を別途呼び出さず、時系列ウィンドウを簡潔に表す場合に便利です。 > 相対時間リテラル(`now - 1h`形式)はMachbase 8.0.50以降でサポートします。月/年単位の調整には`ADD_TIME`、文字列の変換には`TO_DATE`を使用します。 ## クイックリファレンス | 式 | 例 | 説明 | |------|------|------| | `NOW` / `now` | `now` | 現在時刻(ナノ秒精度) | | `SYSDATE` / `sysdate` | `sysdate` | 現在時刻(`NOW`と同じ) | | `now - offset` | `now - 1h` | 現在時刻からオフセットを減算 | | `now + offset` | `now + 30m` | 現在時刻にオフセットを加算 | | ナノ秒整数の直接使用 | `value + 1000000000` | ナノ秒単位の整数をDATETIMEへ加算 | ## 相対時間単位(リテラルの接尾辞) | 接尾辞 | 意味 | 例 | |--------|------|------| | `ns` | ナノ秒 | `500ns` | | `us` | マイクロ秒 | `20us` | | `ms` | ミリ秒 | `15ms` | | `s` | 秒 | `45s` | | `m` | 分 | `30m` | | `h` | 時間 | `12h` | | `d` | 日 | `7d` | | `w` | 週 | `2w` (= 14日) | > 月(`month`、`mo`)と年(`year`、`y`)の接尾辞は非対応です。暦上の月や年を移動するには > `ADD_TIME()`を使用します。`30d`と`365d`は固定の日数のため、暦上の1か月・1年と常に一致するとは限りません。 ## ADD_TIME関数 月・年など、相対時間リテラルにない暦の調整には`ADD_TIME()`を使用します。引数、形式、エラー条件は [SQL関数辞典](../functions/functions-full/#add_time)を参照してください。 ## TO_DATE関数 参照区間の開始と終了を日付文字列で指定するときは、`TO_DATE()`でDATETIME値を作成します。 日付形式と変換エラーは[SQL関数辞典](../functions/functions-full/#to_date)を参照してください。 ## 利用パターン ### 時間区間の絞り込み ```sql -- 直近1時間のデータ(相対時間リテラル) SELECT * FROM sensor_tag WHERE time > now - 1h; -- 直近1時間のデータ(ADD_TIME関数) SELECT * FROM sensor_tag WHERE time > ADD_TIME(now, '0/0/0 -1:0:0'); -- 直近24時間の記録 SELECT * FROM app_log WHERE _arrival_time BETWEEN now - 1d AND now; -- 直近10分以内のアラーム SELECT alert_id, level, occurred_at FROM alert_log WHERE occurred_at >= sysdate - 10m; ``` ### 複合時間式 ```sql -- 2日6時間15分後 SELECT * FROM maintenance_plan WHERE planned_at < now + 2d6h15m; -- 秒未満の単位の組み合わせ SELECT TO_CHAR(now + 3s125ms10us4ns, 'YYYY-MM-DD HH24:MI:SS mmm:uuu:nnn'); ``` ### TO_DATE結果へのオフセット適用 ```sql -- 日付文字列に3日を加算 SELECT TO_CHAR(TO_DATE('2024-05-01', 'YYYY-MM-DD') + 3d, 'YYYY-MM-DD'); -- 結果: 2024-05-04 -- 日付文字列から4時間15分を減算 SELECT TO_CHAR( TO_DATE('2024-05-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS') - 4h15m, 'YYYY-MM-DD HH24:MI:SS' ); -- 結果: 2024-05-01 03:45:00 ``` ### ナノ秒整数の直接使用 数値リテラルはナノ秒として解釈します。 ```sql -- 1秒 = 1,000,000,000ナノ秒 SELECT event_time + 1000000000 AS event_time_plus_1s FROM events; -- 250ナノ秒を減算 SELECT event_time - 250 AS event_time_minus_250ns FROM events; ``` ## 制約 - 相対時間リテラル(`1h`、`30m`など)はMachbase 8.0.50以降でのみサポートします。 - 月(`mo`)と年(`y`)単位のリテラルは非対応です。`ADD_TIME()`の年/月の位置を使用してください。 - 文字列リテラルはinterval演算でDATETIMEへ暗黙変換されないため、先に`TO_DATE()`で変換してください。 - インターバル自体は`ORDER BY`句では使用できません。 ## エラー処理 | 状況 | エラー | 対処方法 | |------|------|-----------| | 非対応の接尾辞(`1y`, `5mo`) | `ERR-02034` invalid time expression | 暦単位には`ADD_TIME()`、固定期間には`d`などの対応する接尾辞を使用 | | 単位の省略(`now + 10`) | ナノ秒として解釈 | 意図する単位の接尾辞を明示 | | 大きすぎる値(`1000000d`) | `ERR_OVERFLOW_INTERVAL` | 値の範囲を縮小 | ## LOGのDURATION 相対時間リテラルとDURATIONは役割が異なります。`event_time >= now - 1h`は選択列のWHERE条件で、 DURATIONはLOGの`_arrival_time`範囲を指定します。TAGの時間列やユーザー定義DATETIME列にはWHERE条件を使用してください。 ```text SELECT ... FROM log_table [WHERE ...] DURATION n unit [BEFORE base_time | AFTER base_time] [GROUP BY ...] [HAVING ...] [ORDER BY ...] [LIMIT ...] SELECT ... FROM log_table [WHERE ...] DURATION FROM from_time TO to_time [GROUP BY ...] [HAVING ...] [ORDER BY ...] [LIMIT ...] ``` 上記は基本形式です。期間には`HOUR`、`MINUTE`、`DAY`などの単位を使用します。全範囲を表す`ALL`も使用できます。 DURATIONはWHEREの後、GROUP BY・ORDER BYの前に置きます。 | 形式 | 範囲 | 指定されるスキャン方向 | |---|---|---| | DURATION 1 HOUR | 現在時刻を基準とする直近1時間 | 新しい順 | | DURATION 1 HOUR BEFORE t | t−1時間からtまで | 新しい順 | | DURATION 1 HOUR AFTER t | tからt+1時間まで | 古い順 | | DURATION FROM a TO b, a < b | aからbまで | 古い順 | | DURATION FROM a TO b, a > b | bからaまで | 新しい順 | 範囲の両端を含みます。FROMとTOが同時刻なら、その時刻の行が対象です。スキャン方向と結合・集計後の 最終出力順は区別してください。結果順序が必要な場合はORDER BYを明示し、同時刻の複数行には追加のソートキーを指定します。 次の例では、終了時刻にある2番の行も選択されます。 ```sql CREATE LOG TABLE ch7_ref_duration (event_id INTEGER); INSERT INTO ch7_ref_duration(_arrival_time, event_id) VALUES (TO_DATE('2026-01-01 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1); INSERT INTO ch7_ref_duration(_arrival_time, event_id) VALUES (TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 2); SELECT event_id FROM ch7_ref_duration DURATION 1 HOUR BEFORE TO_DATE('2026-01-01 11:00:00', 'YYYY-MM-DD HH24:MI:SS') ORDER BY event_id; DROP TABLE ch7_ref_duration; ``` 結果は1・2番です。連続する区間を日別に分ける場合、 `WHERE _arrival_time >= 開始 AND _arrival_time < 終了`のように半開区間を使用すると、境界行の二重集計を防げます。 LOGとLOOKUPが混在するクエリでは、DURATIONの代わりにLOG列のWHERE範囲を使用してください。 ## 関連ドキュメント - [LOG時間範囲の演習](/ja/dbms/log-table-usage/query-analysis/) — 境界・ソート・結合結果の比較 - [相対時間式](/ja/dbms-8.5/sql-reference/time-expressions/) — 8.5リファレンスの詳細 --- title: "16.1.6 ROWID" url: https://docs.machbase.com/ja/dbms/reference/sql/rowid/ language: ja kind: page --- # 16.1.6 ROWID Machbase 8.7.0以降でサポート `ROWID`はテーブル内の1行を再検索するための64ビット識別子です。このページではSQLでの意味、 テーブル別の参照条件、INSERTの実行結果、有効期間を定義します。SDK別のアクセスAPIとコードは、 [SDK機能のサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/)と各言語のページを参照してください。 この機能はStandard Editionでサポートします。サーバーとSDKをROWIDに対応するバージョンへ一緒に 更新してください。Cluster Editionでは使用できません。 ## ROWIDと業務キーの区別 ROWIDは現在のテーブルの保存行の位置を示す識別子であり、注文番号や機器IDなどの永続的な業務キーではありません。 - 通常の列ではないため`SELECT *`には含まれません。必要な場合は明示的に選択してください。 - 他のテーブルのROWIDと比較したり、他のテーブルの参照に使用したりしないでください。 - ROWID値を分解したり算術演算に使用したりしないでください。 - 数値の大小はテーブル全体の取り込み順序を意味しません。 - 新規テーブルには`ROWID`という実列を定義できません。 - 旧バージョンで実際の`ROWID`列を作成したテーブルでは、その列を優先します。ROWID疑似列を使用するには既存列の名前を変更してください。 ```sql SELECT ROWID, name, time, value FROM sensor_tag WHERE name = 'TAG-01'; ``` ## テーブル別のサポート範囲 | テーブル | ROWIDの意味 | 参照条件 | 単一行INSERTの結果 | |--------|--------------|-----------|------------------| | LOG | 保存されたログ行の識別子 | `=`, `<`, `<=`, `>`, `>=`, `BETWEEN`, `ORDER BY` | 生成されたROWIDを返す | | TAG | 保存された元のTAG行の識別子 | 最上位の`AND`に含む単一の`ROWID = 値` | 生成されたROWIDを返す | | TRANSACTION | 単一の`LONG`/`INT64` PRIMARY KEY値 | 既存PKがサポートする条件 | PK値をROWIDとして返す | | LOOKUP | 単一の`LONG`/`INT64` PRIMARY KEY値 | 既存PKがサポートする条件 | PK値をROWIDとして返す | | VOLATILE | 単一の`LONG`/`INT64` PRIMARY KEY値 | 既存PKがサポートする条件 | PK値をROWIDとして返す | TRANSACTION、LOOKUP、VOLATILEでは、`AUTO_INCREMENT`の使用に関係なく、値が`0`以上の単一 `LONG`/`INT64` PRIMARY KEYをROWIDとして使用します。アプリケーションがPK値を指定した場合はその値を、 `AUTO_INCREMENT` PKを省略またはNULLにした場合はサーバーが生成した値を返します。負数のPKはROWIDとして使用できません。 LOGとTAGのROWIDは`0..UINT64_MAX-1`、3つのPRIMARY KEYベースのテーブルは`0..INT64_MAX`の範囲です。 `0`は有効な値で、`UINT64_MAX`はROWIDとして使用できません。 ### LOGの参照 LOGのROWIDは範囲参照とソートに使用できます。`_ARRIVAL_TIME`は複数行で同じ値になる場合があるため、 特定行の再検索にはROWIDを使用します。 ```sql SELECT ROWID, message FROM app_log WHERE ROWID >= ? AND ROWID < ? ORDER BY ROWID; ``` `ROWID IN (...)`はサポートしません。 ### TAGの参照 TAGは単一ROWIDの等値参照のみをサポートします。タグ名、時刻、値の条件を`AND`で併用でき、 すべての条件を満たす行だけを返します。 ```sql SELECT ROWID, name, time, value FROM sensor_tag WHERE ROWID = ? AND name = 'TAG-01' AND time >= TO_DATE('2026-08-10 00:00:00', 'YYYY-MM-DD HH24:MI:SS'); ``` TAG ROWIDの条件のサポート可否は次のとおりです。 | 使用方法 | サポート | |--------|:---------:| | `ROWID = ?` | O | | `ROWID > ?`、`BETWEEN`などの範囲条件 | X | | `ROWID IN (...)` | X | | `ROWID = ? OR ...` | X | | `ORDER BY ROWID` | X | | `DELETE ... WHERE ROWID = ?` | X | | rollup、custom rollup、statの結果との組み合わせ | X | ### TRANSACTION、LOOKUP、VOLATILEの比較 次の3つのテーブルは同じ`AUTO_INCREMENT`宣言を使用できますが、再起動時の動作と取り込み機能は異なります。 ```sql CREATE TRANSACTION TABLE orders ( id LONG PRIMARY KEY AUTO_INCREMENT, item VARCHAR(100) ); CREATE LOOKUP TABLE lookup_orders ( id LONG PRIMARY KEY AUTO_INCREMENT, item VARCHAR(100) ); CREATE VOLATILE TABLE volatile_orders ( id LONG PRIMARY KEY AUTO_INCREMENT, item VARCHAR(100) ); ``` | 項目 | TRANSACTION | LOOKUP | VOLATILE | |------|-------------|--------|----------| | 再起動後に行と次の自動値を保持 | O | O | X | | 明示的トランザクション | O | X | X | | `INSERT ... SELECT`で自動値を生成 | O | X | X | | AUTO_INCREMENTテーブルのUPSERT | O (ROWID返却はX) | X | X | | 単一行`INSERT ... VALUES`の結果ROWID | O | O | O | LOOKUPの`PROPERTY(SEQUENCE)`と`NEXTVAL()`は`AUTO_INCREMENT`とは別の機能です。 同じ列に両方式を指定しないでください。 明示的トランザクション中はTRANSACTIONテーブルのDDLを実行できません。`CREATE TRANSACTION TABLE`が `ERR-02362`で失敗したら、先に`COMMIT`または`ROLLBACK`してから再実行します。 ### JOIN、集約、View JOIN結果全体を代表するROWIDはありません。必要なソーステーブルの別名ごとにROWIDを参照します。 ```sql SELECT a.ROWID AS order_rowid, b.ROWID AS item_rowid, a.customer, b.item FROM orders a JOIN order_items b ON a.id = b.order_id; ``` | 参照形式 | ROWIDの処理 | |-----------|------------| | JOIN | 必要なソーステーブルの別名ごとに`alias.ROWID`を指定 | | 集約、`GROUP BY`、`DISTINCT`、集合演算 | 結果行に新しいROWIDを生成しない | | View, CTE, inline view | 内部SELECTでROWIDを明示的に選択した場合のみ伝播 | ## INSERT結果でROWIDを受け取る条件 `INSERT ... RETURNING ROWID`構文は使用しません。対応するSDKは、成功した単一行の `INSERT ... VALUES`の実行結果にROWIDも含めて返します。 | 取り込み方法 | generated ROWID | 説明 | |-----------|:---------------:|------| | 単一行の直接`INSERT ... VALUES` | O | 1行の作成が成功した場合 | | 単一行のプリペアドINSERT | O | 実行ごとに現在の結果を返す | | `INSERT ... SELECT` | X | 複数行を作成する可能性があるため単一値を返さない | | execute-array, batch, `executemany()` | X | 内部の最終行を代表値として公開しない | | Append API, append batch | X | 高速取り込み経路では返さない | | loader | X | ファイル取り込み経路では返さない | | UPSERT | X | INSERTまたはUPDATEの結果を単一ROWIDで代表しない | | 失敗したINSERT | X | 前回の実行のROWIDも消去 | 生成されたROWIDはステートメントごとの結果です。接続全体の最新値を参照するSQL関数は提供しません。 ## 参照結果とエラーの区別 形式が正しいROWIDが現在のテーブルになければ、エラーではなく0行を返します。削除済みの行や追加条件を 満たさない行も同様です。一方、NULL、負数のPK、`UINT64_MAX`、数値へ変換できない値、TAGで非対応の 範囲・IN・OR・ソート条件はエラーです。 ## 有効期間と再試行 ROWIDを長期保存する業務キーとして使用しないでください。 | 状況 | 既存のROWID | |------|------------| | 正常な再起動 | 保持された行では維持 | | ROWIDの保持に対応する製品のバックアップ/復元 | 保持された行では維持 | | 行のDELETE | 無効 | | transaction ROLLBACK | 該当INSERTのROWIDは無効 | | スナップショット復旧で破棄された行 | 無効 | | LOG TRUNCATE | 以前の値が再利用される場合がある | | テーブルのDROP後の再作成 | 以前の値が別の行を指す場合がある | | エクスポート/インポートまたは行の再挿入 | 保持しない | INSERTが成功してもネットワーク応答が失われると、アプリケーションがROWIDを受け取れない場合があります。 同じINSERTを自動再試行すると重複行が生じる可能性があるため、業務キーや別途の冪等性ポリシーで 実際の反映状態を先に確認してください。 ## 関連ドキュメント - [SDK機能のサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/) - [AUTO_INCREMENT](/ja/dbms/reference/sql/syntax/auto-increment-syntax/) - [LOGデータの取り込み](/ja/dbms/log-table-usage/data-input-mutation/) - [TAGデータの取り込み](/ja/dbms/tag-table-usage/data-input-mutation/) --- title: "16.2 設定リファレンス" url: https://docs.machbase.com/ja/dbms/reference/configuration/ language: ja kind: section --- # 16.2 設定リファレンス Machbaseサーバーは、`$MACHBASE_HOME/conf/machbase.conf`に定義されたプロパティで動作を制御します。 このセクションでは、各プロパティの許容範囲とデフォルト値を確認できます。 ## 下位セクション | セクション | 説明 | |------|------| | [設定プロパティ辞典](./configuration/) | サーバーの基本設定、性能、セキュリティ、ログなど、Standard Editionの全プロパティ一覧 | | [クラスター設定プロパティ辞典](./configuration-2/) | Cluster Edition専用のCoordinator、Broker、Warehouse設定 | | [PVO Cacheプロパティ辞典](./pvo-cache/) | SQL実行計画キャッシュ(PVO Statement Cache)のプロパティ | | [タイムゾーン設定辞典](./configuration-timezone/) | タイムゾーンのプロパティとクライアント別の設定方法 | ## プロパティの確認方法 サーバー実行中のプロパティ値は、`v$property`システムビューで確認します。 ```sql -- すべてのプロパティを参照 SELECT name, value, type FROM v$property ORDER BY name; -- 特定のプロパティを参照 SELECT name, value, min, max FROM v$property WHERE name = 'PORT_NO'; ``` ## 動的に変更できるプロパティ 一部のプロパティは、サーバーを再起動せずに`ALTER SYSTEM SET`で変更できます。 ```sql ALTER SYSTEM SET TRACE_LOG_LEVEL = 3; ALTER SYSTEM SET PVO_CACHE_MAX_MEMORY_SIZE = 536870912; ``` 変更後に`v$property`を参照して適用を確認します。再起動が必要なプロパティを動的に変更すると、エラーが返されます。 --- title: "16.2.1 設定プロパティ辞典" url: https://docs.machbase.com/ja/dbms/reference/configuration/configuration/ language: ja kind: page --- # 16.2.1 設定プロパティ辞典 `$MACHBASE_HOME/conf/machbase.conf`で設定するStandard Editionの主なプロパティの辞典です。 特に記載がない場合はサーバーの再起動が必要です。 ## サーバーの基本設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `PORT_NO` | 5656 | 1024~65535 | クライアントのTCP/IP接続ポート | | `BIND_IP_ADDRESS` | 0.0.0.0 | - | クライアントリスナーのバインドIP。`0.0.0.0`はすべてのインターフェース | | `GRANT_REMOTE_ACCESS` | 1 | 0~1 | リモート接続の許可。0はローカル接続のみ許可 | | `MAX_SESSION_COUNT` | 4096 | 64~2^64-1 | 同時セッションの最大数 | | `MAX_STMT_COUNT_PER_SESSION` | 1024 | 512~2^32-1 | セッション当たりの最大ステートメント数 | | `SESSION_IDLE_TIMEOUT_SEC` | 0 | 0~2^64-1 | セッションのアイドルタイムアウト(秒)。0は無効 | | `SESSION_QUERY_TIMEOUT_SEC` | 0 | 0~2^64-1 | クエリ実行タイムアウト(秒)。0は無効 | | `UNIX_PATH` | machbase-unix | - | Unixドメインソケットのファイル名 | | `DBS_PATH` | ?/dbs | - | データベースファイルの保存先(`?`は`$MACHBASE_HOME`) | | `PID_PATH` | ?/conf | - | PIDファイルの保存先 | ## CPU / スレッド設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `CPU_COUNT` | 1 | 0~2^32-1 | 使用するCPU数。0はすべて使用 | | `CPU_PARALLEL` | 1 | 1~2^32-1 | CPU当たりの並列スレッド数 | | `CPU_AFFINITY_BEGIN_ID` | 0 | 0~2^32-1 | CPUアフィニティの開始番号 | | `CPU_AFFINITY_COUNT` | 0 | 0~2^32-1 | CPUアフィニティで使用するCPU数。0はすべて | | `DISK_IO_THREAD_COUNT` | 3 | 1~2^32-1 | ディスクI/Oスレッド数 | | `INDEX_BUILD_THREAD_COUNT` | 3 | 0~2^32-1 | インデックス構築スレッド数。0はインデックスを作成しない | | `INDEX_LEVEL_PARTITION_BUILD_THREAD_COUNT` | 3 | 1~1024 | LSMインデックスのマージスレッド数 | | `INDEX_LEVEL_PARTITION_AGER_THREAD_COUNT` | 1 | 1~1024 | LSMインデックスの不要ファイル削除スレッド数 | | `QUERY_PARALLEL_FACTOR` | 0 | 0~100 | 並列クエリ実行スレッド数。Standardのデフォルト値は0、Clusterは4 | ## メモリ設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `PROCESS_MAX_SIZE` | 8GB | 1GB~2^64-1 | サーバープロセスの最大メモリ(バイト)。配布サンプルでは`16GB`の場合がある | | `DISK_COLUMNAR_TABLESPACE_MEMORY_MAX_SIZE` | 8GB | 256MB~2^64-1 | LOGテーブルの入力バッファー上限。総メモリ予算内で調整 | | `DISK_COLUMNAR_TABLESPACE_MEMORY_MIN_SIZE` | 100MB | 1MB~2^64-1 | サーバー起動時に事前確保するメモリ | | `DISK_COLUMNAR_TABLESPACE_MEMORY_EXT_SIZE` | 2MB | 1MB~2^64-1 | 列パーティションのメモリブロックサイズ | | `DISK_COLUMNAR_TABLESPACE_DWFILE_INT_SIZE` | 2MB | 1MB~2^32-1 | データの整合性/復旧用ダブルライトファイルの初期サイズ | | `DISK_COLUMNAR_TABLESPACE_DWFILE_EXT_SIZE` | 1MB | 1MB~2^32-1 | ダブルライトファイルの拡張サイズ | | `DISK_COLUMNAR_PAGE_CACHE_MAX_SIZE` | 2GB | 0~2^64-1 | ページキャッシュの最大サイズ(バイト) | | `VOLATILE_TABLESPACE_MEMORY_MAX_SIZE` | 2GB | 0~2^64-1 | Volatile/Lookupテーブル全体のメモリ上限 | | `MAX_QPX_MEM` | 1GB | 1MB~2^64-1 | GROUP BY/ORDER BYなどのクエリ処理の最大メモリ | | `MEMORY_ROW_TEMP_TABLE_PAGESIZE` | 32768 | 8KB~2^32-1 | Volatile/Lookup一時テーブルのページサイズ(バイト) | ## ディスクI/O設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `DISK_BUFFER_COUNT` | 16 | 1~2^32-1 | ディスクI/Oバッファー数 | | `DISK_TABLESPACE_DIRECT_IO_WRITE` | 1 | 0~1 | 書き込みのDirect I/Oの有効化。ZFSなど非対応のファイルシステムでは0に設定 | | `DISK_TABLESPACE_DIRECT_IO_READ` | 0 | 0~1 | 読み取りのDirect I/Oの有効化 | | `DISK_TABLESPACE_DIRECT_IO_FSYNC` | 0 | 0~1 | Direct I/Oでのfsyncの有効化 | | `DISK_TABLESPACE_SYNCHRONOUS` | 1 | 0~3 | 同期ポリシー。0=OFF, 1=NORMAL, 2=FULL, 3=EXTRA | | `DISK_COLUMNAR_TABLE_COLUMN_PART_IO_INTERVAL_MIN_SEC` | 3 | 0~2^32-1 | パーティションファイルをディスクへ反映する間隔(秒) | | `DISK_COLUMNAR_TABLE_COLUMN_PART_FLUSH_MODE` | 0 | 0~1 | 列パーティションが満杯になったときだけフラッシュするかどうか | | `DISK_COLUMNAR_TABLE_CHECKPOINT_INTERVAL_SEC` | 120 | 1~2^32-1 | テーブルのチェックポイント間隔(秒) | | `DISK_COLUMNAR_INDEX_CHECKPOINT_INTERVAL_SEC` | 120 | 1~2^32-1 | インデックスのチェックポイント間隔(秒) | | `DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE` | 1 | 0~1 | LOGの時刻逆転時、1=直前の時刻+1nsに補正、0=入力を拒否 | | `DISK_COLUMNAR_TABLESPACE_MEMORY_SLOWDOWN_HIGH_LIMIT_PCT` | 80 | 0~100 | メモリ使用量のしきい値(%)。超過時は入力速度を低下 | | `DISK_COLUMNAR_TABLESPACE_MEMORY_SLOWDOWN_MSEC` | 1 | 0~2^32-1 | しきい値超過時のレコード当たりの待機時間(ms) | LOGの`DISK_COLUMNAR_TABLE_TIME_INVERSION_MODE=1`は、明示した過去の時刻をそのまま 保存するという意味ではありません。直前の`_ARRIVAL_TIME`より小さい値は補正されます。 同じ時刻はこの逆転条件に該当しないため、すべての行の時刻が一意になるわけでもありません。 移行時には[時間モデル](/ja/dbms/log-table-usage/arrival-time-model/)のソート順と対象の状態も確認してください。 ## インデックス設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `DEFAULT_LSM_MAX_LEVEL` | 2 | 0~3 | LSMインデックスのデフォルト最大レベル | | `INDEX_BUILD_MAX_ROW_COUNT_PER_THREAD` | 100000 | 1~2^32-1 | インデックス構築を開始する未インデックスレコード数 | | `INDEX_FLUSH_MAX_REQUEST_COUNT_PER_INDEX` | 3 | 1~2^32-1 | インデックス当たりの最大フラッシュ要求数 | | `INDEX_LEVEL_PARTITION_BUILD_MEMORY_HIGH_LIMIT_PCT` | 70 | 0~100 | LSMインデックス構築時の最大メモリ使用率(%) | | `DISK_COLUMNAR_INDEX_SHUTDOWN_BUILD_FINISH` | 0 | 0~1 | 終了時にすべてのインデックスをディスクへ反映するかどうか | | `DISK_COLUMNAR_INDEX_FDCACHE_COUNT` | 0 | 0~2^32-1 | オープンするインデックスパーティションのファイル記述子数 | | `DISK_COLUMNAR_TABLE_COLUMN_FDCACHE_COUNT` | 0 | 0~2^32-1 | オープンする列のファイル記述子数 | | `DISK_COLUMNAR_TABLE_COLUMN_MINMAX_CACHE_SIZE` | 100MB | 0~2^64-1 | `_ARRIVAL_TIME`列のMINMAXキャッシュサイズ(バイト) | ## TAGテーブル設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `TAG_CACHE_ENABLE` | 31 | 0~31 | TAGキャッシュの使用範囲(ビットOR)。0=無効, 1=map, 2=row, 4=data file, 8=varchar file, 16=delete vector | | `TAG_CACHE_MAX_MEMORY_SIZE` | 512MB | 32KB~2^64-1 | TAGキャッシュプール1つ当たりの最大メモリ(バイト) | | `TAG_CACHE_POOL_COUNT` | 1 | 1~128 | TAGキャッシュプール数。総上限 = `TAG_CACHE_MAX_MEMORY_SIZE × TAG_CACHE_POOL_COUNT` | | `TAG_MEMORY_INDEX_TYPE` | 1 | 0~1 | メモリインデックスの種類。0=RBTree, 1=BTree | | `TAG_MEMORY_INDEX_PANOUT` | 255 | 127~65536 | B-Treeインデックスの次数。`TAG_MEMORY_INDEX_TYPE=1`で適用 | | `TAGDATA_AUTO_META_INSERT` | 2 | 0~2 | TAG_NAMEが存在しない場合の処理。0=失敗、1=名前のみ挿入、2=メタデータを含めて挿入 | | `TAG_TABLE_META_MAX_SIZE` | 524288000 | 1MB~2^32-1 | TAGDATAテーブルのメタデータの最大メモリ(バイト) | | `TAG_PARTITION_COUNT` | 4 | 1~1024 | TagテーブルのKey Valueパーティション数 | | `TAG_DATA_PART_SIZE` | 16MB | 1MB~1GB | Tagデータパーティションサイズ(バイト) | | `ROLLUP_FETCH_COUNT_LIMIT` | 3000000 | 0~2^32-1 | ロールアップスレッドが1回にフェッチするデータ数。0は無制限 | ## セキュリティ設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `ENABLE_CASE_SENSITIVE_PASSWORD` | 0 | 0~1 | パスワードの大文字小文字の区別。0は大文字に変換 | ## セッション / クエリ設定 `TABLE_SCAN_DIRECTION`はTAG専用の設定ではありません。LOGなど、スキャン方向を使用する クエリにも影響する場合があります。最終出力のソート順も保証しません。 出力順序はORDER BYで指定し、実際のアクセスパスはEXPLAINで確認してください。 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `TABLE_SCAN_DIRECTION` | 0 | -1~1 | -1=逆方向、0=テーブルタイプのデフォルト値、1=順方向 | | `DDL_LOCK_TIMEOUT` | 0 | 0~1000000 | Standard EditionのDDLロック待機時間(秒)。0は即座にエラーを返す | | `SHOW_HIDDEN_COLS` | 0 | 0~1 | `SELECT *`で`_ARRIVAL_TIME`列を表示するかどうか | | `DURATION_BEGIN` | 0 | 0~2^32-1 | `DURATION`を指定しないSELECTのデフォルト開始オフセット(秒) | | `DURATION_GAP` | 0 | 0~2^31-1 | `DURATION`を指定しないSELECTのデフォルト期間(秒) | | `LOOKUP_APPEND_UPDATE_ON_DUPKEY` | 0 | 0~1 | LookupテーブルへのAppend時の重複キー処理。0=失敗、1=UPDATE | | `LIN_HASH_BIT_SIZE` | 7 | 1~31 | 内部リニアハッシュの初期バケットビット数 | `machbase.conf`の`DDL_LOCK_TIMEOUT`は、サーバー再起動後に新規セッションへコピーされます。 現在のセッションの値は`ALTER SESSION SET DDL_LOCK_TIMEOUT = seconds`で変更し、`V$SESSION`で確認します。 Cluster Editionではこのプロパティを提供しません。 ## TRANSACTION設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `TRANSACTION_BUSY_TIMEOUT_MS` | 30000 | -1~2147483647 | 再試行可能なTRANSACTIONロック競合の待機時間(ms)。-1はキャンセル・解除まで待機、0は即座に返す | | `TRANSACTION_SYNCHRONOUS` | 2 | 1~2 | TRANSACTIONテーブルのトランザクション永続性レベル。1=NORMAL, 2=FULL | | `TRANSACTION_JOURNAL_MODE` | 4 | 0~4 | TRANSACTIONのジャーナルモード。0=DELETE, 4=WAL | 新規セッションはサーバーのTRANSACTION_BUSY_TIMEOUT_MSをコピーします。現在の接続では ALTER SESSIONで変更できます。この値は、すべてのbusyエラーの最小待機時間を保証しません。 WALで古い読み取りスナップショットを書き込みに切り替える際の競合は、-1でも即座に返される場合があります。 この場合は同じ文を繰り返さず、ROLLBACKして新しいトランザクションで読み取りと判断からやり直してください。 [2つの接続を使う演習](/ja/dbms/rdb-table-usage/locking-conflict-timeout/)では、 一時的な書き込みロックとスナップショットの競合を比較できます。 ## ログ / 診断設定 | プロパティ | デフォルト値 | 範囲 | 説明 | |----------|--------|------|------| | `TRACE_LOG_LEVEL` | 277 | 0~2^32-1 | トレースログの詳細レベル。値が大きいほど詳細 | | `TRACE_LOGFILE_PATH` | ?/trc | - | トレースログファイルの保存先 | | `TRACE_LOGFILE_SIZE` | 10MB | 1MB~2^32-1 | トレースログファイルの最大サイズ(バイト) | | `TRACE_LOGFILE_COUNT` | 1000 | 1~2^32-1 | トレースログファイルの最大数 | | `DUMP_TRACE_INFO` | 300 | 0~2^32-1 | DBMSの状態をtrcに記録する間隔(秒)。0は無効 | | `DUMP_APPEND_ERROR` | 0 | 0~1 | Append APIのエラーをtrcに記録するかどうか。テスト目的のみの使用を推奨 | | `FEEDBACK_APPEND_ERROR` | 1 | 0~1 | Appendのエラーデータをクライアントに送信するかどうか | | `GEN_CORE_FILE` | 1 | 0~1 | 異常終了時のcoreファイル生成の有効化 | | `GEN_CALLSTACK_FOR_ABORT_ERROR` | 0 | 0~1 | 異常終了時のコールスタック記録の有効化 | ## プロパティの参照例 ```sql -- 現在適用されているすべてのプロパティ値を参照 SELECT name, value, type FROM v$property ORDER BY name; -- 特定のプロパティの詳細を参照 SELECT name, value, min, max FROM v$property WHERE name = 'MAX_SESSION_COUNT'; ``` 動的に変更できるプロパティは、サーバーを再起動せずに`ALTER SYSTEM SET`で変更できます。 ```sql ALTER SYSTEM SET TRACE_LOG_LEVEL = 3; ALTER SYSTEM SET SESSION_QUERY_TIMEOUT_SEC = 30; ``` --- title: "16.2.2 クラスター設定プロパティ辞典" url: https://docs.machbase.com/ja/dbms/reference/configuration/configuration-2/ language: ja kind: page --- # 16.2.2 クラスター設定プロパティ辞典 Cluster Editionでは、`$MACHBASE_COORDINATOR_HOME/conf/`、`$MACHBASE_BROKER_HOME/conf/`、`$MACHBASE_WAREHOUSE_HOME/conf/`にある各ノードの設定ファイルでクラスターの動作を制御します。 このページでは、運用時に頻繁に確認する主なクラスターのプロパティを示します。 ## Coordinator 設定 Coordinatorは、クラスター全体のメタデータとノードの状態を管理します。 | プロパティ | デフォルト値 | 説明 | |----------|--------|------| | `CLUSTER_LINK_HOST` | - | CoordinatorがバインドするIPアドレス | | `CLUSTER_LINK_PORT_NO` | 3868 | クラスター内部通信ポート | | `CLUSTER_LINK_THREAD_COUNT` | 16 | クラスターリンク処理スレッド数 | | `CLUSTER_LINK_MAX_LISTEN` | 512 | クラスターリンクの最大listen接続数 | | `CLUSTER_LINK_MAX_POLL` | 4096 | クラスターリンクの最大pollイベント数 | | `CLUSTER_LINK_BUFFER_SIZE` | 33554432 | クラスターリンクのバッファーサイズ(バイト)。デフォルトは32MB | | `HTTP_ADMIN_PORT` | 5779 | Coordinator/Deployer管理RESTポート | | `HTTP_THREAD_COUNT` | 2 | 管理RESTリクエスト処理スレッド数 | `HTTP_ADMIN_PORT`は環境変数`MACHBASE_HTTP_ADMIN_PORT`でも指定できます。このポートは クラスターの管理リクエスト専用であり、SQLクエリやデータ入力には使用しません。 ## クラスターリンクのタイムアウト設定 すべての値の単位はマイクロ秒(μs)です。 | プロパティ | デフォルト値(μs) | 説明 | |----------|-----------|------| | `CLUSTER_LINK_ACCEPT_TIMEOUT` | 5000000 | acceptタイムアウト(5秒) | | `CLUSTER_LINK_CHECK_INTERVAL` | 1000000 | 接続状態の確認間隔(1秒) | | `CLUSTER_LINK_CONNECT_RETRY_TIMEOUT` | 60000000 | 接続再試行の最大時間(60秒) | | `CLUSTER_LINK_CONNECT_TIMEOUT` | 5000000 | 接続タイムアウト(5秒) | | `CLUSTER_LINK_HANDSHAKE_TIMEOUT` | 5000000 | ハンドシェイクタイムアウト(5秒) | | `CLUSTER_LINK_RECEIVE_TIMEOUT` | 30000000 | 受信タイムアウト(30秒) | | `CLUSTER_LINK_SEND_TIMEOUT` | 30000000 | 送信タイムアウト(30秒) | | `CLUSTER_LINK_REQUEST_TIMEOUT` | 60000000 | リクエストタイムアウト(60秒) | | `CLUSTER_LINK_SESSION_TIMEOUT` | 3600000000 | セッションタイムアウト(1時間) | | `CLUSTER_LINK_LONG_WAIT_INTERVAL` | 1000000 | 長時間待機の間隔(1秒) | | `CLUSTER_LINK_LONG_TERM_CALLBACK_INTERVAL` | 1000000 | 長期コールバック間隔(1秒) | ## Broker 設定 Brokerはクライアントのクエリを受け付け、Warehouseに分散して処理します。Brokerの`machbase.conf`には サーバー共通の設定とクラスター設定を指定します。サポートするプロパティとデフォルト値はEditionと ノードの役割によって異なるため、Standard Editionの設定ファイルをそのまま適用しないでください。 | プロパティ | デフォルト値 | 説明 | |----------|--------|------| | `PORT_NO` | 5656 | クライアント接続ポート | | `QUERY_PARALLEL_FACTOR` | 4 | 並列クエリ処理スレッド数(Clusterのデフォルト値) | | `CLUSTER_LINK_HOST` | - | Brokerがクラスター通信にバインドするIP | | `CLUSTER_LINK_PORT_NO` | - | Brokerのクラスター通信ポート | ## Warehouse 設定 Warehouseは実データを保存・処理するノードです。ストレージ設定と併せて次のクラスター設定を 使用します。`DDL_LOCK_TIMEOUT`などStandard Edition専用のプロパティは、Cluster Editionでは サポートしません。 | プロパティ | デフォルト値 | 説明 | |----------|--------|------| | `PORT_NO` | 5656 | Warehouseのサービスポート | | `CLUSTER_LINK_HOST` | - | Warehouseがクラスター通信にバインドするIP | | `CLUSTER_LINK_PORT_NO` | - | Warehouseのクラスター通信ポート | | `DBS_PATH` | ?/dbs | Warehouseのデータファイル保存先 | ## クラスターの状態確認 `machcoordinatoradmin --configure`でクラスターの設定値を表示できます。 ```bash machcoordinatoradmin --configure ``` 特定の設定値だけを確認するには、`--configuration=name`オプションを使用します。 ```bash machcoordinatoradmin --configuration=decision ``` ## クラスターのポート構成例 単一ホストにクラスターを構成する場合のポート割り当て例です。 | ノード | サービスポート | HTTPポート | クラスターリンクポート | |------|------------|-----------|------------------| | Coordinator | - | 5102 | 5101 | | Deployer | - | - | 5201 | | Broker | 5757 | 5302 | 5301 | | Warehouse-A1 | 5400 | 5402 | 5401 | | Warehouse-A2 | 5500 | 5502 | 5501 | --- title: "16.2.3 PVO Cacheプロパティ辞典" url: https://docs.machbase.com/ja/dbms/reference/configuration/pvo-cache/ language: ja kind: page --- # 16.2.3 PVO Cacheプロパティ辞典 PVO Statement Cacheは、SQLの解析・検証・最適化の結果と実行計画を再利用し、繰り返し実行するSQLの 処理コストを削減します。公開の根拠がない略語の正式名称は定義しません。Standard Editionでのみ動作します。 ## プロパティ一覧 | プロパティ | デフォルト値 | 範囲 | 動的変更 | 説明 | |----------|--------|------|----------|------| | `PVO_CACHE_ENABLE` | 1 | 0~1 | 可 | PVO Cacheの有効化。0=無効、1=有効 | | `PVO_CACHE_MAX_MEMORY_SIZE` | 268435456 | 32768~2^64-1 | 可 | PVO Cache全体の最大メモリ(バイト)。デフォルトは256MB | | `PVO_CACHE_SHARD_COUNT` | 16 | 1~256 | 不可 | キャッシュのシャード数。変更にはサーバーの再起動が必要 | | `PVO_CACHE_MAX_SQL_ENTRIES` | 0 | 0~2^64-1 | 可 | キャッシュに保持するSQLエントリーの最大数。0=無制限 | | `PVO_CACHE_MAX_PLANS_PER_SQL` | 512 | 1~512 | 可 | SQL文1つ当たりの最大計画(ハンドル)数 | ## プロパティの詳細 ### PVO_CACHE_ENABLE PVO Statement Cacheを有効にするかどうかを設定します。 ``` PVO_CACHE_ENABLE = 1 ``` ### PVO_CACHE_MAX_MEMORY_SIZE PVO Cache全体が使用できる最大メモリサイズ(バイト)です。設定値は`PVO_CACHE_SHARD_COUNT`に従って均等に分配されます。 ``` PVO_CACHE_MAX_MEMORY_SIZE = 536870912 # 512MB ``` ### PVO_CACHE_SHARD_COUNT キャッシュ内部のシャード数です。初期化時のみ適用されるため、変更にはサーバーの再起動が必要です。 同時接続数が多い環境では、シャード数を増やすとロック競合を軽減できます。 ``` PVO_CACHE_SHARD_COUNT = 32 ``` ### PVO_CACHE_MAX_SQL_ENTRIES PVO Cacheに保持できるSQLエントリーの最大数です。0は無制限です。値を設定するとシャード数に応じて分配されます。 ``` PVO_CACHE_MAX_SQL_ENTRIES = 10000 ``` ### PVO_CACHE_MAX_PLANS_PER_SQL 1つのSQL文に対して保持できる実行計画の最大数です。同じSQLでも、バインドパラメーターの型により異なる計画が生成されることがあります。 ``` PVO_CACHE_MAX_PLANS_PER_SQL = 256 ``` ## 動的変更 サーバーを再起動せずに変更できるプロパティは、`ALTER SYSTEM SET`で適用します。 ```sql -- PVO Cacheを有効化 ALTER SYSTEM SET PVO_CACHE_ENABLE = 1; -- 最大メモリを512MBに変更 ALTER SYSTEM SET PVO_CACHE_MAX_MEMORY_SIZE = 536870912; -- SQLエントリー数を制限 ALTER SYSTEM SET PVO_CACHE_MAX_SQL_ENTRIES = 5000; ``` ## キャッシュの初期化 PVO Cacheを強制的に初期化するには、次のコマンドを使用します。 ```sql ALTER SYSTEM FLUSH PVO_CACHE; ``` ## キャッシュの状態確認 ```sql SELECT name, value FROM v$property WHERE name LIKE 'PVO_CACHE%' ORDER BY name; ``` --- title: "16.2.4 タイムゾーン設定辞典" url: https://docs.machbase.com/ja/dbms/reference/configuration/configuration-timezone/ language: ja kind: page --- # 16.2.4 タイムゾーン設定辞典 Machbaseでは、クライアントの接続オプションでタイムゾーンを指定できます。datetime値は内部で ナノ秒値として処理され、タイムゾーンオプションは文字列の入出力変換に影響します。 ## サポートするタイムゾーン形式 | 形式 | 例 | 説明 | |------|------|------| | UTCオフセット | `+0900`, `-0530` | UTCからの時・分のオフセット | 8.5の元のマニュアルと現行の`machsql`、`machloader`のヘルプに記載された形式は `+-HHMM`オフセットです。`Asia/Seoul`などのIANA地域名と`DEFAULT_TIMEZONE`サーバー プロパティは現行の配布サンプルで確認されていないため、この章ではサポート対象として扱いません。 ## クライアント別のタイムゾーン設定 ### machsql `-z`でセッションのタイムゾーンを指定します。 ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -z +0900 ``` ### machloader `-z`でインポート/エクスポート時のdatetime変換に使用するタイムゾーンを指定します。 ```bash machloader -i -d data.csv -t table_name -z +0900 machloader -o -d data.csv -t table_name -z +0900 ``` ### JDBC JDBCでタイムゾーンを指定する場合は、ドライバーのドキュメントで接続オプションを確認します。 このページでは`machsql`/`machloader`の`+-HHMM`オフセット形式を説明します。 ## タイムゾーンの優先順位 クライアントで`-z +0900`のように明示すると、該当セッションの入出力変換に適用されます。 ## タイムゾーン変換の例 `+0900`タイムゾーンを使用する場合は、次のように接続します。 ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -z +0900 ``` --- title: "16.3 システムカタログリファレンス" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/ language: ja kind: section --- # 16.3 システムカタログリファレンス システムカタログは、Machbaseサーバーの内部メタデータと現在の運用状態をSQLで参照できる読み取り専用テーブル群です。次の2種類で構成されます。 | 種類 | 接頭辞 | 説明 | |------|--------|------| | メタデータテーブル | `M$` | テーブル定義、列、インデックス、ユーザーなどのスキーマ情報 | | 仮想テーブル(動的ビュー) | `V$` | セッション、実行クエリ、メモリ、ストレージなどの現在の運用状態 | ## 共通事項 - すべてのシステムカタログテーブルは**読み取り専用**です。`INSERT`、`UPDATE`、`DELETE`はエラーを返します。 - `M$`テーブルはDDLコマンド(`CREATE`、`ALTER`、`DROP`)の実行結果を自動反映します。 - `V$`テーブルはサーバー状態をリアルタイムに反映し、クエリのたびに最新の値を返します。 - 全一覧は次のクエリで確認します。 ```sql -- 全メタデータテーブル一覧 SELECT name FROM m$tables ORDER BY name; -- 全仮想テーブル一覧 SELECT name FROM v$tables WHERE name LIKE 'V$%' ORDER BY name; ``` ## 下位セクション | セクション | 説明 | |------|------| | [メタデータテーブル辞典](./meta/) | M$SYS_TABLES、M$SYS_COLUMNSなどのスキーマメタデータテーブルの詳細 | | [仮想テーブル辞典](./virtual/) | V$SESSION、V$STMT、V$PROPERTYなどの動的ビューの詳細 | | [TAG別統計ビュー](/ja/dbms/tag-table-usage/query-analysis/#tag-stat-axis-schema) | `V$
_STAT`の時間・距離軸別のスキーマと参照方法 | | [V$ROLLUP辞典](./vrollup/) | Rollupジョブ状態ビューの列の詳細 | | [V$STORAGE_MOUNT_*辞典](./vstorage-mount/) | マウント済みバックアップデータベースのビューの列の詳細 | | [仮想テーブルの完全リファレンス](./virtual-table-full/) | 8.5の元の仮想テーブルリファレンスの全項目 | --- title: "16.3.1 メタデータテーブル辞典" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/meta/ language: ja kind: page --- # 16.3.1 メタデータテーブル辞典 メタデータテーブルは`M$`で始まり、テーブル定義、列、インデックス、ユーザーなどのMachbaseスキーマ情報を参照します。DDLの実行結果を自動反映する読み取り専用テーブルです。 8.7.0 Standard Editionの複数データベース環境でカタログローカルなメタデータを結合するときは、 `DATABASE_ID`、`TABLESPACE_ID`、親オブジェクトIDを併用してください。論理的な`DATABASE_ID`と 物理的な`TABLESPACE_ID`は相互に代用できません。データベースの運用境界は [複数データベースの運用ガイド](/ja/dbms/operations-configuration-recovery/multi-database/)を参照してください。 ## メタデータテーブル一覧 | テーブル名 | 説明 | |------------|------| | `M$SYS_TABLES` | ユーザー作成テーブルの一覧とタイプ | | `M$SYS_TABLE_PROPERTY` | テーブルに適用されたプロパティ情報 | | `M$SYS_COLUMNS` | テーブルの列定義(型、長さなど) | | `M$SYS_INDEXES` | インデックス定義 | | `M$SYS_INDEX_COLUMNS` | インデックスを構成する列の情報 | | `M$SYS_TABLESPACES` | テーブルスペース一覧 | | `M$SYS_TABLESPACE_DISKS` | テーブルスペースが使用するディスクパス | | `M$SYS_USERS` | 登録済みユーザー一覧 | | `M$SYS_VIEWS` | ビューを定義するSQLテキスト | | `M$SYS_USER_ACCESS` | テーブル別のユーザー権限 | | `M$RETENTION` | 保持ポリシー情報 | | `M$TABLES` | M$メタデータテーブル自体の一覧 | | `M$COLUMNS` | M$メタデータテーブルの列一覧 | ## M$SYS_TABLES ユーザーが作成したテーブルの一覧とタイプを参照します。 | 列名 | 型 | 説明 | |--------|------|------| | `NAME` | VARCHAR | テーブル名 | | `TYPE` | INTEGER | テーブルタイプ | | `ID` | LONG | テーブル識別子 | | `DATABASE_ID` | LONG | 論理データベース識別子 | | `TABLESPACE_ID` | LONG | 物理テーブルスペース識別子 | | `USER_ID` | INTEGER | テーブルを作成したユーザーの識別子 | | `COLCOUNT` | INTEGER | 列数 | | `FLAG` | INTEGER | サブタイプ(1: Tag Data, 2: Rollup, 4: Tag Meta, 8: Tag Stat) | **TYPE値の意味:** | 値 | テーブルタイプ | |----|------------| | `0` | Log テーブル | | `1` | Fixed テーブル | | `3` | Volatile テーブル | | `4` | Lookup テーブル | | `5` | Key Value テーブル | | `6` | Tag テーブル | | `7` | View | | `8` | TRANSACTION テーブル | ## M$SYS_COLUMNS テーブルの列定義を参照します。 | 列名 | 型 | 説明 | |--------|------|------| | `NAME` | VARCHAR | 列名 | | `TYPE` | INTEGER | 列のデータ型 | | `TABLE_ID` | LONG | 所属テーブルの識別子 | | `DATABASE_ID` | LONG | 論理データベース識別子 | | `TABLESPACE_ID` | LONG | 物理テーブルスペース識別子 | | `LENGTH` | INTEGER | 列の最大長 | | `PART_PAGE_COUNT` | INTEGER | パーティション当たりのページ数 | | `MINMAX_CACHE_SIZE` | LONG | MIN-MAXキャッシュサイズ | ## M$SYS_INDEXES インデックス定義を参照します。 | 列名 | 型 | 説明 | |--------|------|------| | `NAME` | VARCHAR | インデックス名 | | `TYPE` | INTEGER | インデックスタイプ | | `TABLE_ID` | LONG | 所属テーブルの識別子 | | `DATABASE_ID` | LONG | 論理データベース識別子 | | `TABLESPACE_ID` | LONG | 物理テーブルスペース識別子 | | `COLCOUNT` | INTEGER | インデックスの列数 | | `MAX_LEVEL` | INTEGER | 最大LSMレベル | ## M$SYS_USERS 登録済みユーザー一覧を参照します。 | 列名 | 型 | 説明 | |--------|------|------| | `USER_ID` | INTEGER | ユーザー識別子 | | `NAME` | VARCHAR | ユーザー名 | | `PWD_POLICY_LEVEL` | INTEGER | パスワードポリシーレベル | | `VALID_BEFORE` | VARCHAR | アカウントの有効期間 | ## M$RETENTION 保持ポリシーの情報を参照します。 | 列名 | 型 | 説明 | |--------|------|------| | `POLICY_NAME` | VARCHAR | ポリシー名 | | `DURATION` | LONG | 保持期間(秒) | | `INTERVAL` | LONG | 削除実行間隔(秒) | ## SQL例 ```sql -- 全テーブル一覧(タイプを含む) SELECT name, type, colcount FROM m$sys_tables ORDER BY name; -- Tagテーブルのみ参照(type = 6) SELECT name FROM m$sys_tables WHERE type = 6; -- 特定テーブルの列一覧 SELECT c.name AS col_name, c.type AS col_type, c.length FROM m$sys_columns c JOIN m$sys_tables t ON c.database_id = t.database_id AND c.tablespace_id = t.tablespace_id AND c.table_id = t.id WHERE t.name = 'SENSOR_TAG' ORDER BY c.id; -- 特定テーブルのインデックス一覧 SELECT i.name AS idx_name, i.type AS idx_type, i.colcount FROM m$sys_indexes i JOIN m$sys_tables t ON i.database_id = t.database_id AND i.tablespace_id = t.tablespace_id AND i.table_id = t.id WHERE t.name = 'SENSOR_TAG'; -- インデックスを構成する列の確認 SELECT ic.name AS col_name, ic.index_type FROM m$sys_index_columns ic JOIN m$sys_indexes i ON ic.index_id = i.id JOIN m$sys_tables t ON i.table_id = t.id WHERE t.name = 'SENSOR_TAG'; -- テーブルスペースのディスクパスの確認 SELECT ts.name AS tbs_name, d.path, d.io_thread_count FROM m$sys_tablespace_disks d JOIN m$sys_tablespaces ts ON d.tablespace_id = ts.id; -- ユーザー一覧の参照 SELECT user_id, name, pwd_policy_level, valid_before FROM m$sys_users; -- 保持ポリシー一覧 SELECT * FROM m$retention; ``` > メタデータテーブルは読み取り専用です。`INSERT`、`UPDATE`、`DELETE`はエラーを返します。スキーマの変更には`CREATE TABLE`、`ALTER TABLE`、`DROP TABLE`などのDDLを使用してください。 --- title: "16.3.2 仮想テーブル辞典" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/virtual/ language: ja kind: page --- # 16.3.2 仮想テーブル辞典 仮想テーブル(動的ビュー)は`V$`で始まり、Machbaseサーバーの現在の運用状態をテーブル形式で表します。読み取り専用で、クエリのたびに最新の状態を返します。 ## 仮想テーブル一覧 | カテゴリー | テーブル名 | 説明 | |---------|------------|------| | セッション/システム | `V$VERSION` | サーバーバージョン情報 | | セッション/システム | `V$SESSION` | 現在の接続セッション一覧 | | データベース | `V$DATABASES` | アクティブ/マウント済みデータベースの状態 | | データベース | `V$DATABASE_OPERATIONS` | データベースのライフサイクル操作履歴 | | セッション/システム | `V$STMT` | 実行中のSQL文 | | セッション/システム | `V$PROPERTY` | 現在のサーバー設定値 | | セッション/システム | `V$SYSMEM` | システムのメモリ使用量 | | セッション/システム | `V$SYSSTAT` | システム統計情報 | | セッション/システム | `V$SYSTIME` | システム時間統計 | | ストレージ | `V$STORAGE` | ストレージファイルサイズの概要 | | ストレージ | `V$STORAGE_USAGE` | ディスク使用量と使用率の上限 | | ストレージ | `V$STORAGE_TABLES` | テーブル別のストレージ使用量 | | ストレージ | `V$STORAGE_MOUNT_DATABASES` | マウント済みバックアップデータベース | | タグRollup | `V$ROLLUP` | Rollupジョブの状態 | | TAGテーブル | `V$
_STAT` | テーブル別のタグ・軸統計。実際の名前はTAGテーブル名から生成 | | ライセンス | `V$LICENSE_INFO` | ライセンス情報 | | ロック | `V$MUTEX` | ロック状況 | `V$
_STAT`はTAGテーブルごとに動的に作成されるため、固定のグローバル仮想テーブル一覧とは 区別します。時間軸・距離軸別の列名と型は [TAG別統計ビュー](/ja/dbms/tag-table-usage/query-analysis/#tag-stat-axis-schema)を参照してください。 ## V$VERSION サーバーバージョン情報を参照します。 | 列名 | 説明 | |----------|------| | `BINARY_SIGNATURE` | サーバーバージョン文字列 | ```sql SELECT binary_signature FROM v$version; ``` ## V$DATABASES 論理データベースとマウント済みデータベースの状態を参照します。`DATABASE_ID`は論理カタログの 識別子であり、`TABLESPACE_ID`とは異なります。 | 列 | 説明 | |------|------| | `DATABASE_ID` | 論理データベース識別子 | | `SOURCE_DATABASE_ID` | マウント済みバックアップの元のデータベース識別子 | | `NAME` | データベース名またはマウントのエイリアス | | `KIND` | `ACTIVE`または`MOUNTED` | | `ACCESS_MODE` | `READ_WRITE`または`READ_ONLY` | | `CAN_USE` | `USE`で選択できるかどうか | | `STATE` | ライフサイクルの状態 | | `IS_DEFAULT` | デフォルトの`MACHBASEDB`かどうか | ```sql SELECT database_id, name, kind, access_mode, can_use, state, is_default FROM v$databases ORDER BY database_id; ``` ## V$DATABASE_OPERATIONS `CREATE`、`ALTER`、`DROP`、`BACKUP`、`RESTORE`、`MOUNT`、`UMOUNT`操作の状態とエラーを参照します。 `FAILED_NEEDS_ACTION`状態の場合は、実際の`V$DATABASES`の状態とサーバーログも確認してください。 | 列 | 説明 | |------|------| | `OPERATION_ID` | 操作識別子 | | `DATABASE_ID` | 対象論理データベース識別子 | | `DATABASE_NAME` | 対象データベース名 | | `STATE` | 操作状態 | | `LAST_ERROR` | 失敗原因 | | `CREATED_AT` | 作成時刻 | | `UPDATED_AT` | 最終変更時刻 | ```sql SELECT operation_id, database_name, state, last_error FROM v$database_operations ORDER BY operation_id DESC; ``` ## V$SESSION 現在の接続セッションの一覧と状態を表示します。 | 列名 | 説明 | |----------|------| | `ID` | セッション識別子 | | `CLOSED` | 接続が閉じているかどうか(0: アクティブ) | | `USER_ID` | ユーザー識別子 | | `LOGIN_TIME` | 接続時刻 | | `CLIENT_TYPE` | 接続クライアントのタイプ | | `USER_NAME` | ユーザー名 | | `USER_IP` | ユーザーIPアドレス | | `SQL_LOGGING` | 該当セッションのトレースログ記録の有効化 | | `IDLE_TIMEOUT` | アイドル状態のセッションを終了するまでの時間(秒) | | `QUERY_TIMEOUT` | クエリ応答の待機時間 | ```sql -- 現在のアクティブセッション一覧 SELECT id, user_name, user_ip, client_type, login_time FROM v$session WHERE closed = 0 ORDER BY login_time; ``` ## V$STMT 現在実行中または待機中のSQL文の情報を表示します。 | 列名 | 説明 | |----------|------| | `ID` | クエリ識別子 | | `SESS_ID` | クエリを実行したセッションの識別子 | | `STATE` | クエリ状態 | | `RECORD_SIZE` | SELECT実行時の結果レコードサイズ | | `QUERY` | クエリのテキスト | ```sql -- 実行中のクエリの確認 SELECT id, sess_id, state, query FROM v$stmt WHERE state LIKE 'Execute in progress%' OR state LIKE 'Fetch in progress%' OR state LIKE 'Append in progress%'; ``` ## V$PROPERTY サーバーに設定されたすべてのプロパティ値を参照します。 | 列名 | 説明 | |----------|------| | `NAME` | プロパティ名 | | `VALUE` | 現在の設定値 | | `TYPE` | データ型 | | `DEFLT` | デフォルト値 | | `MIN` | 最小値 | | `MAX` | 最大値 | ```sql -- 特定設定値の確認 SELECT name, value, deflt FROM v$property WHERE name IN ('PORT_NO', 'TRACE_LOG_LEVEL', 'MAX_SESSION_COUNT'); -- デフォルト値と異なる設定のみ参照 SELECT name, value, deflt FROM v$property WHERE value != deflt ORDER BY name; ``` ## V$STORAGE_USAGE ストレージシステムのディスク使用状況を表示します。 | 列名 | 説明 | |----------|------| | `TOTAL_SPACE` | データディレクトリがあるストレージの総容量 | | `USED_SPACE` | 使用中の容量 | | `USED_RATIO` | 使用率(%) | | `RATIO_CAP` | 使用量の上限(超過時は取り込みを停止) | ```sql SELECT total_space, used_space, used_ratio, ratio_cap FROM v$storage_usage; ``` ## V$SYSMEM システムのメモリ使用量を参照します。 | 列名 | 説明 | |----------|------| | `ID` | メモリマネージャー識別子 | | `NAME` | メモリマネージャー名 | | `USAGE` | 現在の使用量 | | `MAX_USAGE` | 記録された最大使用量 | ```sql SELECT name, usage, max_usage FROM v$sysmem ORDER BY usage DESC; ``` ## V$LICENSE_INFO サーバーのライセンス情報を参照します。 | 列名 | 説明 | |----------|------| | `ID` | ライセンスID | | `ISSUE_DATE` | 発行日 | | `TYPE` | ライセンスタイプ | | `CUSTOMER` | 顧客名 | | `PROJECT` | プロジェクト名 | | `INSTALL_DATE` | インストール日 | | `VIOLATE_STATUS` | ライセンス違反状態 | | `VIOLATE_MSG` | ライセンス違反メッセージ | ```sql SELECT id, type, customer, issue_date, install_date, violate_status, violate_msg FROM v$license_info; ``` ## 全仮想テーブル一覧の確認 ```sql -- 現在のサーバーで参照できる全V$仮想テーブル一覧 SELECT name FROM v$tables WHERE name LIKE 'V$%' ORDER BY name; ``` > 仮想テーブルは読み取り専用です。Cluster Editionでのみ提供するテーブル(V$NODE_STATUS、V$REPLICATIONなど)は、Standard Editionでは参照できません。 --- title: "16.3.3 V$ROLLUP辞典" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/vrollup/ language: ja kind: page --- # 16.3.3 V$ROLLUP辞典 `V$ROLLUP`は、TagデータのRollupジョブの状態をリアルタイムに表示する仮想テーブルです。Rollupの正常動作の確認や実行間隔と所要時間の監視に使用します。 ## 列の詳細 | 列名 | 型 | 説明 | |----------|------|------| | `ID` | INTEGER | RollupジョブID | | `ROLLUP_NAME` | VARCHAR | Rollupジョブ名 | | `ROLLUP_TABLE` | VARCHAR | Rollup結果の保存先テーブル名 | | `SOURCE_TABLE` | VARCHAR | 集計元のTAGテーブル名 | | `COLUMN_NAME` | VARCHAR | 集計対象の列名 | | `INTERVAL_TIME` | ULONG | データの集計間隔(ミリ秒) | | `WAKEUP_INTERVAL` | ULONG | Rollupジョブの実行間隔(ミリ秒) | | `LAST_WAKEUP_TIME` | DATETIME | 直近の実行時刻 | | `ENABLED` | INTEGER | 有効かどうか(1: 有効、0: 無効) | | `LAST_ELAPSED_MSEC` | DOUBLE | 直前の実行の所要時間(ミリ秒) | | `RUN_STATE` | VARCHAR | スレッド状態(I: 初期化、S: 待機、R: 実行中) | ## RUN_STATEの値 | 値 | 説明 | |----|------| | `I` | 初期化中(Initializing) | | `S` | 次回の実行を待機中(Sleeping) | | `R` | 実行中(Running) | ## SQL例 ```sql -- 全Rollupジョブの状態確認 SELECT rollup_name, rollup_table, source_table, column_name, interval_time, wakeup_interval, enabled, last_elapsed_msec, run_state FROM v$rollup ORDER BY rollup_table; -- 最後の実行時刻の確認 SELECT rollup_name, rollup_table, last_wakeup_time, last_elapsed_msec, run_state FROM v$rollup; -- 無効になっているRollupの確認 SELECT rollup_name, rollup_table, source_table, enabled FROM v$rollup WHERE enabled = 0; -- 実行に時間がかかるRollupの確認 SELECT rollup_name, rollup_table, wakeup_interval, last_elapsed_msec, last_elapsed_msec * 100.0 / wakeup_interval AS usage_ratio FROM v$rollup WHERE last_elapsed_msec > 0 AND wakeup_interval > 0 ORDER BY last_elapsed_msec DESC; ``` ## 注意事項 - `INTERVAL_TIME`はデータの集計間隔、`WAKEUP_INTERVAL`はRollupジョブの実行間隔です。 - `LAST_ELAPSED_MSEC`が`WAKEUP_INTERVAL`を超えていれば、直前の実行時間が設定された実行間隔を超えています。集計対象のデータ量と実行間隔を確認してください。例の`usage_ratio`は実行間隔に対する直前の実行時間の割合(%)です。 - `ENABLED = 0`はRollupが無効であることを示します。`ALTER ROLLUP rollup_name START`で再び有効にします。`rollup_name`には参照した`ROLLUP_NAME`の値を指定します。 - Rollupの作成と管理は[TAGテーブルとRollup](/ja/dbms/tag-rollup-usage/overview-use-criteria/#rollup)を参照してください。 --- title: "16.3.4 V$STORAGE_MOUNT_DATABASES辞典" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/vstorage-mount/ language: ja kind: page --- # 16.3.4 V$STORAGE_MOUNT_DATABASES辞典 `V$STORAGE_MOUNT_DATABASES`は、現在のインスタンスに読み取り専用で接続したバックアップデータベースを表示します。 ## 列 | 列 | 型 | 説明 | |---|---|---| | `NAME` | VARCHAR | バックアップデータベース名 | | `PATH` | VARCHAR | バックアップイメージの元のパス | | `BACKUP_TBSID` | LONG | バックアップのテーブルスペース識別子 | | `BACKUP_SCN` | LONG | バックアップSCN | | `MOUNTDB` | VARCHAR | MOUNT時に指定したデータベースのエイリアス | | `DB_BEGIN_TIME` | VARCHAR | バックアップデータの開始時刻 | | `DB_END_TIME` | VARCHAR | バックアップデータの終了時刻 | | `BACKUP_BEGIN_TIME` | VARCHAR | バックアップ処理の開始時刻 | | `BACKUP_END_TIME` | VARCHAR | バックアップ処理の終了時刻 | | `FLAG` | INTEGER | 内部状態フラグ。値の意味を推測しないこと | ## 参照 ```sql SELECT NAME, PATH, MOUNTDB, DB_BEGIN_TIME, DB_END_TIME, BACKUP_BEGIN_TIME, BACKUP_END_TIME FROM V$STORAGE_MOUNT_DATABASES ORDER BY MOUNTDB; ``` ## MOUNTと参照の例 ```sql MOUNT DATABASE '/data/backup/sc15_snapshot' TO backup_check; SELECT * FROM backup_check.sys.target_table LIMIT 10; UMOUNT DATABASE backup_check; ``` オペランドはバックアップパス、`TO`、エイリアスの順です。マウント済みデータベースのオブジェクトは `mount_alias.owner.table`という3部構成の名前で参照します。権限と安全上の制約の全体は [BACKUP/RESTORE/MOUNT構文](/ja/dbms/reference/sql/syntax/backup-restore-mount-syntax/)を参照してください。 --- title: "16.3.5 仮想テーブルの完全リファレンス" url: https://docs.machbase.com/ja/dbms/reference/system-catalog/virtual-table-full/ language: ja kind: page --- # 16.3.5 仮想テーブルの完全リファレンス Virtual Tableは、Machbaseサーバーの運用情報をテーブル形式で提供する読み取り専用の仮想テーブルで、名前は`V$`で始まります。サーバー状態の参照や、他のテーブルとのJOINによる運用データの分析に使用します。INSERT、UPDATE、DELETEはサポートしません。 ## 目次 * [Session/System](#sessionsystem) * [V$PROPERTY](#vproperty) * [V$SESSION](#vsession) * [V$SESMEM](#vsesmem) * [V$SESSTAT](#vsesstat) * [V$SESTIME](#vsestime) * [V$SYSMEM](#vsysmem) * [V$SYSSTAT](#vsysstat) * [V$SYSTIME](#vsystime) * [V$STMT](#vstmt) * [V$VERSION](#vversion) * [V$DATABASES](#vdatabases) * [V$DATABASE_OPERATIONS](#vdatabase_operations) * [V$NEO\_SESSION](#vneo_session) * [V$NEO\_STMT](#vneo_stmt) * [PVO Statement Cache](#pvo-statement-cache) * [V$PVO\_CACHE\_STAT](#vpvo_cache_stat) * [V$PVO\_CACHE\_LIST](#vpvo_cache_list) * [Storage](#storage) * [V$STORAGE](#vstorage) * [V$STORAGE\_MOUNT\_DATABASES](#vstorage_mount_databases) * [V$CACHE](#vcache) * [V$CACHE\_OBJECTS](#vcache_objects) * [V$STORAGE\_DC\_TABLESPACES](#vstorage_dc_tablespaces) * [V$STORAGE\_DC\_TABLESPACE\_DISKS](#vstorage_dc_tablespace_disks) * [V$STORAGE\_DC\_DWFILES](#vstorage_dc_dwfiles) * [V$STORAGE\_DC\_PAGECACHE](#vstorage_dc_pagecache) * [V$STORAGE\_DC\_PAGECACHE\_LRU\_LST](#vstorage_dc_pagecache_lru_lst) * [V$STORAGE\_USAGE](#vstorage_usage) * [V$STORAGE\_TABLES](#vstorage_tables) * [Log Table](#log-table) * [V$STORAGE\_DC\_TABLES](#vstorage_dc_tables) * [V$STORAGE\_DC\_TABLES\_STAT](#vstorage_dc_tables_stat) * [V$STORAGE\_DC\_TABLE\_COLUMNS](#vstorage_dc_table_columns) * [V$STORAGE\_DC\_TABLE\_COLUMN\_PARTS](#vstorage_dc_table_column_parts) * [V$STORAGE\_DC\_TABLE\_INDEXES](#vstorage_dc_table_indexes) * [LSM(Log Structured Merge) Index](#lsmlog-structured-merge-index) * [V$STORAGE\_DC\_LSMINDEX\_LEVEL\_PARTS](#vstorage_dc_lsmindex_level_parts) * [V$STORAGE\_DC\_LSMINDEX\_LEVEL\_PARTS\_CACHE](#vstorage_dc_lsmindex_level_parts_cache) * [V$STORAGE\_DC\_LSMINDEX\_LEVELS](#vstorage_dc_lsmindex_levels) * [V$STORAGE\_DC\_LSMINDEX\_FILES](#vstorage_dc_lsmindex_files) * [V$STORAGE\_DC\_LSMINDEX\_AGER\_JOBS](#vstorage_dc_lsmindex_ager_jobs) * [Volatile Table](#volatile-table) * [V$STORAGE\_DC\_VOLATILE\_TABLE](#vstorage_dc_volatile_table) * [Tag Table](#tag-table) * [V$STORAGE\_TAG\_TABLES](#vstorage_tag_tables) * [V$STORAGE\_TAG\_CACHE](#vstorage_tag_cache) * [V$STORAGE\_TAG\_CACHE\_BASE](#vstorage_tag_cache_base) * [V$STORAGE\_TAG\_CACHE\_OBJECTS](#vstorage_tag_cache_objects) * [V$STORAGE\_TAG\_TABLE\_FILES](#vstorage_tag_table_files) * [V$STORAGE\_TAG\_INDEX](#vstorage_tag_index) * [Tag Rollup](#tag-rollup) * [V$ROLLUP](#vrollup) * [License](#license) * [V$LICENSE\_INFO](#vlicense_info) * [Mutex](#mutex) * [V$MUTEX](#vmutex) * [V$MUTEX\_WAIT\_STAT](#vmutex_wait_stat) * [Cluster](#cluster) * [V$NODE\_STATUS](#vnode_status) * [V$DDL\_INFO](#vddl_info) * [V$REPLICATION](#vreplication) * [V$REPL\_SENDER](#vrepl_sender) * [V$REPL\_SENDER\_META](#vrepl_sender_meta) * [V$REPL\_RECEIVER](#vrepl_receiver) * [V$REPL\_RECEIVER\_META](#vrepl_receiver_meta) * [V$REPL\_READER](#vrepl_reader) * [V$REPL\_READER\_META](#vrepl_reader_meta) * [V$REPL\_WRITER](#vrepl_writer) * [V$REPL\_WRITER\_META](#vrepl_writer_meta) * [Others](#others) * [V$TABLES](#vtables) * [V$COLUMNS](#vcolumns) * [V$RETENTION\_JOB](#vretention_job) * [V$USER\_AUTH\_KEYS](#vuser_auth_keys) ## Session/System ### V$PROPERTY --- サーバーに設定されたプロパティ情報を表示します。 | 列名 | 説明 | | ----- | ------------ | | NAME | プロパティ名 | | VALUE | プロパティ値 | | TYPE | データ型 | | DEFLT | デフォルト値 | | MIN | 設定できる最小値 | | MAX | 設定できる最大値 | ### V$SESSION --- MACHBASEサーバーに接続したセッションの情報を表示します。 | 列名 | 説明 | | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | HOSTNAME (Cluster Only) | セッションが接続したHOST名 | | ID | セッション識別子 | | CLOSED | 接続が閉じているかどうか | | USER_ID | ユーザー識別子 | | LOGIN_TIME | 接続時刻 | | CLIENT_TYPE | 接続クライアントのタイプ | | USER_NAME | ユーザー名 | | CURRENT_DB_ID | セッションの現在の論理データベース識別子 | | CURRENT_DB_NAME | セッションの現在のデータベース名 | | USER_IP | ユーザーIP | | SQL_LOGGING | 該当セッションのトレースログにメッセージを記録するかどうか
解析、検証、最適化段階のエラーを記録します。
DDLの実行結果を記録します。
(両方を記録します) | | SHOW_HIDDEN_COLS | SELECTで隠し列を表示するかどうか | | FEEDBACK_APPEND_ERROR | APPENDでエラーを検出したら即座に失敗させるかどうか | | DEFAULT_DATE_FORMAT | Datetime取り込み時のデフォルト入力形式 | | MAX_QPX_MEM | クエリ実行時に使用できる最大メモリサイズ | | IDLE_TIMEOUT | 接続後、指定時間クライアントが何もしなければセッションを終了 | | QUERY_TIMEOUT | クエリ実行時の応答待機時間 | | DDL_LOCK_TIMEOUT (Standard Only) | 競合するDDLロックの待機時間(秒)。`0`は即座にエラーを返します。 | | TRANSACTION_BUSY_TIMEOUT_MS | TRANSACTION書き込み競合の待機時間(ミリ秒)。`-1`は待機を続け、`0`は即座にエラーを返します。 | ### V$SESMEM --- セッションのメモリ情報を表示します。 | 列名 | 説明 | | ----- | ----------- | | SID | セッション識別子 | | ID | メモリマネージャー識別子 | | USAGE | 使用サイズ | ### V$SESSTAT --- セッションの統計情報を表示します。 | 列名 | 説明 | | ----- | --------- | | SID | セッション識別子 | | ID | 統計情報識別子 | | VALUE | 統計情報の値 | ### V$SESTIME --- セッションの時間情報を表示します。 `ACCUM_MSEC`と`MAX_MSEC`はミリ秒単位の`DOUBLE`値です。 | 列名 | 説明 | | ---------- | -------------- | | SID | セッション識別子 | | ID | 実行単位の識別子 | | ACCUM_MSEC | 累積時間 | | MAX_MSEC | 各実行の最大時間 | ### V$SYSMEM --- システムのメモリ情報を表示します。 | 列名 | 説明 | | --------- | ------------ | | ID | メモリマネージャー識別子 | | NAME | メモリマネージャー名 | | USAGE | 現在の使用量 | | MAX_USAGE | 記録された最大使用量 | ### V$SYSSTAT --- システムの統計情報を表示します。 | 列名 | 説明 | | ----- | --------- | | ID | 統計情報識別子 | | NAME | 統計情報名 | | VALUE | 統計情報の値 | ### V$SYSTIME --- システムの時間情報を表示します。 `ACCUM_MSEC`、`AVG_MSEC`、`MIN_MSEC`、`MAX_MSEC`はミリ秒単位の`DOUBLE`値です。 | 列名 | 説明 | | ---------- | -------------- | | ID | 実行単位の識別子 | | NAME | 実行単位の名前 | | ACCUM_MSEC | 累積時間 | | AVG_MSEC | 各実行の平均時間 | | MIN_MSEC | 各実行の最小時間 | | MAX_MSEC | 各実行の最大時間 | | COUNT | 実行回数 | ### V$STMT --- ユーザーが現在実行しているクエリの情報を表示します。 | 列名 | 説明 | | ----------- | ----------------------------- | | ID | クエリ識別子 | | SESS_ID | クエリを実行したセッションの識別子 | | STATE | クエリ状態 | | RECORD_SIZE | SELECT文の実行中の場合、結果レコードのサイズ | | QUERY | クエリのテキスト | ### V$VERSION --- MACHBASEのバージョン情報を表示します。 | 列名 | 説明 | | ------------------------- | ---------------------------------------- | | BINARY_DB_MAJOR_VERSION | DBメジャーバージョン | | BINARY_DB_MINOR_VERSION | DBマイナーバージョン | | BINARY_META_MAJOR_VERSION | METAメジャーバージョン | | BINARY_META_MINOR_VERSION | METAマイナーバージョン | | BINARY_CM_MAJOR_VERSION | Client(Communication Level)メジャーバージョン | | BINARY_CM_MINOR_VERSION | Client(Communication Level)マイナーバージョン | | BINARY_SIGNATURE | DBサーバーファイルのバージョン名 | | FILE_DB_MAJOR_VERSION | File DBメジャーバージョン | | FILE_DB_MINOR_VERSION | File DBマイナーバージョン | | FILE_META_MAJOR_VERSION | File METAメジャーバージョン | | FILE_META_MINOR_VERSION | File METAマイナーバージョン | | FILE_CM_MAJOR_VERSION | File Client(Communication Level)メジャーバージョン | | FILE_CM_MINOR_VERSION | File Client(Communication Level)マイナーバージョン | | FILE_CREATE_TIME | ファイル作成時刻 | | EDITION | MACHBASEの種類 | ### V$DATABASES --- アクティブな論理データベースとマウント済みデータベースの状態を表示します。`DATABASE_ID`は論理 カタログ識別子であり、物理的な`TABLESPACE_ID`とは異なります。 | 列名 | 説明 | | ----------- | ------ | | DATABASE_ID | 論理データベース識別子 | | SOURCE_DATABASE_ID | マウント済みバックアップの元のデータベース識別子 | | NAME | データベース名またはマウントのエイリアス | | KIND | `ACTIVE`または`MOUNTED` | | ACCESS_MODE | `READ_WRITE`または`READ_ONLY` | | CAN_USE | `USE`で選択できるかどうか | | STATE | ライフサイクルの状態 | | IS_DEFAULT | デフォルトの`MACHBASEDB`かどうか | ```sql SELECT database_id, name, kind, access_mode, can_use, state, is_default FROM v$databases ORDER BY database_id; ``` ### V$DATABASE_OPERATIONS --- データベースのライフサイクル操作の状態とエラーを表示します。 | 列名 | 説明 | | ----------- | ------ | | OPERATION_ID | 操作識別子 | | DATABASE_ID | 対象論理データベース識別子 | | DATABASE_NAME | 対象データベース名 | | STATE | 操作状態 | | LAST_ERROR | 失敗原因 | | CREATED_AT | 作成時刻 | | UPDATED_AT | 最終変更時刻 | ```sql SELECT operation_id, database_name, state, last_error FROM v$database_operations ORDER BY operation_id DESC; ``` ### V$NEO_SESSION --- Neoプロトコルクライアントのセッション状態を表示します。 | 列名 | 説明 | | -- | -- | | ID | セッション識別子 | | USER_ID | ユーザー識別子 | | USER_NAME | ユーザー名 | | STMT_COUNT | セッションのステートメント数 | | DISCONN_FLAG | 切断フラグ | ### V$NEO_STMT --- Neoプロトコルクライアントのステートメント状態を表示します。 | 列名 | 説明 | | -- | -- | | ID | ステートメント識別子 | | SESS_ID | セッション識別子 | | STATE | ステートメント状態 | | QUERY | ステートメントのテキスト | | APPEND_SUCCESS_CNT | Append成功件数 | | APPEND_FAILURE_CNT | Append失敗件数 | ## PVO Statement Cache Standard Edition専用のグローバルなPVO Statement Cacheの状態を参照します。 ### V$PVO_CACHE_STAT --- PVO Statement Cacheの全体統計を表示します。 | 列名 | 説明 | | -- | -- | | CACHE_ENTRY_COUNT | キャッシュに格納されたSQLエントリー数 | | CACHE_HANDLE_COUNT | 全SQLのキャッシュ済み計画(ハンドル)数 | | CACHE_MEMORY_USAGE | 使用中のキャッシュメモリサイズ | | CACHE_MAX_MEMORY_SIZE | 設定されたキャッシュメモリ上限 | | CACHE_MAX_PLANS_PER_SQL | SQL当たりの最大許容計画数 | | CACHE_MAX_SQL_ENTRIES | 最大許容SQLエントリー数(0は無制限) | | CACHE_SHARD_COUNT | キャッシュのシャード数 | | CACHE_HIT | キャッシュヒット回数 | | CACHE_MISS | キャッシュミス回数 | | SINGLEFLIGHT_WAIT | 同じSQLの同時構築を待機した回数 | | BUILD_COUNT | 計画の構築試行回数 | | BUILD_FAIL | 構築失敗回数 | | INVALIDATE_COUNT | 無効化された計画数 | | EVICT_COUNT | メモリ上限などによるキャッシュの追い出し回数 | | FLUSH_COUNT | 明示的/内部フラッシュ回数 | ### V$PVO_CACHE_LIST --- PVO Statement Cacheに保存されたSQL別の詳細情報を表示します。 | 列名 | 説明 | | -- | -- | | TOUCH_TIME | 最終アクセス時刻 | | USER_ID | SQLを所有するユーザーID | | QUERY | 元のSQLテキスト | | DEFAULT_DATE_FORMAT | 実行時の日付形式 | | TIMEZONE_OFFSET | 実行時のタイムゾーンオフセット | | SHOW_HIDDEN_COLS | 隠し列を表示するかどうか | | QUERY_PARALLEL_FACTOR | 並列実行係数 | | HANDLE_COUNT | 保持する計画(ハンドル)数 | | BUSY_COUNT | 同時に使用中のハンドル数 | | HIT_COUNT | キャッシュヒット回数 | | BUILD_IN_PROGRESS | 構築中かどうか | ## Storage ### V$STORAGE --- ストレージシステムの内部情報を表示します。 | 列名 | 説明 | | ------------------------- | ------------------------------------ | | DC_TABLE_FILE_SIZE | ディスク上の列データの総容量 | | DC_INDEX_FILE_SIZE | インデックスファイルデータの総容量 | | DC_TABLESPACE_DWFILE_SIZE | 全列データ用DWFILEの総容量 | | DC_KV_TABLE_FILE_SIZE | TAGDATAテーブルのパーティションテーブルが持つデータファイルの総容量 | ### V$STORAGE_MOUNT_DATABASES --- マウント機能でマウントしたバックアップデータベースの情報を表示します。 | 列名 | 説明 | | ----------------- | ---------------------- | | NAME | マウント済みデータベース名 | | PATH | バックアップファイルの場所 | | BACKUP_TBSID | バックアップデータベースのテーブルスペース識別子 | | BACKUP_SCN | バックアップデータベースの識別子 | | MOUNTDB | MOUNT時に指定したデータベースのエイリアス | | DB_BEGIN_TIME | バックアップデータベースの最初の取り込み時刻 | | DB_END_TIME | バックアップデータベースの最後の取り込み時刻 | | BACKUP_BEGIN_TIME | バックアップ実行の開始時刻 | | BACKUP_END_TIME | バックアップ実行の終了時刻 | | FLAG | プロパティフラグ | ### V$CACHE --- Storage Managerで読み取った結果をキャッシュするオブジェクトの集計情報を表示します。 | 列名 | 説明 | | --------- | ---------------- | | OBJ_COUNT | 結果セットのキャッシュオブジェクトの現在数 | ### V$CACHE_OBJECTS --- ストレージシステムで読み取った結果をキャッシュする各オブジェクトの情報を表示します。 | 列名 | 説明 | | --------- | -------------- | | OID | オブジェクト識別子 | | REF_COUNT | 参照カウント | | FLAG | サーバー内部用フラグ | ### V$STORAGE_DC_TABLESPACES --- ストレージシステムのテーブルスペース情報を表示します。 | 列名 | 説明 | | ---------- | ---------------------------- | | NAME | テーブルスペース名 | | ID | テーブルスペース識別子 | | FLAG | テーブルスペースのプロパティを示すフラグ | | REF_COUNT | テーブルスペースの参照回数 | | DISK_COUNT | テーブルスペースに属するディスク数 | ### V$STORAGE_DC_TABLESPACE_DISKS --- ストレージシステムのテーブルスペース情報を表示します。 | 列名 | 説明 | | ------------------ | ------------------- | | NAME | ディスク名 | | ID | ディスク識別子 | | TABLESPACE_ID | ディスクが属するテーブルスペースの識別子 | | PATH | ディスクのパス | | IO_THREAD_COUNT | I/Oスレッド数 | | IO_JOB_COUNT | I/Oジョブ数 | | VIRTUAL_DISK_COUNT | 仮想ディスク数 | ### V$STORAGE_DC_DWFILES --- ストレージシステムが管理するダブルライトファイル(DW File)の情報を表示します。 | 列名 | 説明 | | -------------------- | ----------------------- | | TBS_ID | テーブルスペース識別子 | | DISK_ID | ディスク識別子 | | FILE | ファイルのパス | | TABLE_ID | テーブル識別子 | | COLUMN_ID | 列識別子 | | PARTITION_ID | パーティション識別子 | | PAGE_ID | ページ識別子 | | DISK_OFFSET | ディスクオフセット | | DISK_IMAGE_SIZE | ディスクイメージサイズ | | HEAD_CRC32CODE_IMAGE | CRC32コードのヘッドイメージ | | TAIL_CRC32CODE_IMAGE | CRC32コードのテールイメージ | | CRC32CODE_PAGE | CRC32コードのページ | | HEAD_TIMESTAMP_PAGE | タイムスタンプのヘッドページ | | TAIL_TIMESTAMP_PAGE | タイムスタンプのテールページ | ### V$STORAGE_DC_PAGECACHE --- ストレージシステムが管理するページキャッシュの情報を表示します。 | 列名 | 説明 | | ------------ | ---------------------- | | MAX_MEM_SIZE | ページキャッシュの最大メモリサイズ | | CUR_MEM_SIZE | ページキャッシュの現在のメモリサイズ | | PAGE_CNT | キャッシュされたページ数 | | CHECK_TIME | 検査時刻 | ### V$STORAGE_DC_PAGECACHE_LRU_LST --- ストレージシステムが管理するページキャッシュのLRUリストの情報を表示します。 | 列名 | 説明 | | ------------ | ------------------- | | SIZE | ページサイズ | | REF_CNT | 参照回数 | | PARTITION_ID | パーティション識別子 | | OFFSET | ページキャッシュのオフセット | | OBJECT_ID | オブジェクト識別子 | | LEVEL | パーティションレベル | ### V$STORAGE_USAGE --- ストレージシステムで使用中のストレージ使用量を表示します。 | 列名 | 説明 | | ----------- | ------------------------------------------------------ | | TOTAL_SPACE | $MACHBASE_HOME/dbsディレクトリがあるストレージの総容量 | | USED_SPACE | $MACHBASE_HOME/dbsディレクトリがあるストレージの使用量 | | USED_RATIO | 使用率(%) | | RATIO_CAP | ストレージ使用量の上限。USED_RATIOがこの上限に達すると、取り込み/インデックス構築が停止します。 | ### V$STORAGE_TABLES --- テーブルの詳細情報を表示します。 | 列名 | 説明 | | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ID | テーブルのID | | TYPE | テーブルタイプ
Persistent: LOGテーブルとTAGテーブル
Volatile: Volatileテーブル
Key-Value: TAGテーブルの補助テーブル | | STATUS | 現在の状態
Creating...: CREATE TABLEでテーブル作成中
Normal: 正常
Predrop: DROP TABLEコマンドを受け付けた状態
Dropping...: DROP TABLEコマンドの実行中
Dropped: DROP TABLEコマンドの完了
Mounted: バックアップデータベースをmountコマンドで読み込んだ状態 | | STORAGE_USAGE | 該当テーブルがストレージ上で占有する容量 | ## Log Table ### V$STORAGE_DC_TABLES --- Logテーブルの内部情報を表示します。 | 列名 | 説明 | | -------------------- | ------------------------------------------ | | ID | テーブルの識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | CREATE_SCN | 作成時のシステム変更番号(System Change Number) | | UPDATE_SCN | 最終変更時のシステム変更番号(System Change Number) | | DDL_REF_COUNT | DDL実行で該当テーブルを参照しているセッション数 | | BEGIN_RID | テーブルの最小RID | | END_RID | テーブルの最後のRow ID + 1 | | BEGIN_META_RID | メタデータの記録開始時点のID | | END_META_RID | メタデータの記録終了時点のID | | END_SYNC_RID | ディスクに記録された最後のRow ID + 1 | | FLAG | テーブルのプロパティを示すフラグ | | COLUMN_COUNT | テーブルの列数 | | INDEX_COUNT | テーブルのインデックス数 | | INDEX_MIN_END_RID | インデックスに記録された最後のRID + 1 | | LAST_ARRIVAL_TIME | 最後に記録された\_arrival_timeの値 | | LAST_CHECKPOINT_TIME | 最後にチェックポイントを通過した時点 | | TYPE | テーブルタイプ | ### V$STORAGE_DC_TABLES_STAT --- Logテーブルの内部情報を表示します。 | 列名 | 説明 | | ------------- | ----------- | | TABLESPACE_ID | テーブルスペース識別子 | | TABLE_ID | テーブル識別子 | | COUNT | レコード数 | | COLUMN_ID | 列識別子 | ### V$STORAGE_DC_TABLE_COLUMNS --- Logテーブルの列情報を表示します。 | 列名 | 説明 | | ------------------------- | ------------------------------- | | TABLE_ID | テーブル識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | ID | 列識別子 | | FLAG | プロパティフラグ | | SIZE | 列のデータサイズ | | PARTITION_VALUE_COUNT | パーティションに保存する最大データ数 | | PAGE_VALUE_COUNT | ページに保存する最大データ数 | | CACHE_VALUE_COUNT | キャッシュ値の最大数 | | MINMAX_CACHE_SIZE | 列パーティションのMIN/MAXキャッシュの最大サイズ | | CUR_APPEND_PARTITION_ID | 現在取り込み中のパーティション識別子 | | CUR_CACHE_PARTITION_COUNT | 現在のキャッシュにデータを読み込んだパーティション数 | | CUR_MINMAX_CACHE_SIZE | 現在のMIN/MAXキャッシュサイズ | | END_RID_FOR_DEFAULT_VALUE | この値より小さいRIDを持つ列値にはデフォルト値を使用 | | DISK_FILE_SIZE | 該当列の列パーティションデータファイルの合計サイズ | | MEMORY_TOTAL_SIZE | テーブルが使用中のメモリサイズ | | MEMORY_ALLOC_SIZE | テーブルに割り当てられたメモリサイズ | ### V$STORAGE_DC_TABLE_COLUMN_PARTS --- Logテーブルの列パーティション情報を表示します。 | 列名 | 説明 | | ----------------------------- | ---------------------------------------------------------------------------------- | | TABLE_ID | テーブル識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | COLUMN_ID | 列識別子 | | ID | パーティション識別子 | | FLAG | 列のプロパティを示すフラグ | | BEGIN_RID | パーティションに保存された最小RID | | END_RID | パーティションに保存された最後のRID | | END_SYNC_RID | SYNCが完了した最後のRID。
開始RIDより大きく最後のSYNC RIDより小さいRIDを持つデータは、パーティションファイルに記録されています。 | | MIN_TIME | 列パーティションに最初にデータを取り込んだ時刻 | | MAX_TIME | 列パーティションに最後にデータを取り込んだ時刻 | | MAX_VALUE_COUNT_PER_PARTITION | パーティションの最大データ数 | | MAX_VALUE_COUNT_PER_PAGE | ページ当たりの最大データ数 | | MAX_PAGE_COUNT | パーティション当たりの最大ページ数 | | PAGE_SIZE | 列パーティションに保存されたページのサイズ | | PAGE_COUNT | 現在の列パーティションに作成されたページ数 | | COMPRESS_RATIO | 列パーティションの圧縮率。0はまだデータ圧縮を実行していないことを示します。 | | DISK_FILENAME | パーティションファイル名 | | EXTERNAL_PART_SIZE | 大きな値を記録する外部パーティションファイルのサイズ | | MIN_VALUE | 列パーティションの最小値 | | MAX_VALUE | 列パーティションの最大値 | ### V$STORAGE_DC_TABLE_INDEXES --- Logテーブルに作成されたインデックス情報を表示します。 | 列名 | 説明 | | -------------------- | ---------------------------- | | TABLE_ID | テーブル識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | ID | インデックス識別子 | | FLAG | インデックスのプロパティを示すフラグ | | TABLE_BEGIN_RID | テーブルに取り込まれた最小RID | | TABLE_END_RID | テーブルの最後のRID | | BEGIN_RID | インデックスの最小RID | | END_RID | インデックスの最大RID | | END_SYNC_RID | ファイルに記録された最大RID+1 | | COLUMN_COUNT | インデックスの列数 | | BEGIN_PART_ID | インデックスの最初のパーティション識別子 | | END_PART_ID | インデックスの最後のパーティション識別子 | | FLUSH_REQUEST_COUNT | ディスクへの反映を要求されたインデックスパーティション数 | | MAX_KEY_SIZE | 最大キーサイズ | | INDEX_TYPE | インデックスタイプ | | DISK_FILE_SIZE | 該当インデックスのパーティションファイルの合計サイズ | | LAST_CHECKPOINT_TIME | 最後にチェックポイントを通過した時点 | ## LSM(Log Structured Merge) Index ### V$STORAGE_DC_LSMINDEX_LEVEL_PARTS --- LSMインデックスのパーティション情報を表示します。 | 列名 | 説明 | | -------------------------- | --------------------------------------- | | TABLE ID | インデックスが作成されたテーブルの識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | INDEX_ID | インデックス識別子 | | LEVEL | インデックスパーティションのLSMレベル | | PARTITION_ID | パーティション識別子 | | BEGIN_RID | パーティションに取り込まれた最小RID | | END_RID | パーティションに取り込まれた最大RID+1 | | KEY_VALUE_COUNT | パーティションに取り込まれたキー値の数 | | KEY_VALUE_TABLE_SIZE | キー値を保存するページのサイズ | | KEY_VALUE_TABLE_PAGE_COUNT | キー値を保存するページ数 | | MIN_KEY_VALUE | 最小キー値 | | MAX_KEY_VALUE | 最大キー値 | | BITMAP_TABLE_SIZE | ビットマップ値を保存するページの合計サイズ | | BITMAP_TABLE_PAGE_COUNT | ビットマップ値を保存するページ数 | | META_SIZE | メタデータを保存するページの合計サイズ | | META_PAGE_COUNT | メタデータを保存するページ数 | | TOTAL_BUILD_MSEC | 該当パーティションの完成までの合計時間 | | KEYVAL_BUILD_MSEC | KeyValue Modeで該当パーティションの完成までの合計時間 | | BITMAP_BUILD_MSEC | Bitmap Modeで該当パーティションの完成までの合計時間 | ### V$STORAGE_DC_LSMINDEX_LEVEL_PARTS_CACHE --- LSMインデックスのパーティションキャッシュ情報を表示します。 | 列名 | 説明 | | -------------------------- | --------------------------- | | BEGIN_RID | パーティションに取り込まれた最小RID | | BITMAP_TABLE_PAGE_COUNT | ビットマップ値を保存するページ数 | | BITMAP_TABLE_SIZE | ビットマップ値を保存するページの合計サイズ | | END_RID | パーティションに取り込まれた最大RID+1 | | INDEX_ID | インデックス識別子 | | KEY_VALUE_COUNT | パーティションに取り込まれたキー値の数 | | KEY_VALUE_TABLE_PAGE_COUNT | キー値を保存するページ数 | | KEY_VALUE_TABLE_SIZE | キー値を保存するページのサイズ | | LEVEL | インデックスパーティションのLSMレベル | | MEMORY_SIZE | メモリ使用量 | | MEMORY_SIZE_RBTREE | 赤黒木が使用したメモリ量 | | META_PAGE_COUNT | メタデータを保存するページ数 | | META_SIZE | メタデータを保存するページの合計サイズ | | PARTITION_ID | パーティション識別子 | | TABLE_ID | インデックスが作成されたテーブルの識別子 | | TABLESPACE_ID | テーブルスペース識別子 | ### V$STORAGE_DC_LSMINDEX_LEVELS --- LSMインデックスのレベル情報を表示します。 | 列名 | 説明 | | -------------- | ---------------------- | | TABLE_ID | テーブル識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | INDEX_ID | インデックス識別子 | | LEVEL | レベル | | BEGIN_RID | パーティションの最初のRID | | END_RID | パーティションの最後のRID+1 | | META_BEGIN_RID | メタデータの記録開始時点のRID | | META_END_RID | メタデータの記録終了時点のRID | | DELETE_END_RID | 削除されたRIDの最大値+1 | ### V$STORAGE_DC_LSMINDEX_FILES --- LSMインデックスを構成するファイルの情報を表示します。 | 列名 | 説明 | | ------------ | --------------- | | TABLE_ID | テーブル識別子 | | TABLESPACE_ID | テーブルスペース識別子 | | INDEX_ID | インデックス識別子 | | LEVEL | インデックスパーティションのLSMレベル | | PARTITION_ID | パーティション識別子 | | BEGIN_RID | パーティションの最初のRID | | END_RID | パーティションの最後のRID+1 | | PATH | インデックスファイルの場所 | ### V$STORAGE_DC_LSMINDEX_AGER_JOBS --- LSMインデックスの削除を担当するAgerの作業状態を表示します。 | 列名 | 説明 | | --------- | ------------------ | | TABLE_ID | テーブル識別子 | | INDEX_ID | インデックス識別子 | | LEVEL | インデックスパーティションのLSMレベル | | BEGIN_RID | パーティションの最初のRID | | END_RID | パーティションの最後のRID+1 | | STATE | Index Agerの作業状態 | ## Volatile Table ### V$STORAGE_DC_VOLATILE_TABLE --- Volatileテーブルの情報を表示します。 | 列名 | 説明 | | ------------ | --------------------------- | | MAX_MEM_SIZE | Volatileテーブルスペースの最大サイズ | | CUR_MEM_SIZE | Volatileテーブルスペースの現在のサイズ | ## Tag Table ### V$STORAGE_TAG_TABLES --- Tagdataテーブルのパーティションテーブルの情報を表示します。 | 列名 | 説明 | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ID | テーブル識別子 | | TABLE_BEGIN_RID | テーブルの開始RID | | TABLE_END_RID | テーブルの終了RID | | WRITE_END_RID | データファイルに記録された最後のRID | | EXT_ROW_COUNT | VARCHARレコードのうち外部パーティションに取り込まれた件数 | | EXT_WRITE_COUNT | VARCHARレコードのうちデータファイルに記録された件数 | | DISK_INDEX_END_RID | ストレージに保存されたインデックスの終了RID | | MEMORY_INDEX_END_RID | メモリインデックスにあるテーブルの終了RID | | DELETE_MIN_DATE | DELETE ... BETWEEN ...実行時の削除対象の最小時刻 | | DELETE_MAX_DATE | DELETE ... BETWEEN ...またはDELETE ... BEFORE ...実行時の削除対象の最大時刻 | | INDEX_STATE | 現在のインデックス構築状態
IDLE: 構築完了、待機中
PROGRESS: 構築中
IOWAIT: ストレージI/O待機
PENDING: テーブルの読み取りロック待機
SHUTDOWN: 停止。DELETEまたはDROP操作が実行中
ABNORMAL: 異常終了 | | DELETE_STATE | 現在のDELETE操作の状態。DELETEコマンドを受けたときのみ実行するため、IDLEはありません。
PROGRESS: 削除中
IOWAIT: ストレージI/O待機
PENDING: テーブルの読み取り/書き込みロック待機
SHUTDOWN: 停止。DELETE操作は実行されていません
ABNORMAL: 異常終了 | | SAVE_STATE | 現在のテーブル保存操作の状態
IDLE: 保存完了、待機中
PROGRESS: 保存中
IOWAIT: ストレージI/O待機
PENDING: テーブルの読み取りロック待機
SHUTDOWN: 停止。DELETEまたはDROP操作が実行中
ABNORMAL: 異常終了 | | VINDEX_STATE | 現在のVARCHARインデックス構築状態
IDLE: 構築完了、待機中
PROGRESS: 構築中
IOWAIT: ストレージI/O待機
PENDING: テーブルの読み取りロック待機
SHUTDOWN: 停止。DELETEまたはDROP操作が実行中
ABNORMAL: 異常終了 | ### V$STORAGE_TAG_CACHE --- Tagdataテーブルのパーティションテーブルが使用するキャッシュ情報を表示します。 | 列名 | 説明 | | ----------- | ------------------------ | | POOL_ID | キャッシュプール識別子 | | CATEGORY | キャッシュされているオブジェクトの分類 | | USED_MEMORY | 使用中のメモリサイズ | | BLOCK_COUNT | データキャッシュ数 | | CACHE_HIT | データキャッシュヒット回数 | | CACHE_MISS | データキャッシュミス回数 | | FLUSHOUT | データキャッシュの競合でページを解放した回数 | | COLD_READ | ストレージから直接読み取ったデータページ数 | | MEMORY_WAIT | データメモリがキャッシュの競合で待機した回数 | | IO_WAIT | データ読み取り操作の待機回数 | ### V$STORAGE_TAG_CACHE_BASE --- タグキャッシュプールの集計情報を表示します。 | 列名 | 説明 | | -- | -- | | POOL_ID | キャッシュプール識別子 | | TOTAL_CACHE_MEMORY | キャッシュメモリの合計 | | TOTAL_OBJECT_COUNT | キャッシュオブジェクトの総数 | | TOTAL_LRU_LOOP_COUNT | LRUループの総数 | ### V$STORAGE_TAG_CACHE_OBJECTS --- Tagdataテーブルのパーティションテーブルが使用する各キャッシュブロックの詳細情報を表示します。 | 列名 | 説明 | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | CATEGORY | キャッシュされているオブジェクトの分類 | | LATEST_HIT | 最終アクセス時刻 | | STATUS | キャッシュ状態
None: メモリ割り当て完了
Resides: キャッシュに保持された状態
Loading: ストレージからテーブルデータを読み込み中
ERROR!: データ読み込み中にエラーが発生 | | WAIT_COUNT | Loading状態でキャッシュを読めずに待機した回数 | | REF_COUNT | 現在のキャッシュブロックを参照中のセッション数 | | HIT_COUNT | キャッシュブロックの参照回数 | | TABLE_ID | テーブル識別子 | | FILE_ID | ファイル識別子 | | PART_ID | データファイル内のパーティション識別子 | | SAVE_SCN | テーブル保存SCN | | VSAVE_SCN | テーブル保存SCN | | DELETE_SCN | DELETE操作のSCN | | OFFSET | データファイルオフセット | | DATA_SIZE | 圧縮前のデータサイズ、または0 | ### V$STORAGE_TAG_TABLE_FILES --- Tagdataテーブルのパーティションテーブルのファイル情報を表示します。 | 列名 | 説明 | | --------- | ---------------------------------------------------------------------------------------------------------------------------------- | | TABLE_ID | テーブル識別子 | | FILE_ID | ファイル識別子 | | STATE | インデックス構築状態
COMPLETE: データ保存・インデックス構築完了
INDEXING: インデックス構築中
FILLED: データが満杯でインデックス構築待機中
PARTIAL: まだデータが満杯でなくインデックス構築待機中 | | REF_COUNT | 現在のファイルを参照中のセッション数 | | ROW_COUNT | 削除済みレコードを含めたファイル内のレコード数 | | DEL_COUNT | ファイルから削除されたレコード数 | | MIN_DATE | 該当ファイルに記録されたデータの最小日付 | | MAX_DATE | 該当ファイルに記録されたデータの最大日付 | ### V$STORAGE_TAG_INDEX --- Tagdataテーブルに作成されたインデックス情報を表示します。 | 列名 | 説明 | | -------------------- | ----------------------------------------------------------------------------------------------------- | | TABLE_ID | テーブル識別子 | | INDEX_ID | インデックス識別子(INDEX_IDが4294967295の場合、tagテーブルの作成時に自動作成されるデフォルトインデックスを示す) | | INDEX_STATE | インデックス構築状態
IDLE: 構築完了、待機中
INDEXING: 構築中
STORAGE FULL: ディスクが満杯のため構築停止 | | DISK_INDEX_END_RID | 最後にディスクに反映されたインデックスのEndRID | | MEMORY_INDEX_END_RID | 最後にメモリに反映されたインデックスのEndRID | | TABLE_END_RID | 最後にテーブルに反映されたデータのEndRID | ## Tag Rollup ### V$ROLLUP --- TagdataテーブルのRollup情報を表示します。 | 列名 | 説明 | | -------------- | ------------------------------------------------------- | | DATABASE_ID | 論理データベース識別子 | | ID | RollupジョブID | | ROLLUP_TABLE | Rollupテーブル名 | | SOURCE_TABLE | 集計対象テーブル名(TAG/ROLLUP) | | COLUMN_NAME | 集計対象の値の列 | | ROOT_TABLE | 最上位のソースタグテーブル名 | | USER_ID | 所有者のUser ID | | INTERVAL_TIME | データ集計間隔(ミリ秒) | | WAKEUP_INTERVAL | Rollupジョブの実行間隔(ミリ秒) | | LAST_WAKEUP_TIME | 直近のwakeup時刻 | | NEXT_WAKEUP_TIME | 次回のwakeup予定時刻 | | ENABLED | Rollupが有効かどうか(1/0) | | END_RID | このRollupが処理したSource Tableの最後のRID | | LAST_ELAPSED_MSEC | 直前のRollup実行の所要時間(ミリ秒) | | EXT_TYPE | 拡張(EXTENSION)の有無のフラグ | | PREDICATE | 条件付きロールアップのフィルター式(NULLは条件なし) | | RUN_STATE | スレッド状態: I=INIT, S=SLEEPING, R=RUNNING | ## License ### V$LICENSE_INFO --- ライセンス情報を表示します。 | 列名 | 説明 | | ---------------- | ---------------------- | | ID | ライセンスID | | ISSUE_DATE | 発行日 | | TYPE | ライセンスタイプ | | CUSTOMER | 顧客名 | | PROJECT | プロジェクト名 | | COUNTRY_CODE | 国コード | | INSTALL_DATE | インストール日 | | VIOLATE_STATUS | ライセンス違反状態 | | VIOLATE_MSG | ライセンス違反メッセージ | `V$LICENSE_STATUS`はStandard 8.5.4サーバーでは公開されていません。Standard Editionで 参照できるライセンスのフィールドには`V$LICENSE_INFO`を使用してください。 ## Mutex ### V$MUTEX --- 現在のミューテックスの状態を表示します。 `WAIT_MSEC`、`WAIT_AVG_MSEC`、`HELD_MSEC`、`HELD_AVG_MSEC`はミリ秒単位の`DOUBLE`値です。 | フィールド名 | 説明 | 備考 | | -------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------- | | OBJECT | ミューテックスオブジェクトのアドレス | | | NAME | ミューテックス作成時に付けた名前 | | | TYPE | ミューテックスタイプ | Mutex: pmuMutex
RW Mutex: pmuRWMutex | | OWNER | ミューテックスを取得したスレッドのID | Mutex: 取得したスレッドがなければ0
RW Mutex w/ Read-Lock: 0
RW Mutex w/ Write-Lock: 書き込みロックを取得したスレッドのID | | LOCK_COUNT | ミューテックスを取得したスレッド数 | RW Mutexでは2以上になる場合があります。 | | PEND_COUNT | ミューテックスの取得待機中のスレッド数 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集 | | TRY_COUNT | ミューテックスの取得試行回数 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集 | | CONFLICT_COUNT | ミューテックスの取得失敗回数 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集 | | WAIT_MSEC | ミューテックスの取得待機時間の合計 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集
RW Mutexでは記録しない | | WAIT_AVG_MSEC | ミューテックスの取得試行から成功までの平均時間 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集
RW Mutexでは記録しない | | HELD_MSEC | ミューテックスの取得から解放までの合計時間 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集
RW Mutexでは記録しない | | HELD_AVG_MSEC | ミューテックスの取得から解放までの平均時間 | TRACE_MUTEX_WAIT_STATUS=1の場合のみ収集
RW Mutexでは記録しない | ### V$MUTEX_WAIT_STAT --- 現在ミューテックスを待機しているコールスタックを表示します。 | フィールド | 説明 | 備考 | | --------- | ------------------- | -------------------------------- | | THREAD_ID | ミューテックスの取得待機中のスレッドID | | | OBJECT | 取得を試みているミューテックスのアドレス | V$MUTEXのOBJECTと同じ | | DEPTH | 呼び出しの深さ | TRACE_MUTEX_WAIT_STACK=1の場合のみ収集 | | SYMBOL | ミューテックスの取得を呼び出した関数のシンボル | TRACE_MUTEX_WAIT_STACK=1の場合のみ収集 | ## Cluster 次の仮想テーブルはCluster Edition専用で、Standardサーバーでは公開されません。 実行中のEditionで参照できることを`V$TABLES`で確認してから使用してください。 ### V$NODE_STATUS --- クラスターの各ノードの状態を表示します。1行だけ表示します。 | 列名 | 説明 | | -------- | ------------------------------------------------------------- | | NODETYPE | ノードタイプ。クエリで参照できるタイプは次の2つのみです。
Broker
Warehouse | | STATE | ノード状態 | ### V$DDL_INFO --- クラスターで実行したDDL情報を表示します。 | 列名 | 説明 | | -------------- | ----------------------- | | SEQUENCENUMBER | DDLのシーケンス番号 | | TIME | DDL実行時刻 | | VALUE | DDLクエリの結果値(サーバー内部用) | | CLIENT | クライアント名 | | BROKER | Leader Brokerのノード名 | | USER | ユーザー名 | | SQL | DDLクエリの値 | ### V$REPLICATION --- レプリケーションの動作情報を表示します。 | 列名 | 説明 | | ---------------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | MODE | サーバー内部用 | | STATE | ノード状態 | | ADDR | Replication Managerのアドレス | | PORT_NO | Replication Managerのポート番号 | | MAX_SENDER_COUNT | 作成できるSenderの最大数 | | RUN_SENDER_COUNT | 動作中のSenderの最大数 | ### V$REPL_SENDER --- レプリケーション動作時のSender情報を表示します。 | 列名 | 説明 | | ------------------ | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | ID | Sender識別子 | | STATUS | Senderスレッドの動作状態 | | PAYLOAD_RECV_COUNT | Senderから受信したペイロード数 | | PAYLOAD_RECV_BYTES | Senderから受信したペイロードの合計サイズ | | QUEUE_REMAIN_COUNT | Receive Queueに残るバッファー数 | | NET_SEND_COUNT | 総送信回数 | | NET_SEND_SIZE | 総送信サイズ | | NET_RECV_COUNT | 総受信回数 | | NET_RECV_SIZE | 総受信サイズ | ### V$REPL_SENDER_META --- レプリケーション動作時のSenderメタデータを表示します。 | 列名 | 説明 | | ---------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | SENDER_ID | Sender識別子 | | TABLE_ID | 対象テーブル識別子 | | TABLE_TYPE | 対象テーブルタイプ | | BEGIN_RID | 対象レコードの開始RID | | END_RID | 対象レコードの終了RID | ### V$REPL_RECEIVER --- レプリケーション動作時のReceiver情報を表示します。 | 列名 | 説明 | | ------------------ | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | STATUS | Receiverスレッドの動作状態 | | PAYLOAD_RECV_COUNT | Senderから受信したペイロード数 | | PAYLOAD_RECV_BYTES | Senderから受信したペイロードの合計サイズ | | QUEUE_REMAIN_COUNT | Receive Queueに残るバッファー数 | | NET_SEND_COUNT | 総送信回数 | | NET_SEND_SIZE | 総送信サイズ | | NET_RECV_COUNT | 総受信回数 | | NET_RECV_SIZE | 総受信サイズ | ### V$REPL_RECEIVER_META --- レプリケーション動作時のReceiverメタデータを表示します。 | 列名 | 説明 | | ---------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | TABLE_ID | 対象テーブル識別子 | | TABLE_TYPE | 対象テーブルタイプ | | BEGIN_RID | 対象レコードの開始RID | | END_RID | 対象レコードの終了RID | ### V$REPL_READER --- レプリケーション動作時のReader情報を表示します。 | 列名 | 説明 | | ----------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | SENDER_ID | Sender識別子 | | ID | Reader識別子 | | STATUS | Readerスレッドの動作状態 | | FETCH_COUNT | FETCH実行回数 | ### V$REPL_READER_META --- レプリケーション動作時のReaderメタデータを表示します。 | 列名 | 説明 | | ---------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | SENDER_ID | Sender識別子 | | ID | Reader識別子 | | TABLE_ID | 対象テーブル識別子 | | TABLE_TYPE | 対象テーブルタイプ | | BEGIN_RID | 対象レコードの開始RID | | END_RID | 対象レコードの終了RID | ### V$REPL_WRITER --- レプリケーション動作時のWriter情報を表示します。 | 列名 | 説明 | | ------------ | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | ID | Writer識別子 | | STATUS | Writerスレッドの動作状態 | | APPEND_COUNT | APPEND実行回数 | ### V$REPL_WRITER_META --- レプリケーション動作時のWriterメタデータを表示します。 | 列名 | 説明 | | ---------- | ---------------------------------- | | HOSTNAME | レプリケーションが動作するノードのホスト名 | | ID | Writer識別子 | | TABLE_ID | 対象テーブル識別子 | | TABLE_TYPE | 対象テーブルタイプ | | BEGIN_RID | 対象レコードの開始RID | | END_RID | 対象レコードの終了RID | ## Others ### V$TABLES --- V$で始まるすべての仮想テーブルを表示します。 | 列名 | 説明 | | ----------- | ------------ | | NAME | テーブル名 | | TYPE | テーブルタイプ | | DATABASE_ID | データベース識別子 | | ID | テーブル識別子 | | USER_ID | テーブルを作成したユーザー | | COLCOUNT | 列数 | ### V$COLUMNS --- 仮想テーブルの列情報を表示します。 | 列名 | 説明 | | -------------------- | ---------- | | NAME | 列名 | | TYPE | 列のデータ型 | | DATABASE_ID | データベース識別子 | | ID | 列の識別子 | | LENGTH | 列のサイズ | | TABLE_ID | テーブル識別子 | | FLAG | 非公開データ | | PART_PAGE_COUNT | 未使用 | | PAGE_VALUE_COUNT | 未使用 | | MINMAX_CACHE_SIZE | 未使用 | | MAX_CACHE_PART_COUNT | 未使用 | ### V$RETENTION_JOB --- RETENTION POLICYが適用されたテーブルの情報を表示します。 | 列名 | 説明 | | ------------------- | ------------------------------------------ | | USER_NAME | ユーザー名 | | TABLE_NAME | 対象TAG TABLE名 | | POLICY_NAME | 適用されているPOLICY名 | | STATE | RETENTION状態(RUNNING/WAITING/STOPPED) | | LAST_DELETED_TIME | 最後に削除した時刻 | ### V$USER_AUTH_KEYS --- チャレンジ認証に登録された公開鍵情報を表示します。 | 列名 | 説明 | | -- | -- | | KEY_ID | 鍵識別子 | | USER_ID | ユーザー識別子 | | USER_NAME | ユーザー名 | | KEY_ALGO | 鍵アルゴリズム | | KEY_PARAM | 鍵パラメーター | | PUBKEY | 公開鍵のテキスト | | ACTIVATED | 鍵が有効かどうか | | VALID_AFTER | 鍵の有効期間の開始日 | | VALID_BEFORE | 鍵の有効期間の終了日 | | COMMENT | 鍵の説明 | --- title: "16.4 コマンドラインツールリファレンス" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/ language: ja kind: section --- # 16.4 コマンドラインツールリファレンス Machbaseはサーバー管理、データのインポート/エクスポート、クエリ実行のためのコマンドラインツールを提供します。このセクションでは各ツールのオプションと使用方法を確認できます。 ## ツール一覧 | ツール | Edition | 説明 | |------|--------|------| | [machadmin](./machadmin/) | Standard / Cluster | サーバーの起動/終了、データベースの作成/削除、ライセンス管理 | | [machsql](./machsql/) | Standard / Cluster | 対話型SQLターミナル | | [machloader](./machloader/) | Standard / Cluster | CSVなどのテキストファイルのインポート/エクスポート | | [csvimport / csvexport](./csvimport-csvexport/) | Standard / Cluster | CSVファイル専用の簡易インポート/エクスポートラッパー | | [tagmetaimport](./tagmetaimport/) | Standard / Cluster | TAGテーブルのメタデータの一括インポート | | [machclusterctl](./machclusterctl/) | Cluster | クラスター全体の起動/終了/管理 | | [machcoordinatoradmin](./machcoordinatoradmin/) | Cluster | Coordinatorノードの管理とクラスター構成 | | [machdeployeradmin](./machdeployeradmin/) | Cluster | Deployerノードの管理 | ## 共通の接続オプション 次は`machsql`の接続オプションです。オプション名とデフォルト値はツールごとに異なるため、 別のツールではそのオプションリファレンスや`--help`の出力を確認してください。特に、サーバーを 直接管理する`machadmin`のオプションとSQLクライアントの接続オプションを混同しないでください。 | オプション | デフォルト値 | 説明 | |------|--------|------| | `-s`, `--server` | 127.0.0.1 | サーバーIPアドレス | | `-P`, `--port` | 5656 | サーバーポート番号 | | `-u`, `--user` | SYS | ユーザー名 | | `-p`, `--password` | MANAGER | ユーザーパスワード | ## ツールの場所 インストールパッケージのツールは`$MACHBASE_HOME/bin/`ディレクトリにあります。 使用できるツールはインストールしたEditionとパッケージによって異なります。 ```bash ls $MACHBASE_HOME/bin/ # machadmin machsql machloader csvimport csvexport tagmetaimport ... ``` PATHに`$MACHBASE_HOME/bin`が登録されていれば、ツール名だけで実行できます。 ```bash export PATH=$MACHBASE_HOME/bin:$PATH machadmin -e ``` --- title: "16.4.1 machadmin" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machadmin/ language: ja kind: page --- # 16.4.1 machadmin `machadmin`は、Machbaseサーバーの起動・終了、データベースの作成・削除、実行状態の確認を行う管理ツールです。 ## オプション一覧 ```bash machadmin -h ``` | オプション | 説明 | |------|------| | `-u`, `--startup` | Machbase サーバーの起動 | | `--recovery[=simple,complex,reset]` | 起動時の復旧モードの指定(デフォルト値: simple) | | `-s`, `--shutdown` | Machbaseサーバーの正常終了(graceful) | | `-k`, `--kill` | Machbaseサーバーの強制終了 | | `-c`, `--createdb` | Machbase データベースの作成 | | `-d`, `--destroydb` | Machbase データベースの削除 | | `-e`, `--check` | サーバーの実行状態確認 | | `-i`, `--silent` | バナーを表示せずに実行 | | `-r`, `--restore` | バックアップからデータベースを復元 | | `-x`, `--extract` | バックアップファイルをバックアップディレクトリに変換 | | `-w`, `--viewimage` | バックアップイメージファイルの情報を表示 | | `-t`, `--licinstall` | ライセンスファイルのインストール | | `-f`, `--licinfo` | インストール済みライセンスの情報を表示 | | `--home-path=path` | Machbaseホームパスの指定 | ## サーバーの起動 ```bash machadmin -u ``` ### 復旧モードの指定 ```bash machadmin -u --recovery=simple # デフォルトの復旧(正常終了後) machadmin -u --recovery=complex # 電源喪失後の再起動時に自動適用 machadmin -u --recovery=reset # simple/complexによる復旧失敗時に全体を検査 ``` | 復旧モード | 説明 | |----------|------| | `simple` | 正常終了後の再起動時のデフォルト復旧。実行時間が短い | | `complex` | 電源喪失などの異常終了後の再起動時に自動適用。`simple`より時間がかかる | | `reset` | 全テーブルのデータを検査して復旧。一部のデータが失われる可能性がある | ## サーバーの終了 正常終了(実行中の作業が完了してから終了): ```bash machadmin -s ``` 強制終了(プロセスを即座に終了): ```bash machadmin -k ``` ## データベースの作成と削除 ```bash # データベースの作成 machadmin -c # データベースの削除(確認プロンプトを表示) machadmin -d ``` ## サーバーの実行状態確認 ```bash machadmin -e ``` サーバーが実行中の場合はPIDを表示します。 ``` Machbase server is already running with PID (14098). ``` サーバーが実行中でなければエラーを表示します。 ``` [ERR] Server is not running. ``` ## データベースの復元 バックアップディレクトリからデータベースを復元します。 ```bash machadmin -r /path/to/backup ``` 例: ```bash machadmin -r /home/mach/backup/machbase_backup_20240101 ``` ## ライセンス管理 ライセンスファイルのインストール: ```bash machadmin -t /path/to/license.dat ``` インストール済みライセンスの情報確認: ```bash machadmin -f ``` ## サイレントモード バナーと状態メッセージを表示せずに実行します。スクリプトで便利に使用できます。 ```bash machadmin -i -u # サーバーの起動 (バナーなし) machadmin -i -s # サーバーの終了 (バナーなし) machadmin -i -e # 状態確認 (バナーなし) ``` ## 使用例 ```bash # データベースの初期設定とサーバーの起動 machadmin -c machadmin -u # サーバーの状態を確認して終了 machadmin -e machadmin -s # ライセンスの更新 machadmin -s machadmin -t new_license.dat machadmin -u ``` --- title: "16.4.2 machsql" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machsql/ language: ja kind: page --- # 16.4.2 machsql `machsql`は、ターミナルでSQLクエリを対話的に実行するクライアントツールです。SQLスクリプトの実行、結果のファイル保存、公開鍵認証にも対応します。 ## オプション一覧 ```bash machsql -h ``` | 短いオプション | 長いオプション | デフォルト値 | 説明 | |----------|---------|--------|------| | `-s` | `--server` | 127.0.0.1 | 接続先サーバーIPアドレス | | `-P` | `--port` | 5656 | サーバーポート番号 | | `-u` | `--user` | SYS | ユーザー名 | | `-p` | `--password` | MANAGER | ユーザーパスワード | | `-K` | `--auth-key-file` | - | 公開鍵認証用の秘密鍵ファイルのパス(8.5以降) | | | `--auth-sig-scheme` | - | 認証署名方式。`ECDSA`、`RSA_PKCS1_V15`、`RSA_PSS`(8.5以降) | | `-f` | `--script` | - | 実行するSQLスクリプトファイル | | `-o` | `--output` | - | クエリ結果の保存先ファイル名 | | `-r` | `--format` | csv | 出力ファイル形式(`csv`、`json`など) | | `-z` | `--timezone` | - | タイムゾーン設定。例: `+0900`、`-1230` | | `-n` | `--nls` | - | NLS設定 | | `-c` | `--connstr` | - | 追加の接続パラメーター文字列(6.1以降) | | `-D` | `--database` | `MACHBASEDB` | 接続直後に使用する論理データベース(8.7.0 Standard) | | `-i` | `--silent` | - | 著作権バナーを表示せずに実行 | | `-v` | `--verbose` | - | 詳細出力 | | `-x` | `--testing` | - | テストモードで実行 | | `-h` | `--help` | - | オプション一覧を表示 | ## 接続例 基本的な接続: ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER machsql --server=localhost --user=SYS --password=MANAGER ``` ポートの指定: ```bash machsql -s 192.168.1.10 -P 5656 -u SYS -p MANAGER ``` SQLスクリプトの実行: ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -f create_tables.sql ``` タイムゾーンの指定: ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -z +0900 machsql -s 127.0.0.1 -u SYS -p MANAGER -z -1230 ``` 結果をファイルに保存: ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -o result.csv -f query.sql ``` ## 公開鍵認証(Machbase 8.5以降) パスワードの代わりに公開鍵によるチャレンジ認証を使用できます。 ECDSA鍵で接続: ```bash machsql -s 127.0.0.1 -u app_user \ -K /opt/machbase/keys/app_user_ecdsa.pem \ --auth-sig-scheme=ECDSA ``` RSA-PSS鍵で接続: ```bash machsql -s 127.0.0.1 -u app_user \ -K /opt/machbase/keys/app_user_rsa.pem \ --auth-sig-scheme=RSA_PSS ``` 対応する鍵アルゴリズム: | アルゴリズム | 鍵パラメーター | デフォルトの署名方式 | |---------|-----------|--------------| | ECDSA | P-256, P-384, P-521 | `ECDSA` | | RSA | 2048, 3072, 4096 bits | `RSA_PKCS1_V15` | ## 追加の接続パラメーター(6.1以降) `-c`オプションで追加の接続パラメーターを指定します。 ```bash machsql -s 127.0.0.1 -u SYS -p MANAGER -P 5656 \ -c 'ALTERNATIVE_SERVERS=192.168.0.147:9209;CONNECTION_TIMEOUT=10' ``` 環境変数でも設定できます。 ```bash export MACHBASE_CONNECTION_STRING="ALTERNATIVE_SERVERS=192.168.0.148:8888;CONNECTION_TIMEOUT=3" machsql -s 127.0.0.1 -u SYS -p MANAGER ``` `-c`オプションが環境変数より優先されます。 ## 論理データベースの選択 Machbase 8.7.0 Standard Editionでは、`-D`または`--database`で接続直後に使用する 論理データベースを指定できます。 ```bash machsql -s 127.0.0.1 -u app_a -p 'AppA#1234' -D factory_a machsql -s 127.0.0.1 -u app_a -p 'AppA#1234' --database=factory_a ``` `-c`接続文字列では、`DATABASE=factory_a`または互換性のための別名`DBNAME=factory_a`を指定できます。 `-D`と接続文字列でデータベースの値が異なると接続が拒否されるため、一方のみを指定するか同じ値を 使用してください。接続後に次のSQLで実際のサーバーカタログを確認します。 ```sql SELECT CURRENT_DATABASE(); SHOW CURRENT DATABASE; ``` ## machsql組み込みコマンド machsqlプロンプト(`Mach>`)で使用できる組み込みコマンドです。 | コマンド | 説明 | |------|------| | `SHOW TABLES` | すべてのテーブル一覧を表示 | | `SHOW TABLE table_name` | 特定テーブルの列とインデックスの情報を表示 | | `SHOW INDEXES` | すべてのインデックス一覧を表示 | | `SHOW INDEX index_name` | 特定インデックスの情報を表示 | | `SHOW INDEXGAP` | インデックス構築のGAP情報を表示 | | `SHOW LSM` | LSMインデックスの構築情報を表示 | | `SHOW TABLESPACES` | すべてのテーブルスペース一覧を表示 | | `SHOW TABLESPACE name` | 特定テーブルスペースの情報を表示 | | `SHOW STORAGE` | テーブル別のディスク使用量を表示 | | `SHOW STATEMENTS` | サーバーに登録されたクエリ一覧を表示 | | `SHOW USERS` | ユーザー一覧を表示 | | `SHOW LICENSE` | ライセンス情報を表示 | | `SHOW DATABASES` | アクティブ/マウント済みデータベース一覧を表示 | | `SHOW CURRENT DATABASE` | 現在のセッションのデータベースを表示 | | `SHOW LAST ROWID` | 直近に成功した単一行INSERTのROWIDを表示 | | `SHOW LASTID` | `SHOW LAST ROWID`と同じコマンド | ### 最後のINSERTのROWID確認 Machbase 8.7.0 Standard Editionでは、単一行の`INSERT ... VALUES`の実行直後に挿入した行の ROWIDを確認できます。 ```sql INSERT INTO orders(item) VALUES('pump'); SHOW LAST ROWID; ``` ```text Last ROWID : 2048 ``` `SHOW LASTID`も同じ値を表示します。返すROWIDがなければ、`0`ではなく`NULL`を表示します。 INSERT失敗、batch・Append・loader、`INSERT ... SELECT`、UPSERT、再接続の後に以前の値を 使用しないでください。SELECTやCOMMITなどINSERT以外のコマンドは最後の値を保持します。 テーブル別のROWID条件とSDKでの確認方法は、 [ROWIDとINSERT結果ID](/ja/dbms/reference/sql/rowid/)を参照してください。 ## DESCとPRIMARY KEYメタデータ `DESC table_name`は、列とインデックスの情報に続いて`[ PRIMARY KEY ]`セクションを表示します。 PRIMARY KEY名、列名、キーの順序を確認できます。TRANSACTION・LOOKUP・VOLATILEで宣言されたPKと TAGテーブルの`NAME`が対象です。通常のLOGテーブルではPK行を表示しません。 ```sql DESC ACCOUNT; ``` この出力はSELECT結果列のメタデータとは別です。SDKでSELECT結果の列がPKかどうかを確認する方法は、 [PRIMARY KEYメタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-primary-key-metadata)を 参照してください。 ## ARRAYの表示とDESC Machbase DBMS 8.7.0の`DESC`はARRAY列を`INT32[3]`、`DECIMAL(12,4)[2]`などの正規の宣言形式で 表示します。クエリ結果は`[value,null,value]`形式です。小文字の`null`は要素のNULLを表し、 列の値全体がNULLの場合は通常のSQL `NULL`として表示します。 ```sql SELECT ID, CHANNELS, ARRAY_LENGTH(CHANNELS), CHANNELS[1] FROM SENSOR_ARRAY ORDER BY ID; ``` ARRAYの宣言、NULLの区別、式は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ## Named Bind Parameter `machsql`の`PREPARE` SQLでは`:name`マーカーを使用できます。値は名前ではなく、 SQL内の出現順に`$1`、`$2`、...の変数へ指定します。 ```sql PREPARE INSERT INTO SENSOR_DATA (ID, NAME, VALUE) VALUES (:id, :name, :value); $1 := 900; $2 := 'machsql-client'; $3 := 72.125000; EXECUTE; PREPARE CLEAN; ``` 同じ名前が繰り返される場合も、各出現位置に値を指定します。 ```sql PREPARE SELECT ID, NAME FROM SENSOR_DATA WHERE ID = :id OR PARENT_ID = :id; $1 := 900; $2 := 900; EXECUTE; PREPARE CLEAN; ``` 名前の構文と出現順序の規則は、[Named Bind Parameter構文](../../sql/syntax/named-bind-parameter-syntax/)を 参照してください。 ## 使用例 ```bash # 対話モードで接続 machsql -s 127.0.0.1 -u SYS -p MANAGER # 接続後にテーブルを確認 Mach> SHOW TABLES; # テーブル構造の確認 Mach> SHOW TABLE sensor_data; # SQLスクリプトを実行し結果をCSVで保存 machsql -s 127.0.0.1 -u SYS -p MANAGER \ -f report.sql -o report_output.csv -i ``` --- title: "16.4.3 machloader" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machloader/ language: ja kind: page --- # 16.4.3 machloader `machloader`は、CSVなどのテキストファイルとMachbaseサーバー間でデータをインポート/エクスポートする汎用ロードツールです。デフォルトでAPPENDモードを使用し、スキーマファイルによる複雑な変換にも対応します。 ## オプション一覧 ```bash machloader -h ``` | オプション | 説明 | |------|------| | `-s`, `--server=SERVER` | サーバーIPアドレス (デフォルト値: 127.0.0.1) | | `-P`, `--port=PORT` | サーバーポート番号 (デフォルト値: 5656) | | `-u`, `--user=USER` | ユーザー名 (デフォルト値: SYS) | | `-p`, `--password=PASSWORD` | ユーザーパスワード (デフォルト値: MANAGER) | | `-i`, `--import` | インポートモード | | `-o`, `--export` | エクスポートモード | | `-c`, `--schema` | スキーマファイル生成モード | | `-t`, `--table=TABLE_NAME` | 対象テーブル名 | | `-f`, `--form=SCHEMA_FILE` | スキーマファイル名 | | `-d`, `--data=DATA_FILE` | データファイル名 | | `-m`, `--mode=MODE` | インポートモード。`append`(デフォルト)または`replace` | | `-H`, `--header` | ヘッダー行の有無。インポート時は先頭行をヘッダーとして扱い、エクスポート時は列名をヘッダーとして生成 | | `-D`, `--delimiter=DELIMITER` | フィールド区切り文字 (デフォルト値: `,`) | | `-n`, `--newline=NEWLINE` | レコード区切り文字 (デフォルト値: `\n`) | | `-e`, `--enclosure=ENCLOSURE` | フィールドの囲み文字 | | `-r`, `--format=FORMAT` | ファイル形式 (デフォルト値: csv) | | `-E`, `--encoding=CHARSET` | ファイルエンコーディング。UTF8(デフォルト)、ASCII、MS949、KSC5601、EUCJP、SHIFTJIS、BIG5、GB231280、UTF16 | | `-F`, `--dateformat=DATEFORMAT` | datetime列の日付形式。`unixtimestamp`または`nanotimestamp`を指定可能 | | `-z`, `--timezone` | タイムゾーン設定。例: `+0900`、`-1230` | | `-a`, `--atime` | `_ARRIVAL_TIME`列を含めるかどうか(デフォルト: 含めない) | | `-C`, `--create` | インポート時にテーブルがなければ自動作成 | | `-l`, `--log=LOG_FILE` | 実行ログファイル | | `-b`, `--bad=BAD_FILE` | 取り込みに失敗した行を記録するbadファイル | | `--first=FIRST_ROW` | 処理を開始する先頭行番号 | | `-I`, `--silent` | バナーと進行状況を表示せずに実行 | | `-S`, `--slash` | バックスラッシュ区切り文字の指定 | | `--summary` | 選択したオプション値を表示して終了(実際の処理はしない) | | `-h`, `--help` | オプション一覧を表示 | ## CSVファイルのインポート 基本的なインポート: ```bash machloader -i -d data.csv -t sensor_data ``` サーバー接続情報の指定: ```bash machloader -i -s 192.168.0.10 -P 5656 -u SYS -p MANAGER \ -d data.csv -t sensor_data ``` ヘッダー行のあるCSVのインポート: ```bash machloader -i -d data.csv -t sensor_data -H ``` 既存データを削除してからインポート(replaceモード): ```bash machloader -i -d data.csv -t sensor_data -m replace ``` 特定の行から開始: ```bash machloader -i -d data.csv -t sensor_data --first=10 ``` ## CSVファイルのエクスポート ```bash machloader -o -d output.csv -t sensor_data machloader -o -d output.csv -t sensor_data -H ``` `_ARRIVAL_TIME`列を含むエクスポート: ```bash machloader -o -d output.csv -t sensor_data -a ``` ### ARRAY列 Machbase DBMS 8.7.0のARRAY列は`[value,null,value]`形式でインポート/エクスポートします。 ARRAY内部にカンマを含むため、CSVフィールドを囲み文字で囲みます。 ```csv 1,"[1.5,null,3.5,4.5]" ``` NULLフィールドはARRAY全体のNULLを表し、`"[null,null]"`は全要素がNULLの非NULL ARRAYを表します。 `-C`によるテーブル自動作成ではARRAY型を推論しないため、ARRAY列が必要なテーブルは事前に 明示的に作成してください。型とNULL規則の詳細は[数値ARRAY型](/ja/dbms/reference/sql/types/array/)を参照してください。 ## エンコーディングと区切り文字の設定 EUC-KRエンコーディング、タブ区切り: ```bash machloader -i -d data.txt -t table_name -E MS949 -D '\t' ``` パイプ(`|`)区切り文字: ```bash machloader -i -d data.txt -t table_name -D '|' machloader -o -d data.txt -t table_name -D '|' ``` ## タイムゾーンの指定 ```bash machloader -i -d data.csv -t sensor_data -z +0900 machloader -i -d data.csv -t sensor_data -z -1230 ``` ## datetime形式の指定 コマンドラインで直接指定: ```bash machloader -i -d data.csv -t sensor_data \ -F "_arrival_time YYYY-MM-DD HH24:MI:SS" ``` Unixタイムスタンプで取り込み: ```bash machloader -i -d data.csv -t sensor_data \ -F "time_column unixtimestamp" ``` ナノ秒タイムスタンプで取り込み: ```bash machloader -i -d data.csv -t sensor_data \ -F "time_column nanotimestamp" ``` ## スキーマファイルの使用 スキーマファイルを作成します: ```bash machloader -c -t sensor_data -f sensor_data.fmt ``` スキーマファイルを使ったインポート/エクスポート: ```bash machloader -i -f sensor_data.fmt -d data.csv machloader -o -f sensor_data.fmt -d output.csv ``` スキーマファイル形式の例 (`sensor_data.fmt`): ``` table sensor_data { name varchar(64); time datetime; value double; } DATEFORMAT time "YYYY-MM-DD HH24:MI:SS" ``` 特定列を無視: ``` table sensor_data { id integer; name varchar(64); extra varchar(32) IGNORE; } ``` ## ログとbadファイル ```bash machloader -i -d data.csv -t sensor_data \ -l import.log -b import.bad ``` - `-l`: インポートの実行ログ(成功/失敗統計) - `-b`: 失敗した行データを元の形式で記録 ## テーブルの自動作成 テーブルがなければ自動作成します。列名は`c0`、`c1`、...の順で、型は`varchar(32767)`です。 ```bash machloader -i -d data.csv -t new_table -C machloader -i -d data.csv -t new_table -C -H # ヘッダーを列名として使用 ``` ## 使用例 ```bash # 実際のインポート前に設定を確認(--summary) machloader -i -d data.csv -t sensor_data --summary # 大容量ファイルのインポート(ログとbadファイルを指定) machloader -i -d bigdata.csv -t sensor_data \ -H -z +0900 \ -l import_20240101.log -b import_20240101.bad # テーブル全体のエクスポート machloader -o -d export_20240101.csv -t sensor_data -H -a ``` --- title: "16.4.4 csvimport / csvexport" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/csvimport-csvexport/ language: ja kind: page --- # 16.4.4 csvimport / csvexport `csvimport`と`csvexport`は、CSVファイル専用の簡易インポート/エクスポートラッパーです。`machloader`のCSV関連オプションを簡略化して提供します。以下にないオプションも`machloader`と同様に使用できます。 ## csvimport CSVファイルをMachbaseテーブルにインポートします。 ### オプション一覧 | オプション | 説明 | |------|------| | `-t`, `--table=TABLE_NAME` | 対象テーブル名 | | `-d`, `--data=DATA_FILE` | インポートするCSVファイル名 | | `-s`, `--server=SERVER` | サーバーIPアドレス (デフォルト値: 127.0.0.1) | | `-P`, `--port=PORT` | サーバーポート番号 (デフォルト値: 5656) | | `-u`, `--user=USER` | ユーザー名 (デフォルト値: SYS) | | `-p`, `--password=PASSWORD` | ユーザーパスワード (デフォルト値: MANAGER) | | `-H` | CSVの先頭行をヘッダーとして扱い、取り込みから除外 | | `-C` | テーブルがなければ自動作成(`-H`を併用するとヘッダーを列名として使用) | | `-m`, `--mode=MODE` | インポートモード。`append`(デフォルト)または`replace` | | `-a`, `--atime` | `_ARRIVAL_TIME`列を含める | | `-F`, `--dateformat=DATEFORMAT` | datetime列の日付形式 | | `-l`, `--log=LOG_FILE` | 実行ログファイル | | `-b`, `--bad=BAD_FILE` | 取り込みに失敗した行を記録するbadファイル | | `-I`, `--silent` | バナーと状態を表示せずに実行 | ### 基本的な使用方法 テーブル名とファイル名を指定します。 ```bash csvimport -t table_name -d data.csv ``` オプションなしで引数だけでも実行できます(順序は任意)。 ```bash csvimport table_name data.csv csvimport data.csv table_name ``` ### ヘッダー行の処理 CSVの先頭行をヘッダーとして扱い、データから除外します。 ```bash csvimport -t table_name -d data.csv -H ``` ### テーブルの自動作成 テーブルがなければ自動作成します。 ```bash # 列名をc0、c1、...として自動生成 csvimport -t table_name -d data.csv -C # CSV ヘッダーを列名として使用 csvimport -t table_name -d data.csv -C -H ``` 自動作成した列の型はすべて`varchar(32767)`です。 ### replaceモード 既存データを削除し、CSVファイルから再び取り込みます。 ```bash csvimport -t table_name -d data.csv -m replace ``` ### サーバー接続情報の指定 ```bash csvimport -s 192.168.0.10 -P 5656 -u SYS -p MANAGER \ -t sensor_data -d data.csv ``` ## csvexport MachbaseテーブルのデータをCSVファイルへエクスポートします。 ### オプション一覧 | オプション | 説明 | |------|------| | `-t`, `--table=TABLE_NAME` | エクスポートするテーブル名 | | `-d`, `--data=DATA_FILE` | 保存するCSVファイル名 | | `-s`, `--server=SERVER` | サーバーIPアドレス (デフォルト値: 127.0.0.1) | | `-P`, `--port=PORT` | サーバーポート番号 (デフォルト値: 5656) | | `-u`, `--user=USER` | ユーザー名 (デフォルト値: SYS) | | `-p`, `--password=PASSWORD` | ユーザーパスワード (デフォルト値: MANAGER) | | `-H` | 列名をCSVヘッダーとして生成 | | `-a`, `--atime` | `_ARRIVAL_TIME`列を含める | | `-F`, `--dateformat=DATEFORMAT` | datetime列の日付形式 | | `-l`, `--log=LOG_FILE` | 実行ログファイル | | `-I`, `--silent` | バナーと状態を表示せずに実行 | ### 基本的な使用方法 ```bash csvexport -t table_name -d output.csv ``` オプションなしで引数だけでも実行できます。 ```bash csvexport table_name output.csv csvexport output.csv table_name ``` ### ヘッダーを含むエクスポート 列名をCSVファイルの先頭行(ヘッダー)として出力します。 ```bash csvexport -t table_name -d output.csv -H ``` ### `_ARRIVAL_TIME`を含むエクスポート ```bash csvexport -t table_name -d output.csv -a ``` ## 使用例 ```bash # 基本的なインポート csvimport -t sensor_data -d sensor_20240101.csv # ヘッダー付きCSVのインポート csvimport -t sensor_data -d sensor_20240101.csv -H # 全データのエクスポート(ヘッダーを含む) csvexport -t sensor_data -d export_20240101.csv -H # ログファイルを指定してインポート csvimport -t sensor_data -d data.csv -H \ -l import.log -b import.bad # リモートサーバーからエクスポート csvexport -s 192.168.0.10 -P 5656 -u SYS -p MANAGER \ -t sensor_data -d remote_export.csv -H -a ``` --- title: "16.4.5 tagmetaimport" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/tagmetaimport/ language: ja kind: page --- # 16.4.5 tagmetaimport `tagmetaimport`はCSVファイルからTAGテーブルのメタデータを一括インポートするツールです。大量の TAG名とメタデータの登録に使用します。既存タグの自動更新やファイル全体の単一トランザクションでの反映は行いません。 ## オプション一覧 ```bash tagmetaimport -h ``` | オプション | 説明 | |------|------| | `-s`, `--server=SERVER` | サーバーIPアドレス (デフォルト値: 127.0.0.1) | | `-P`, `--port=PORT` | サーバーポート番号 (デフォルト値: 5656) | | `-u`, `--user=USER` | ユーザー名 (デフォルト値: SYS) | | `-p`, `--password=PASSWORD` | ユーザーパスワード (デフォルト値: MANAGER) | | `-t`, `--table=TABLE_NAME` | 対象のメタデータ保存テーブル名。論理sensor_tagには_SENSOR_TAG_METAを指定 | | `-d`, `--data=DATA_FILE` | メタデータCSVファイルのパス | | `-l`, `--log=LOG_FILE` | ログファイルのパス | | `-b`, `--bad=BAD_FILE` | 取り込みに失敗したレコードの保存先ファイル | | `-H`, `--header` | CSVの先頭行をヘッダーとして扱う | | `-D`, `--delimiter=DELIMITER` | フィールド区切り文字 (デフォルト値: `,`) | | `-E`, `--encoding=CHARSET` | ファイルエンコーディング (デフォルト値: UTF8) | | `-I`, `--silent` | 進行状況の出力を削減。完了サマリーで成功・失敗件数を確認 | | `-h`, `--help` | オプション一覧を表示 | ## 入力ファイル形式 メタデータCSVファイルは、TAGテーブルのメタデータ列の順序に合わせて作成します。 TAGテーブルの定義例: ```sql CREATE TAG TABLE sensor_tag ( name VARCHAR(64) PRIMARY KEY, time DATETIME BASETIME, value DOUBLE SUMMARIZED ) METADATA ( unit VARCHAR(32), location VARCHAR(128) ); ``` このテーブルのメタデータCSVファイル(`tag_meta.csv`): ``` name,unit,location sensor_001,celsius,Building-A Floor-1 sensor_002,celsius,Building-A Floor-2 sensor_003,bar,Boiler-Room sensor_004,rpm,Motor-Section ``` ヘッダーなしでデータだけの場合: ``` sensor_001,celsius,Building-A Floor-1 sensor_002,celsius,Building-A Floor-2 ``` ## 使用例 ### 基本的なインポート ```bash tagmetaimport -s 127.0.0.1 -P 5656 -u SYS -p MANAGER \ -t _SENSOR_TAG_META -d tag_meta.csv -H ``` ### ヘッダー付きCSVファイルのインポート ```bash tagmetaimport -s 127.0.0.1 -P 5656 -u SYS -p MANAGER \ -t _SENSOR_TAG_META -d tag_meta.csv -H ``` ### リモートサーバーへのインポート ```bash tagmetaimport -s 192.168.0.10 -P 5656 -u SYS -p MANAGER \ -t _SENSOR_TAG_META -d tag_meta.csv -H ``` ### タブ区切りファイル ```bash tagmetaimport -s 127.0.0.1 -P 5656 -u SYS -p MANAGER \ -t _SENSOR_TAG_META -d tag_meta.tsv -D '\t' -H ``` ### EUC-KRエンコーディングのファイル ```bash tagmetaimport -s 127.0.0.1 -P 5656 -u SYS -p MANAGER \ -t _SENSOR_TAG_META -d tag_meta_kr.csv -E MS949 -H ``` ## 動作 - `-t`は論理TAGをMETADATA対象へ自動変換しません。論理テーブルsensor_tagの対象は`_SENSOR_TAG_META`です。この名前はツールの取り込み先の指定にのみ使用します。 - 既存のタグ名は通常のMETADATA INSERTでエラーになります。失敗件数とbad/logファイルで確認します。 - データの取り込み後にメタデータを追加する場合、このツールが効率的です。 - 少量のメタデータはSQL INSERTまたは`machsql`で直接取り込むこともできます。 ```sql -- machsqlでメタデータを直接挿入 INSERT INTO sensor_tag METADATA (name, unit, location) VALUES ('sensor_005', 'volt', 'Panel-Room'); ``` ## 注意事項 - 事前にTAGテーブルを作成してください。 - CSVファイルの列順序はTAGテーブルのメタデータ列の順序に合わせてください。 - `BASETIME`列(`time`)と`SUMMARIZED`列(`value`)はメタデータファイルに含めません。 既存値の変更には`UPDATE sensor_tag METADATA ...`または明示的なSQL UPSERTを使用します。 再現可能な新規取り込みと重複取り込み失敗の例は、[メタデータの一括登録](../../../tag-table-usage/tagmetaimport/)を 参照してください。`_LAST_UPDATE_TIME`は、新規メタデータの取り込み時と値の実際の変更時にサーバーが管理します。 --- title: "16.4.7 machclusterctl" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machclusterctl/ language: ja kind: page --- # 16.4.7 machclusterctl `machclusterctl`は、Machbase Cluster Editionのクラスター全体を単一のコマンドで管理するツールです。YAML設定の検証、新規インストール、稼働中の構成変更、アップグレード、起動/終了、状態確認などを行います。 ## 主なコマンド | コマンド | 説明 | |------|------| | `validate` | `cluster.yaml`の検証 | | `install` | `cluster.yaml`に基づく新規クラスターのインストール | | `apply` | 稼働中のクラスターに設定変更を反映 | | `upgrade` | パッケージのアップグレード(`--online`、`--full-stop`) | | `export` | 稼働中のクラスター構成をフラットなYAMLでエクスポート | | `status` | クラスター全ノードの状態確認 | | `connect` | Broker/Warehouseのエイリアスへ`machsql`で接続 | | `start` | クラスター全ノードの起動 | | `stop` | クラスター全ノードの正常終了 | | `destroy` | クラスターの削除(データを含む) | ## 使用方法 ```bash machclusterctl [options] ``` ## コマンドの詳細 ### validate YAML設定ファイルを検証します。 ```bash machclusterctl validate -f cluster.yaml ``` ### install YAML設定ファイルを読み込み、新規クラスターをインストールします。 ```bash machclusterctl install -f cluster.yaml ``` ### apply 稼働中のクラスターに設定変更を反映します。 ```bash machclusterctl apply -f cluster.yaml ``` ### upgrade パッケージをアップグレードします。 ```bash machclusterctl upgrade --online broker machclusterctl upgrade --full-stop ``` ### start Coordinator → Deployer → Broker → Warehouseの順にクラスター全体を起動します。 ```bash machclusterctl start machclusterctl start -f cluster.yaml ``` ### stop クラスター全体を正常終了します。 ```bash machclusterctl stop ``` ### destroy クラスターを完全に削除します。データベースファイルも削除するため、注意して使用してください。 ```bash machclusterctl destroy ``` ### status クラスターの各ノードの現在の状態を表示します。 ```bash machclusterctl status ``` ### connect Brokerノードへ`machsql`で接続します。 ```bash machclusterctl connect ``` ### export 現在のクラスター構成をYAMLファイルへエクスポートします。 ```bash machclusterctl export -o cluster_backup.yaml ``` ## YAML設定ファイルの構造 `machclusterctl validate`、`install`、`apply`で使用するYAML設定ファイルの基本構造です。 ```yaml cluster: coordinator: host: 192.168.0.32 port: 5101 http_port: 5102 home: /home/machbase/coordinator1 deployer: - host: 192.168.0.32 port: 5201 home: /home/machbase/deployer1 broker: - host: 192.168.0.32 port: 5301 http_port: 5302 home: /home/machbase/broker1 service_port: 5757 warehouse: - group: Group1 host: 192.168.0.32 port: 5401 http_port: 5402 home: /home/machbase/warehouse_a1 service_port: 5400 ``` ## オプション | オプション | 説明 | |------|------| | `-f`, `--file` | クラスター設定YAMLファイルのパス | | `-s`, `--silent` | 進行ログの出力を削減 | | `-v`, `--verbose` | 詳細な進行ログを表示 | | `--node` | `start`/`stop`の対象ノードのエイリアスを指定 | | `--type` | `start`/`stop`の対象ノードタイプを指定 | | `-o`, `--output` | 出力ファイルのパス(`export`で使用) | | `-h`, `--help` | ヘルプを表示 | ## 使用例 ```bash # YAMLの検証 machclusterctl validate -f my_cluster.yaml # クラスターの新規インストール machclusterctl install -f my_cluster.yaml # 稼働中のクラスターに変更を反映 machclusterctl apply -f my_cluster.yaml # クラスターの起動 machclusterctl start # 特定タイプまたはノードのみ停止/起動 machclusterctl stop --node broker-1 machclusterctl start --type warehouse # 状態確認 machclusterctl status # Brokerに接続してSQLを実行 machclusterctl connect # クラスターの終了 machclusterctl stop # 設定のエクスポート machclusterctl export -o cluster_config_backup.yaml ``` --- title: "16.4.8 machcoordinatoradmin" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machcoordinatoradmin/ language: ja kind: page --- # 16.4.8 machcoordinatoradmin `machcoordinatoradmin`はMachbase Cluster EditionのCoordinatorノードを管理し、クラスター構成を制御するツールです。Cluster Editionパッケージにのみ含まれます。 ## オプション一覧 ```bash machcoordinatoradmin -h ``` ### 基本管理オプション | オプション | 説明 | |------|------| | `-u`, `--startup` | Coordinatorプロセスの起動 | | `-s`, `--shutdown` | Coordinatorプロセスの正常終了 | | `-k`, `--kill` | Coordinatorプロセスの強制停止 | | `-c`, `--createdb` | Coordinatorメタデータの作成 | | `-d`, `--destroydb` | Coordinatorのメタデータとパッケージファイルの削除 | | `-e`, `--check` | Coordinatorプロセスが実行中か確認 | | `-i`, `--silent` | バナーを表示せずに実行 | | `--home-path=path` | Machbaseホームパスの指定 | ### 設定参照オプション | オプション | 説明 | |------|------| | `--configuration[=name]` | 設定のキーと値を表示。特定キーのみの表示も可能 | | `--configure` | システムプロパティ一覧をすべて表示 | ### クラスター状態の制御 | オプション | 説明 | |------|------| | `--activate` | クラスター状態をServiceへ変更 | | `--deactivate` | クラスター状態をDeactivateへ変更 | | `--cluster-status` | クラスターの各ノードの状態概要を表示 | | `--cluster-status-full` | クラスターの各ノードの詳細状態を表示 | | `--cluster-node` | クラスター情報を表示 | | `--verbose` | 状態表示にDeployerの状態を含める | ### パッケージ管理 | オプション | 説明 | |------|------| | `--list-package[=package]` | 登録済みパッケージ一覧を表示。特定パッケージのみの表示も可能 | | `--add-package=package` | パッケージの追加 | | `--remove-package=package` | パッケージの削除 | ### ノード管理 | オプション | 説明 | |------|------| | `--list-node[=node]` | ノード情報一覧を表示 | | `--add-node=node` | ノードの追加 | | `--remove-node=node` | ノードの削除 | | `--attach-node=node` | 既存ノードをクラスターのメタデータに接続 | | `--detach-node=node` | ノードをクラスターのメタデータから切り離す | | `--upgrade-node=node` | ノードのアップグレード | | `--startup-node=node` | 特定ノードの起動 | | `--shutdown-node=node` | 特定ノードの正常終了 | | `--kill-node=node` | 特定ノードの強制停止 | ### Lookup ノード管理 | オプション | 説明 | |------|------| | `--startup-lookup` | Lookupノードの起動 | | `--shutdown-lookup` | Lookupノードの終了 | | `--set-lookup-master=node` | Lookup masterノードの指定 | ### Warehouseのグループ/状態管理 | オプション | 説明 | |------|------| | `--set-group-state=[normal\|readonly]` | 特定Warehouseグループの状態変更 | | `--set-warehouse-state=[normal\|scrapped]` | `--node`で指定したWarehouseノードの状態変更 | | `--force-restore-warehouse=node` | scrapped状態のWarehouseノードを強制復旧 | ### Broker管理 | オプション | 説明 | |------|------| | `--deactivate-broker=node` | 指定ノードをinactive状態へ変更 | | `--activate-broker=node` | 指定ノードをnormal状態へ変更 | ### スナップショット管理 | オプション | 説明 | |------|------| | `--snapshot-interval=sec` | スナップショット実行間隔(秒)の設定 | | `--exec-snapshot` | スナップショットの即時実行(`--group`が必要) | | `--snapshot-recover=node` | 指定ノードをスナップショットから復旧 | | `--exec-sync=node` | 指定ノードの同期を実行 | | `--snapshot-clean` | スナップショットの整理 | ### ホストリソース監視 | オプション | 説明 | |------|------| | `--get-host-resource` | 各ノードのホストリソース情報を表示 | | `--host-resource-enable` | ホストリソース情報の収集開始 | | `--host-resource-disable` | ホストリソース情報の収集停止 | ### 追加オプション(他のオプションと併用) | 追加オプション | 必須オプション | 説明 | |----------|----------|------| | `--file-name=filename` | `--add-package` | パッケージファイル名 | | `--port-no=portno` | `--add-node`, `--attach-node` | サービスポート番号 | | `--http-admin-port=portno` | Coordinator/Deployer `--add-node`, `--attach-node` | 管理RESTポート番号 | | `--deployer=node` | `--add-node` | Deployerノード名 | | `--package-name=name` | `--add-node`, `--upgrade-node` | インストール元のパッケージ名 | | `--home-path=path` | `--add-node`, `--attach-node` | ノードのインストール先 | | `--node-type=[broker\|warehouse\|lookup]` | `--add-node`, `--attach-node` | ノードタイプ | | `--lookup-type=[master\|slave\|monitor]` | `--add-node`, `--attach-node` | Lookup ノードタイプ | | `--node=node` | `--set-warehouse-state` | 状態変更の対象ノード | | `--alias=alias` | `--add-node`, `--attach-node` | ノードのエイリアス | | `--dbs-path=path` | `--add-node` (Broker/Warehouse) | データベースファイルのパス | | `--group=groupname` | `--add-node`, `--attach-node`, `--set-group-state`, `--exec-snapshot` | ノードのグループ名 | | `--replication=host:port` | `--add-node`, `--attach-node` | レプリケーション先のhost:port | | `--no-replicate` | `--add-node`, `--attach-node` | レプリケーションを無効化 | | `--primary=host:port` | `-u`, `--startup` | Secondary CoordinatorのPrimaryを指定 | | `--host=host` | `--get-host-resource` | 特定ホストを指定 | | `--metric=[cpu\|memory\|disk\|network]` | `--get-host-resource` | 表示するメトリクスの種類 | ## 使用例 ### 実行状態の確認 ```bash machcoordinatoradmin -e ``` ### クラスターの状態確認 ```bash machcoordinatoradmin --cluster-status machcoordinatoradmin --cluster-status-full ``` ### クラスターの有効化/無効化 ```bash machcoordinatoradmin --activate machcoordinatoradmin --deactivate ``` ### Warehouse ノードの追加 ```bash machcoordinatoradmin \ --add-node=192.168.0.32:5401 \ --node-type=warehouse \ --deployer=192.168.0.32:5201 \ --package-name=machbase \ --home-path=/home/machbase/warehouse_a1 \ --port-no=5400 \ --group=Group1 \ --alias=warehouse-a1 \ --dbs-path=/data/machbase/warehouse_a1_dbs ``` ### ノード一覧の確認 ```bash machcoordinatoradmin --list-node machcoordinatoradmin --list-node=192.168.0.32:5401 ``` ### Warehouseグループを読み取り専用に変更 ```bash machcoordinatoradmin --set-group-state=readonly --group=Group1 ``` ### 設定の参照 ```bash machcoordinatoradmin --configuration machcoordinatoradmin --configuration=decision ``` ### ホストリソース監視 ```bash machcoordinatoradmin --host-resource-enable machcoordinatoradmin --get-host-resource machcoordinatoradmin --get-host-resource --metric=cpu machcoordinatoradmin --get-host-resource --host=192.168.0.33 machcoordinatoradmin --host-resource-disable ``` --- title: "16.4.9 machdeployeradmin" url: https://docs.machbase.com/ja/dbms/reference/command-line-tools/machdeployeradmin/ language: ja kind: page --- # 16.4.9 machdeployeradmin `machdeployeradmin`はMachbase Cluster EditionのDeployerノードを直接管理するツールです。DeployerはCoordinatorの指示に従って各ノードにパッケージを配布し、インストールを行います。 通常は`machcoordinatoradmin`でDeployerを制御することを推奨します。制御できない場合に`machdeployeradmin`を直接使用します。 Cluster Editionパッケージにのみ含まれます。 ## オプション一覧 ```bash machdeployeradmin -h ``` | オプション | 説明 | |------|------| | `-u`, `--startup` | Deployerプロセスの起動 | | `-s`, `--shutdown` | Deployerプロセスの正常終了 | | `-k`, `--kill` | Deployerプロセスの強制停止 | | `-c`, `--createdb` | Deployerメタデータの作成 | | `-d`, `--destroydb` | Deployerメタデータの削除 | | `-e`, `--check` | Deployerプロセスが実行中か確認 | | `-i`, `--silent` | バナーを表示せずに実行 | ## プロセス管理 ### 起動 ```bash machdeployeradmin -u ``` ### 正常終了 ```bash machdeployeradmin -s ``` ### 強制停止 ```bash machdeployeradmin -k ``` ### 実行状態の確認 ```bash machdeployeradmin -e ``` 実行中の場合はPIDを表示します。 ``` Machbase Deployer is running with pid(29373)! ``` ## メタデータ管理 Deployerのメタデータを新規作成します。 ```bash machdeployeradmin -c ``` Deployerのメタデータを削除します。 ```bash machdeployeradmin -d ``` ## Deployerの役割 DeployerはCoordinatorの指示に従って次の作業を行います。 - Broker、Warehouse、LookupノードへのMachbaseパッケージの配布とインストール - ノードの設定ファイルの作成と管理 - ノードの起動/終了指示の転送 - ノードのアップグレードの支援 ## 使用例 ```bash # Deployerの初期設定 machdeployeradmin -c machdeployeradmin -u # 実行状態の確認 machdeployeradmin -e # 正常終了 machdeployeradmin -s # 問題発生時に強制停止 machdeployeradmin -k ``` ## 参考 クラスター構成とノード管理の大部分は`machcoordinatoradmin`で行います。`machdeployeradmin`はCoordinatorと通信できない場合やDeployer自体に問題がある場合に直接操作するために使用します。 クラスター管理の詳細は[machcoordinatoradmin](../machcoordinatoradmin/)を参照してください。 --- title: "16.6 サポート範囲と制約" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/ language: ja kind: section --- # 16.6 サポート範囲と制約 MachbaseのEdition別、テーブルタイプ別、SDK別の機能サポート範囲と既知の制約をまとめた クイックリファレンスです。動作の仕組みや使用例は各機能の章を参照し、特定環境でのサポート可否は このセクションで確認してください。 ## このセクションの構成 | ページ | 内容 | |--------|------| | [Edition別機能サポート表](./edition/) | Standard EditionとCluster Editionの機能比較 | | [テーブルタイプ別機能サポート表](./table-types-type/) | TAG / LOG / LOOKUP / VOLATILE / TRANSACTIONのサポート機能 | | [SDK別機能サポート表](/ja/dbms/development-tools-integration/sdk-support-scope/) | JDBC、Python、Go、.NET、Node.jsのサポート範囲 | | [ROLLUPのサポート範囲](./rollup/) | Edition別・テーブルタイプ別のROLLUPサポート範囲 | | [バックアップ/マウントサポート表](./backup-mount/) | BACKUP / MOUNT機能のEdition別サポート可否 | | [権限別機能サポート表](./privileges/) | データベース権限とテーブル権限の一覧 | | [TRANSACTION機能サポート表](./rdb/) | TRANSACTIONテーブルのサポートSQL機能と制約 | | [バージョンと互換性](./compatibility-version/) | アップグレード時の注意事項、対応OS/プラットフォーム | | [サーバーとSDKの互換性](./compatibility-xma-protocol/) | サーバーとSDKのバージョンの組み合わせ別のサポート範囲 | | [LOOKUP SQL/JSONサポート表](./lookup-sql-json/) | LOOKUPテーブルのSQL/JSONサポート状況と制約 | | [TAGデータUPDATEサポート表](./tag-data-update/) | TAG UPDATEの条件と対象列のサポート状況 | サポート表にない内部オブジェクト・フラグ・プロトコルの動作に依存しないでください。 SDKの機能はサーバーとクライアントのバージョンを併せて確認します。機能別のエラー診断は [トラブルシューティング](/ja/dbms/troubleshooting/)を参照してください。 ## 表記規則 このセクションのサポート表では、次の記号を使用します。 | 記号 | 意味 | |:----:|------| | O | 完全にサポート | | X | 非対応 | | △ | 一部をサポート、または制約あり | --- title: "16.6.1 Edition別機能サポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/edition/ language: ja kind: page --- # 16.6.1 Edition別機能サポート表 Machbaseは、単一サーバー向けの**Standard Edition**と、複数ノードで水平スケーリングする **Cluster Edition**を提供します。基本的な時系列機能は共通ですが、拡張性と高可用性の要件に応じて サポート範囲が異なります。 ## Edition別の機能比較 | 機能 | Standard | Cluster | 備考 | |------|:--------:|:-------:|------| | **テーブルタイプ** | | | | | TAGテーブル | O | O | | | LOGテーブル | O | O | | | LOOKUPテーブル | O | O | | | TRANSACTIONテーブル | O | X | Cluster Editionでは非対応 | | VOLATILEテーブル | O | O | メモリ上のデータのノード・再起動に伴うライフサイクルはデプロイ構成で確認 | | **データ管理** | | | | | ROLLUP(基本) | O | O | | | Custom ROLLUP | O | X | Cluster Editionでは非対応 | | ROLLUP_REBUILD | O | X | Cluster Editionでは非対応 | | **バックアップと復旧** | | | | | 複数の論理データベース | O | X | Standard Edition専用。DBごとのCPU・メモリ・ディスクの物理クォータは提供しない | | BACKUP DATABASE | O | O | | | BACKUP TABLE | O | O | | | MOUNT DATABASE | O | X | Cluster Editionでは非対応 | | UMOUNT DATABASE | O | X | Cluster Editionでは非対応 | | machadmin -rによる復元 | O | X | Cluster Editionでは非対応 | | **拡張性とHA** | | | | | 水平スケーリング | X | O | Warehouseノードの追加で拡張 | | HA(高可用性) | X | O | Broker/Warehouseの冗長化 | | AUTH KEY認証 | O | O | | ## Cluster Editionの制約の概要 Cluster Editionには、単一ノードを中心とするローカルファイル操作とTRANSACTION機能に制約があります。 - **TRANSACTIONテーブル**: 分散環境でACIDトランザクションを保証するTRANSACTIONテーブルは非対応です。トランザクションが必要なデータは外部RDBMSと連携してください。 - **VOLATILEテーブル**: 作成・DMLはサポートしますが、メモリ上のデータはノードローカルで、ノード間では共有しません。接続先Broker・ルーティングとノード再起動によるデータの範囲を検証してください。 - **MOUNT/UMOUNT**: ローカルファイルシステムのバックアップのマウントは、分散環境では非対応です。 - **Custom ROLLUP / ROLLUP_REBUILD**: 分散集計の構造が異なるため、カスタムロールアップの再定義と再構築は非対応です。 ## Editionの選択基準 | 要件 | 推奨Edition | |-----------|-------------| | 単一サーバーのスループットと保存容量で運用できるワークロード | Standard Edition | | 単一サーバーを超える水平スケーリングが必要なワークロード | Cluster Edition | | 高可用性(障害からの自動復旧)が必要 | Cluster Edition | | TRANSACTIONテーブルまたはMOUNT機能が必要 | Standard Edition | | リアルタイムの収集量が単一サーバーの容量を超え、ノードの追加が必要 | Cluster Edition | --- title: "16.6.2 テーブルタイプ別機能サポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/table-types-type/ language: ja kind: page --- # 16.6.2 テーブルタイプ別機能サポート表 Machbaseは用途に応じて5種類のテーブルタイプを提供します。設計目的により、各タイプのサポート範囲は異なります。 ## テーブルタイプの概要 | テーブルタイプ | 主な用途 | |------------|----------| | **TAG** | 時系列センサーデータの高速収集と集計(ROLLUP) | | **LOG** | ログ・イベントを定義済み列へ順次保存、テキスト検索 | | **LOOKUP** | メタデータ、コードテーブル、参照データ(UPDATE/DELETE対応) | | **VOLATILE** | メモリ上のサーバー状態・キャッシュ。再起動時にデータ消失 | | **TRANSACTION** | トランザクションが必要な一般的なリレーショナルデータ | ## テーブルタイプ別機能サポート一覧 | 機能 | TAG | LOG | LOOKUP | VOLATILE | TRANSACTION | |------|:---:|:---:|:------:|:--------:|:---:| | **書き込み** | | | | | | | INSERT (SQL) | O | O | O | O | O | | **更新/削除** | | | | | | | UPDATE | △ | X | O | O | O | | DELETE | O | O | O | O | O | | **トランザクション** | | | | | | | Transaction (COMMIT/ROLLBACK) | X | X | X | X | O | | **集計と検索** | | | | | | | ROLLUP | O | X | X | X | X | | テキスト検索 (KEYWORD INDEX) | X | O | X | X | X | | **JSON** | | | | | | | JSON 列 | O | O | O | X | O | | JSON path query | O | O | O | X | O | | **固定小数点** | | | | | | | DECIMAL / NUMERIC 列 | O | O | O | O | O | | **固定長ARRAY** | | | | | | | ARRAY列の作成 | O | O | O | O | O | | ARRAY ADD/DROP COLUMN | △ | O | O | O | O | | **インデックス** | | | | | | | 基本インデックス | O | O | O | O | O | | LSM インデックス | X | O | X | X | X | | **参照** | | | | | | | SELECT | O | O | O | O | O | | 最新値の参照(`SCAN_BACKWARD`, TAG stat) | O | X | X | X | X | | JOIN (他のテーブルと) | △ | △ | O | O | O | | Subquery | O | O | O | O | O | | VIEW | O | O | O | O | O | > 記号: O = サポート、X = 非対応、△ = 一部をサポート、または制約あり AppendがサポートするテーブルタイプはクライアントAPIによって異なります。使用する言語とAPIの サポート範囲は[SDK Appendサポート表](/ja/dbms/development-tools-integration/sdk-support-scope/#append-table-type-matrix)を 確認してください。 DECIMALは5種類すべてのテーブルタイプで使用できる正確な固定小数点型です。 `NUMERIC`、`DEC`、`FIXED`、`NUMBER`はDECIMALの別名です。精度(precision)は最大65桁、 小数部の桁数(scale)は最大30桁です。詳細は [DECIMALとNUMERIC固定小数点型](../../sql/types/decimal-numeric-fixed-point/)を参照してください。 ARRAY ADD/DROPはStandard EditionのLOG、VOLATILE、LOOKUP、TRANSACTION、TAG METADATAで サポートします。表のTAG列の`△`は、ALTERでTAG DATAの通常列は追加できず、TAG METADATAのみ サポートすることを示します。Cluster EditionではLOG経路のみをサポートします。正確な構文と 既存行へのDEFAULT規則は[DDL構文](../../sql/syntax/ddl-syntax/#add-column)と [数値ARRAY型](../../sql/types/array/)を参照してください。 ## 主な制約の詳細 ### TAGテーブルのUPDATE制約 (△, Standard Edition) TAGテーブルのUPDATEは、次のすべての条件を満たす必要があります。 Cluster EditionではTAGデータUPDATEは使用できません。 - `WHERE`句にタグ選択条件(`name =`、`name IN`、`name LIKE`)を含める - `WHERE`句にBASETIME列の条件を含める - SET対象は実際のデータ列 - `time`(BASETIME)列、`name`列、メタデータ列はデータUPDATEで変更不可 - SETの右辺では既存行の列を参照できず、定数・バインド・列を含まない式のみ使用可能 ```sql -- 可能: タグ条件と時刻条件でデータ列を更新 UPDATE sensor_data SET value = 101 WHERE name = 'sensor01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); -- 不可: BASETIME列を更新 UPDATE sensor_data SET time = SYSDATE WHERE name = 'sensor01' AND time >= TO_DATE('2026-07-01', 'YYYY-MM-DD'); ``` 詳細は[TAGデータUPDATEサポート表](../tag-data-update/)を参照してください。 ### LOOKUPとVOLATILEのトランザクション範囲 LOOKUPとVOLATILEテーブルの各DMLは文単位で反映されます。複数のDMLを`BEGIN`と `COMMIT`/`ROLLBACK`でまとめるTRANSACTIONテーブルのトランザクションには参加しません。 ### JSON列のサポート範囲 JSON列はTAG、LOG、LOOKUP、TRANSACTIONテーブルでサポートします。VOLATILEではJSON型列を作成できません。LOOKUPのJSON列は通常の列として使用できますが、主キーには使用できません。詳細は[JSON型のテーブルタイプ別サポート範囲](../../sql/types/table-types-type-support-scope-json/)を参照してください。 ## TAGテーブルの最新値と 時間範囲の参照 TAGテーブルは、逆方向スキャンと時刻条件で最新値と時間範囲を参照します。 ```sql -- 特定タグの最新5件の値を参照 SELECT /*+ SCAN_BACKWARD(sensor_data) */ * FROM sensor_data WHERE name = 'sensor01' LIMIT 5; -- 時間範囲の参照 SELECT * FROM sensor_data WHERE name = 'sensor01' AND time BETWEEN TO_DATE('2024-01-01') AND TO_DATE('2024-01-02'); ``` --- title: "16.6.3 TRANSACTION機能サポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/rdb/ language: ja kind: page --- # 16.6.3 TRANSACTION機能サポート表 MachbaseのTRANSACTIONテーブルは、トランザクションが必要な一般的なリレーショナルデータを保存します。 Machbase SQLとJDBC/ODBCなどの対応ドライバーでアクセスします。 > **注意**: TRANSACTIONテーブルは**Standard Editionでのみサポート**します。Cluster Editionでは作成・使用できません。 修飾のない`CREATE TABLE`、`CREATE TRANSACTION TABLE`、`CREATE TXN TABLE`はすべてTRANSACTION テーブルを作成します。このためCluster Editionでは3つの構文がすべて拒否されます。 Cluster EditionでLOGテーブルを作成する場合は`CREATE LOG TABLE`を使用します。 ## SQL機能のサポート可否 | 機能 | サポート | 備考 | |------|:---------:|------| | **基本DML** | | | | SELECT | O | | | INSERT | O | | | UPDATE | O | | | DELETE | O | | | INSERT ... ON DUPLICATE KEY UPDATE | O | PRIMARY KEY・UNIQUE INDEXの競合時に既存行を更新 | | **トランザクション** | | | | Transaction (COMMIT/ROLLBACK) | O | 単独の`BEGIN`、`COMMIT`、`ROLLBACK` | | TRANSACTION TRUNCATEのROLLBACK | O | 明示的トランザクション内の全行削除として処理 | | Savepoint | X | 非対応 | | **クエリ機能** | | | | Prepared Statement | O | | | パラメーターバインド | O | | | JOIN | O | 他のテーブルタイプとの結合が可能 | | Subquery | O | | | VIEW | O | | | **オブジェクト** | | | | SEQUENCE | O | `CREATE SEQUENCE` | | PRIMARY KEY / UNIQUE INDEX | O | 単一列のPRIMARY KEYと単一・複合列のUNIQUE INDEX | | セカンダリINDEX | O | 単一・複合列のBTREEインデックス | | JSON path INDEX | O | `json_column->'$.path'` | | AUTO_INCREMENT | O | `LONG`/`INT64`列単位のPRIMARY KEY | | ALTER ADD/DROP COLUMN | O | 列定義に括弧を使用 | | ALTER RENAME COLUMN / RENAME TO | O | 列名・テーブル名の変更 | | ALTER MODIFY COLUMN | X | 非対応 | | Trigger | X | 非対応 | | Stored Procedure | X | 非対応 | | Foreign Key | X | 非対応 | `AUTO_INCREMENT`の使用方法は[AUTO_INCREMENT](/ja/dbms/reference/sql/syntax/auto-increment-syntax/)を、 upsertは[INSERT ON DUPLICATE KEY UPDATE](/ja/dbms/rdb-table-usage/insert-on-duplicate-key-update/)を参照してください。 Appendはクライアント別に経路が異なるため、[SDK Append matrix](/ja/dbms/development-tools-integration/sdk-support-scope/#append-table-type-matrix)を 正式な参照先とします。 ## トランザクションと同時アクセスの境界 アクティブなトランザクションでも、他のテーブルタイプのSELECTと、タイプが混在するJOINを許可します。 ただし、LOG・TAG・LOOKUP・VOLATILEへの書き込みを同じTRANSACTIONトランザクションに含めることはできません。 許可されたクエリも、全タイプに共通のスナップショット時点を保証するものではありません。 一般的な制約エラーでは、失敗した文とトランザクション全体を区別します。先に成功した変更を取り消すには ROLLBACKが必要です。ロールバック専用状態では後続処理を続けず、終了してください。 開いているTRANSACTIONカーソルはCOMMIT・ROLLBACKを妨げる場合があります。 現在、複数のTRANSACTIONテーブルのコミットは、テーブルごとのストレージハンドルに順次適用されます。 通常の複数テーブルCOMMIT・ROLLBACKのサポートは、コミット中の障害を含めた複数テーブルの原子性保証とは 異なります。エラーや応答消失の後は、業務キーで反映状態を確認してください。 WALの古い読み取りスナップショットを書き込みに切り替える際の競合は、 TRANSACTION_BUSY_TIMEOUT_MS=-1でも待機では解消しません。 [トランザクション演習](../../../rdb-table-usage/transaction/)と [2つの接続による競合演習](../../../rdb-table-usage/locking-conflict-timeout/)を参照してください。 ## 関連ドキュメント - [TRANSACTIONテーブルの利用](../../../rdb-table-usage/) - [TRANSACTIONのDDLとDML](../../sql/syntax/) - [SDK機能のサポート範囲](../../../development-tools-integration/sdk-support-scope/) --- title: "16.6.4 TAGデータUPDATEサポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/tag-data-update/ language: ja kind: page --- # 16.6.4 TAGデータUPDATEサポート表 TAGテーブルの実際の時系列データは、`UPDATE table_name SET ... WHERE ...`で更新できます。 このページではTAGデータUPDATEで許可するWHERE条件とSET対象をまとめます。 メタデータの更新には別の`UPDATE ... METADATA`構文を使用します。 Machbase 8.7.0以降でサポート TAGデータUPDATEは、Standard Editionの論理TAGテーブルでのみサポートします。 Cluster Editionと内部のrawコンポーネントテーブルへの直接UPDATEはサポートしません。 ## WHERE条件別のサポート状況 TAGデータUPDATEには、1つのタグ選択条件と1つ以上のBASETIME軸条件が必要です。 | WHERE条件 | サポート | 備考 | |-----------|:---:|------| | `name = 'tag-01'` | O | 単一タグを選択 | | `name = ?`, `name = :tag_name` | O | 位置指定/名前付きバインドで単一タグを選択 | | `? = name`, `:tag_name = name` | O | 左右を逆にした等値条件もサポート。列を左辺に置く形式を推奨 | | `name IN ('tag-01', 'tag-02')` | O | リテラル/バインド値のリストをサポート。サブクエリの`IN`は非対応 | | `name LIKE 'tag-%'` | O | パターンに一致するタグを対象に展開 | | `time = t1` | O | BASETIME列の等値条件 | | `time = ?`, `time = :base_time` | O | 位置指定/名前付きバインドで基準時刻を指定 | | `? = time`, `:base_time = time` | O | 左右を逆にした等値条件をサポート | | `time BETWEEN t1 AND t2` | O | 両端を含む | | `time >= t1 AND time < t2` | O | `>`、`>=`、`<`、`<=`の組み合わせをサポート | | `time >= ? AND time < ?` | O | 範囲の境界値にもバインドマーカーを使用可能 | | 片側のみの時刻条件 | O | 例: `time >= t1` | | データ列の述語 | O | 例: `value > 100`。タグ/時刻条件と併用 | | 条件のないUPDATE | X | TAGデータ全体のUPDATEは不可 | | タグ選択のない時刻条件のみ | X | 対象タグの指定が必要 | | 時刻条件のないタグ条件のみ | X | BASETIME範囲の指定が必要 | | `OR`条件 | X | TAGデータUPDATE条件では不可 | | サブクエリ/集約式 | X | UPDATE対象の決定条件には使用不可 | | タグ/軸列を関数・演算式で囲む式 | X | タグ選択とBASETIME条件では該当列を直接指定する必要がある | バインドパラメーターは値のみを置き換えます。必須のタグ選択・BASETIME条件、許容する条件構造、 SET対象は変わりません。プリペアドステートメントを再実行すると最新のバインド値で対象を選び直し、 一致する行がなければ影響行数`0`で成功します。 ## SET対象列別のサポート状況 | SET対象 | サポート | 備考 | |---------|:---:|------| | データ列 | O | `value`や補助列などのユーザーデータ列 | | `SUMMARIZED`データ列 | O | 元のTAGデータを更新 | | 複数のデータ列 | O | 同じUPDATE文でまとめて指定可能 | | `name` (PRIMARY KEY) | X | タグ名は変更不可 | | `time` (BASETIME) | X | 時間軸列は変更不可 | | メタデータ列 | X | `UPDATE table_name METADATA SET ...`を使用 | | 隠し/システム列 | X | 内部列はUPDATE対象外 | SET式には、定数、バインド変数、既存行の列を参照しない算術式・関数・`CASE`式・文字列連結、 列制約が許容する場合はNULL値を使用できます。SETの右辺で既存行の列を参照することはできず、 サブクエリと集約式も使用できません。 ## 正式な参照先 実行構文とパラメーターのメタデータは[TAGデータUPDATE](../../sql/syntax/dml-syntax/tag-data-update-syntax/#tag-data-update-predicate-bind)を、 SDK別のマーカーAPIは[Named Bind Parameter](../../sql/syntax/named-bind-parameter-syntax/)を、 診断は[TAGの制約とトラブルシューティング](../../../tag-table-usage/constraints-errors-troubleshooting/)を参照してください。 --- title: "16.6.5 LOOKUP SQL/JSONサポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/lookup-sql-json/ language: ja kind: page --- # 16.6.5 LOOKUP SQL/JSONサポート表 このページでは、LOOKUPテーブルのSQL機能とJSON関連の制約をまとめます。 ## サポート状況 | 機能 | サポート | 備考 | |------|:---:|------| | **基本CRUD** | | | | INSERT | O | 通常のINSERTを使用 | | SELECT | O | 主キー(PK)条件と一般の検索条件の両方を使用可能 | | UPDATE(PK条件) | O | 主キーの高速アクセスパスを使用 | | DELETE(PK条件) | O | 主キーの高速アクセスパスを使用 | | UPDATE(一般の検索条件) | O | 条件に一致する主キー集合を収集してから更新 | | DELETE(一般の検索条件) | O | 条件に一致する主キー集合を収集してから削除 | | **JSON機能** | | | | JSON型列 | O | 通常の列として作成、保存、参照、更新が可能 | | JSON path query (`$.key`) | O | `->`、`JSON_EXTRACT_*`、`JSON_TYPEOF`、`JSON_IS_VALID`を使用可能 | | JSON PK | X | JSON列は主キーとして宣言不可 | | JSON path index | X | 個別のJSONパスインデックスは非対応 | | **その他** | | | | 明示的トランザクション(`BEGIN`/`COMMIT`/`ROLLBACK`) | X | DMLは文単位で反映され、複数の文をまとめてロールバックすることは不可 | | Prepared Statement | O | 主キー条件と一般の検索条件でパラメーターバインドをサポート | | Append API | △ | 通常のSQL INSERTが基本。AppendはLOOKUP固有のAppendポリシーに従う | ## 正式な参照先 LOOKUPのJSONスキーマと実行例は[JSON列とクエリ](../../../lookup-table-usage/json-column-query/)を、 UPDATE・DELETE構文は[DML構文](../../sql/syntax/dml-syntax/)を参照してください。 --- title: "16.6.6 ROLLUPのサポート範囲" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/rollup/ language: ja kind: page --- # 16.6.6 ROLLUPのサポート範囲 ## Editionとテーブルの範囲 | 機能 | Standard | Cluster | |---|:---:|:---:| | 時間軸TAGの通常・条件付き・拡張ROLLUPの作成・参照・制御 | O | O | | WITH ROLLUPによる自動作成 | O | O | | 対応するJSONパス・ドキュメント全体の集計 | O | O | | Custom INTO...AS | O | X | | ROLLUP_REBUILD | 限定された対象・引数でサポート | X | 距離軸TAG、LOG、TRANSACTION、VOLATILE、LOOKUPには時間軸ROLLUPを適用しません。 Clusterの状態は、関連するノードと階層ごとに確認します。 ## 作成タイプと列 | タイプ | 必要な条件 | |---|---| | 通常の数値 | 対応する数値DATA列。明示的に作成する場合はSUMMARIZEDは必須ではない | | JSONパス | JSON DATA列と集計対象の数値パス | | JSONドキュメント全体 | JSON SUMMARIZED列 | | WITH ROLLUP | 時間軸TAGの3番目のSUMMARIZED列 | | FROM階層 | より大きな整数倍の間隔と、同一の拡張・モード条件 | | Custom | ソースとなる時間軸TAGが1つ、事前作成した互換性のある出力先TAG | ## 集計と選択 通常の数値ROLLUPはMIN/MAX/SUM/COUNT/AVG/SUMSQを提供し、拡張ROLLUPはFIRST/LASTも提供します。 Customの部分結果はユーザーが再集計します。平均は合計と有効件数を使い、FIRST/LASTは対応する時刻を 保持して統合します。JSONドキュメント全体のCOUNTは保存された集計件数であり、元のCOUNT(value)と 常に一致するわけではありません。 候補の選択は条件・列・パス・モード・間隔に依存します。通常/拡張だけで優先順位を断定したり、 日単位のバケットに24 HOUR ROLLUPが自動適用されると仮定したりしないでください。 [クエリ規則](../../../tag-rollup-usage/query-syntax-rollup/)を確認してください。 ## REBUILDと作成のサポート範囲の違い REBUILDの対象は、完全な自動SEC/MIN/HOUR階層と、対応するCustom経路です。任意の手動名、 一部のみの自動階層、10 MIN Customなど、作成可能なすべての構成を再構築できるわけではありません。 現在のCustomの時間境界処理間隔は1 SEC・1 MIN・1 HOURであり、SELECTのバケットにも一致する必要があります。 定数の時刻引数、バケット全体への拡張、状態遷移、エラー後の確認は [REBUILDリファレンス](../../sql/syntax/rollup-rebuild-syntax/)に従います。 ## 権限 作業用アカウントに、対象データベースへの接続と作成・削除・参照などの必要な権限を付与します。 次は既存の作業用アカウントに作成・削除権限を付与する例であり、必要な権限をすべて一括設定する スクリプトではありません。 ```sql GRANT CREATE, DROP ON DATABASE MACHBASEDB TO rollup_user; ``` [権限管理](../../../security-access-control/privileges/)で所有者と作業範囲を確認してください。 --- title: "16.6.7 権限別機能サポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/privileges/ language: ja kind: page --- # 16.6.7 権限別機能サポート表 Machbaseの権限は、適用範囲に応じて**データベース権限**と**テーブル権限**に分かれます。 ## データベース権限 データベース権限は、指定したアクティブデータベースの範囲に適用します。`MOUNT`は `MACHBASEDB`に付与します。マウント済みデータベースへのアクセスには、`USAGE`と テーブルの`SELECT`権限を個別に付与します。 | 権限 | 許可する操作 | デフォルトで保有 | |------|-------------|:--------:| | `CONNECT` | アクティブデータベースへの接続、`USE`、オブジェクトの探索 | O(MACHBASEDB互換) | | `CREATE` | テーブル、ビュー、インデックス、ロールアップ、テーブルスペース、保持ポリシーの作成 | O | | `DROP` | テーブル、ビュー、インデックス、ロールアップ、テーブルスペース、保持ポリシーの削除 | O | | `ALTER` | テーブル構造の変更、`ALTER SYSTEM`の実行 | X | | `BACKUP` | `BACKUP DATABASE`の実行 | X | | `MOUNT` | `MOUNT DATABASE` / `UMOUNT DATABASE`の実行 | X | | `USAGE` | マウント済みデータベースの探索 | X | | `DDL` | CREATE + DROPの組み合わせ(複合権限) | — | | `ALL` | CONNECT、CREATE、DROP、ALTER、BACKUPを一括付与 | — | > 「デフォルトで保有 O」は、`CREATE USER`で作成したユーザーの`MACHBASEDB`に対する互換性維持用のデフォルト権限です。 > 他の論理データベースの権限は個別に付与します。 ## テーブル権限 テーブル権限は、特定テーブルに対するDML操作を制御します。 | 権限 | 許可する操作 | |------|-------------| | `SELECT` | 特定テーブルのSELECTによる参照 | | `INSERT` | 特定テーブルへのINSERT | | `DELETE` | 特定テーブルのDELETE | | `UPDATE` | 特定テーブルのUPDATE | ## GRANT / REVOKE構文 ```sql -- データベース権限を付与 GRANT CONNECT ON DATABASE factory_a TO app_user; GRANT CREATE ON DATABASE factory_a TO app_user; GRANT BACKUP ON DATABASE factory_a TO backup_user; GRANT ALL ON DATABASE factory_a TO admin_user; -- テーブル権限を付与 GRANT SELECT ON sys.sensor_data TO reader_user; GRANT INSERT ON sys.sensor_data TO writer_user; -- 権限を取り消す REVOKE SELECT ON sys.sensor_data FROM reader_user; REVOKE BACKUP ON DATABASE factory_a FROM backup_user; ``` ## 権限が必要な主な操作 | 操作 | 必要な権限の種類 | 必要な権限 | |------|-------------|---------| | `CREATE TABLE` | データベース | CREATE | | `DROP TABLE` | データベース | DROP | | `ALTER TABLE` | データベース | ALTER | | `BACKUP DATABASE` | データベース | BACKUP | | `MOUNT DATABASE` | データベース | MOUNT | | テーブルのSELECT | テーブル | SELECT | | テーブルのINSERT | テーブル | INSERT | | テーブルのUPDATE | テーブル | UPDATE | | テーブルのDELETE | テーブル | DELETE | ## 権限の状態確認 ```sql -- ユーザー一覧 SELECT user_name, user_id FROM m$sys_users; -- データベース権限を参照 SELECT * FROM m$sys_grant_databases WHERE grantee = 'APP_USER'; -- テーブル権限を参照 SELECT * FROM m$sys_grant_tables WHERE grantee = 'APP_USER'; ``` ## 詳細リファレンス 権限モデル全体の説明と例は、[権限管理](/ja/dbms/security-access-control/privileges/)を参照してください。 --- title: "16.6.8 バックアップ/マウントサポート表" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/backup-mount/ language: ja kind: page --- # 16.6.8 バックアップ/マウントサポート表 バックアップはデータをファイルに保存し、マウントは保存したバックアップファイルをデータベースに接続して参照する機能です。 ## Edition別のサポート可否 | 機能 | Standard | Cluster | 備考 | |------|:--------:|:-------:|------| | 複数の論理データベース | O | X | Standard Edition専用 | | BACKUP DATABASE | O | O | データベース全体のバックアップ | | BACKUP TABLE | O | O | 特定テーブルのみのバックアップ | | MOUNT DATABASE | O | X | Cluster Editionでは非対応 | | UMOUNT DATABASE | O | X | Cluster Editionでは非対応 | | machadmin -rによる復元 | O | X | Cluster Editionでは非対応 | `BACKUP DATABASE database_name INTO DISK`は、1つのアクティブな論理データベースをバックアップします。 複数のアクティブデータベースを含むインスタンス全体のイメージは、論理`MOUNT`/`RESTORE DATABASE`の 入力には使用できません。マウント済みデータベースの参照には`USAGE`とテーブルの`SELECT`権限が 必要です。`USE`と書き込みはサポートしません。 ## テーブルタイプ別のバックアップサポート | テーブルタイプ | BACKUPのサポート | MOUNT後の参照 | 備考 | |------------|:-----------:|:------------:|------| | TAGテーブル | O | O | | | LOGテーブル | O | O | | | LOOKUPテーブル | O | O | | | TRANSACTIONテーブル | O | O | | | VOLATILEテーブル | X | X | メモリ上のデータのためバックアップ不可 | ## 正式な参照先 - 構文: [BACKUP · RESTORE · MOUNT](../../sql/syntax/backup-restore-mount-syntax/) - 運用手順: [バックアップ、復元、マウント](../../../operations-configuration-recovery/backup-restore-mount/) --- title: "16.6.9 サーバーとSDKの互換性" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/compatibility-xma-protocol/ language: ja kind: page --- # 16.6.9 サーバーとSDKの互換性 MachbaseサーバーとSDKのバージョンが異なる場合、基本的な接続は可能でも、最新の認証、メタデータ、 名前付きバインドパラメーターの機能が制限される場合があります。この節では、サーバーとSDKの バージョンの組み合わせ別のサポート範囲とアップグレード順序を説明します。 ## サーバーとSDKのバージョン互換表 | サーバーバージョン | 8.5クライアントドライバー | 8.7.0クライアントドライバー | |-----------|:---------------------:|:---------------------:| | **8.7.0サーバー** | 限定的な互換性 | 完全互換 | | **8.5サーバー** | 完全互換 | 後方互換、8.7.0の名前指定APIは非対応 | - **完全互換**: 同じバージョンの組み合わせです。実際に使用できる機能はEdition、テーブルタイプ、SDKのサポート範囲によって異なり、その機能を含むビルドを使用する必要があります。 - **限定的な互換性**: 基本的な接続は可能ですが、AUTH KEYの拡張など8.7.0の新機能が動作しない場合があります。 - **後方互換**: 8.5サーバーの範囲内の機能のみ使用できます。 ## Machbase 8.7.0 SDKの主な変更点 ### AUTH KEY認証の拡張 8.7.0ではAUTH KEYのチャレンジ認証方式を拡張しました。 - 対応する署名方式: `ECDSA`、`RSA_PKCS1_V15`、`RSA_PSS` - 8.5以前のドライバーでは、新しい署名方式`RSA_PSS`をサポートしない場合があります。 - AUTH KEY認証を使用する場合は、ドライバーを8.7.0に更新してください。 ```text -- AUTH KEYを登録(サーバー) ALTER USER app_user ADD AUTH KEY ( KEY='-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n', VALID_BEFORE='2047-12-31' ); ``` ### 接続文字列の互換性 Machbase SQLCLIとODBCのAUTH KEY関連パラメーター: ```ini AUTH_MODE=CHALLENGE; AUTH_KEY_FILE=./private_key.pem; AUTH_SIG_SCHEME=ECDSA; ``` 8.5ドライバーでは`AUTH_SIG_SCHEME`パラメーターを無視する場合があります。 ### Nullableメタデータ 結果列がNULLを許容するか確認するAPIと、サーバー・SDKの組み合わせ別の制約は [Nullableメタデータのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-nullable-metadata)を 参照してください。互換性を確認するときは、サーバーとクライアントの両方のバージョンを記録します。 ### Named Bind Parameter 名前付きパラメーターをサーバーのプリペアドステートメントへ渡すか、位置順にバインドするか、 クライアントでSQL文字列へ変換するかはSDKによって異なります。 [SDK機能のサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/#support-scope-sdk-transaction-prepare-bind)で 使用するクライアントの動作を確認してください。 ### ARRAYと選択列Append 固定長の数値ARRAYと選択列AppendはMachbase DBMS 8.7.0でサポートします。DBMS 8.7.0サーバーと ARRAY機能を含むSDKビルドを併用してください。旧バージョンのサーバーや対応していないSDKは、 ARRAYのメタデータや値を従来のスカラー型で代用せず、該当リクエストをエラーとして処理します。 ARRAYのSQL要素位置とMachbase専用SDKのpositionは0始まりです。従来の1始まりのSQL、 疎なオブジェクト、添字付きAppendターゲットでは、各位置を1減らしてください。保存データと 密なARRAYの要素順序は変わりません。JDBCのパラメーター序数や`java.sql.Array`のスライスなど、 標準APIが定義する1始まりの位置は変更対象ではありません。 Cluster Editionでは、coordinator、broker、warehouseをすべてARRAYに対応した同じDBMS 8.7.0ビルドに そろえます。バージョンが混在する状態では、ARRAY DDLやARRAYデータを使用する操作を開始しないでください。 SQLとSDK別の要件は、[数値ARRAY型](/ja/dbms/reference/sql/types/array/)と [Sparse ARRAYと選択列Append API](/ja/dbms/development-tools-integration/data-input-load-export/array-append/)を参照してください。 ## SDKバージョンの確認 JDBC: ```java Connection conn = DriverManager.getConnection(url, props); DatabaseMetaData meta = conn.getMetaData(); System.out.println("Driver: " + meta.getDriverVersion()); ``` Machbase SQLCLI: ```c SQLGetInfo(conn, SQL_DRIVER_VER, buf, sizeof(buf), NULL); ``` ODBC: ```c SQLGetInfo(conn, SQL_DRIVER_VER, buf, sizeof(buf), NULL); ``` ## アップグレードの推奨事項 1. サーバーとSDKを同じバージョン(8.7.0)へ一緒にアップグレードしてください。 2. SDKを段階的にアップグレードする場合、その期間中の8.5 SDKから8.7.0サーバーへの接続は限定的な互換性となります。 3. AUTH KEY認証を使用する場合は、最初にSDKをアップグレードしてください。 4. Nullableメタデータをアプリケーションのロジックで使用する場合は、サーバーとSDKの両方を8.7.0へアップグレードしてください。 5. Named Bind Parameterの名前指定SDK APIを使用する場合は、サーバーとSDKの両方を8.7.0へアップグレードしてください。 6. ARRAYまたは選択列Appendを使用する場合は、サーバーをMachbase DBMS 8.7.0に、クライアントを対応機能を含むSDKビルドにアップグレードしてください。Cluster Editionでは全ノードをそろえます。 --- title: "16.6.10 バージョンと互換性" url: https://docs.machbase.com/ja/dbms/reference/support-scope-constraints/compatibility-version/ language: ja kind: page --- # 16.6.10 バージョンと互換性 Machbase 8.7.0の後方互換性、アップグレード時の注意事項、対応OS/プラットフォームをまとめます。 ## 8.7.0の後方互換性 ### クライアントドライバーの互換性 | サーバーバージョン | 8.5クライアントドライバー | 8.7.0クライアントドライバー | |-----------|:---------------------:|:---------------------:| | 8.7.0サーバー | 限定的な互換性 | 完全互換 | | 8.5サーバー | 完全互換 | 後方互換 | - 8.7.0サーバーに8.5クライアントドライバーを使用すると、一部の新機能が動作しない場合があります。 - 旧バージョンのサーバーまたはドライバーの組み合わせでは、Nullableメタデータが従来の値や判定不能の値で返される場合があります。この値に依存するアプリケーションでは、サーバーとSDKの両方を8.7.0へアップグレードしてください。 - CASTのすべての変換先の型と長さ・精度オプションを使用するSQLは、8.7.0サーバーでサポートします。同じ要素数の数値ARRAY全体を`CAST(array_expression AS TYPE[N])`で変換する構文も、このバージョンから使用できます。Cluster Editionでは全ノードをCASTとARRAYに対応した同じバージョンにそろえてください。詳細な構文と変換規則は[CAST関数](/ja/dbms/reference/sql/functions/functions-full/#cast)を参照してください。 - 8.7.0サーバーは`CREATE INDEX IF NOT EXISTS`をサポートします。同じデータベースと所有者に同名のインデックスがある場合、既存の定義を維持して成功するため、繰り返しデプロイした後に実際のインデックスの対応関係を確認してください。旧サーバーではこの構文は使用できません。詳細は[INDEX構文](/ja/dbms/reference/sql/syntax/index-syntax/#create-index-if-not-exists)を参照してください。 - 8.7.0 Standard Editionサーバーでは、TAGデータUPDATEのNAMEとBASETIMEの条件値に位置指定または名前付きバインドパラメーターを使用できます。旧サーバーでは同じプリペアドUPDATEが`ERR-02190`で拒否される場合があります。条件の形式とSDK APIは[TAGデータUPDATEのバインド](/ja/dbms/reference/sql/syntax/dml-syntax/tag-data-update-syntax/#tag-data-update-predicate-bind)を参照してください。 - 8.7.0サーバーのBASE DISTANCE TAG統計ビューは、軸列を`*_DISTANCE`という名前と元の`DOUBLE`、`LONG`、`ULONG`型で提供します。従来の`*_TIME`名はエイリアスとして提供せず、既存テーブルもサーバー再起動後に新しいスキーマを使用します。BASE TIME TAGの`*_TIME DATETIME`スキーマは維持します。アプリケーションのSQLと結果マッピングは[TAG別統計ビュー](/ja/dbms/tag-table-usage/query-analysis/#tag-stat-axis-schema)の変換表に従って変更してください。 - 8.7.0 Standard EditionではSELECT/JOIN計画の改善により、テーブルのスキャン順序とソートしていない結果の返却順序が旧バージョンと異なる場合があります。結果の順序が必要な場合は`ORDER BY`を使用し、アップグレード後は[SELECT/JOINオプティマイザー](/ja/dbms/performance-tuning/performance-query-tuning/#select-join-optimizer)の手順に従って結果と実行計画を併せて確認してください。 - 8.7.0 JDBCドライバーは、複数ホストURLで接続段階のI/Oエラーが発生すると次のホストへの接続を試みます。旧ドライバーが最初のホストの一部のソケットエラーで接続を終了する環境では、8.7.0 JDBCドライバーに置き換え、[複数ホストへの接続](/ja/dbms/development-tools-integration/jdbc/#jdbc-multi-host)のURLとタイムアウト設定を確認してください。 - Machbase DBMS 8.7.0は、固定長の数値ARRAYと選択列Appendをサポートします。ARRAYを使用するアプリケーションはDBMS 8.7.0サーバーと対応機能を含むSDKビルドを併用し、Cluster Editionでは全ノードを一緒にアップグレードしてください。SQLとAPIの詳細は[数値ARRAY型](/ja/dbms/reference/sql/types/array/)と[Sparse ARRAYと選択列Append API](/ja/dbms/development-tools-integration/data-input-load-export/array-append/)を参照してください。 - ARRAY列は、Standard EditionのLOG、VOLATILE、LOOKUP、TRANSACTION、TAG METADATAとCluster EditionのLOGテーブルで`ADD COLUMN`と`DROP COLUMN`をサポートします。既存行へのDEFAULT適用のテーブル別の違いは[DDL構文](/ja/dbms/reference/sql/syntax/ddl-syntax/#add-column)を確認してください。 - ARRAYの公開の位置指定は0始まりです。初期の1始まりのARRAY SQL、疎なオブジェクト、添字付きAppendターゲットを使用するコードでは、各位置を1減らしてください。保存済みARRAYデータと密なARRAYの要素順序は変わらないため、データ移行は不要です。 - サーバーとSDKのバージョンの組み合わせによる機能差は、[サーバーとSDKの互換性](../compatibility-xma-protocol/)を参照してください。 ### 8.7.0で削除された機能 Machbase 8.7.0では、次の機能とインターフェースを提供しません。削除された設定、SQL、C APIには 互換レイヤーがないため、アップグレード前に設定ファイル、運用SQL、アプリケーションを変更してください。 | 8.5の機能またはインターフェース | 8.7.0の状態 | ユーザーへの影響 | 移行方法 | |--------------------------|------------|-------------|-----------| | DB HTTP/REST(`/machbase`、`/machiot`、ポート5657) | 削除 | 従来のHTTPクエリとAppendリクエストは使用不可 | SQLCLI、ODBC、JDBC、Python、Go、Node.js、.NET SDKを使用 | | WebAdmin/MWA、静的ClusterAdmin UI | 削除 | Web UIと関連する起動スクリプトは使用不可 | サーバー・クラスターのコマンドラインツールを使用 | | STREAM SQLとカタログ | 削除 | 登録済みSTREAMの実行と状態参照は不可 | Fluentdまたはアプリケーションのジョブで処理 | | Result Cache | 削除 | 結果キャッシュの設定、状態参照、フラッシュコマンドは使用不可 | インデックス・ROLLUP・クエリ最適化、またはアプリケーションキャッシュを使用 | | `machcli.h`と`MachCLI*()` | 削除 | 従来のC/C++ソースとバイナリはそのまま使用不可 | Machbase SQLCLIまたはODBCへ移行 | 次の機能は名前が似ていますが、引き続きサポートします。 | 維持する機能 | 説明 | |-----------|------| | Machbase SQLCLI | ``の`SQL*` API。ODBCとは別のAPI群です。 | | ODBC、JDBC、言語別SDK | Python、Go、Node.js、.NETを含む対応ドライバーは引き続き使用できます。 | | MachEngine API | 従来の`Mach*` APIを引き続き使用できます。 | | PVO Cache | 実行計画オブジェクトを再利用するキャッシュで、削除されたResult Cacheとは異なります。 | | Coordinator管理REST | データSQL RESTとは別の管理用APIです。Coordinatorの`/admin/`パスは引き続き使用できます。 | #### アップグレード前の設定ファイルの整理 次のプロパティが8.7.0の`machbase.conf`に残っていると、不明なプロパティとして扱われ、 サーバーが起動しません。バイナリを置き換える前にすべて削除してください。 ```text HTTP_AUTH HTTP_ENABLE HTTP_MAX_MEM HTTP_PORT_NO RS_CACHE_APPROXIMATE_RESULT_ENABLE RS_CACHE_ENABLE RS_CACHE_MAX_MEMORY_PER_QUERY RS_CACHE_MAX_MEMORY_SIZE RS_CACHE_MAX_RECORD_PER_QUERY RS_CACHE_TIME_BOUND_MSEC STREAM_THREAD_COUNT STREAM_WAIT_MS ``` 従来のSTREAM定義が必要な場合は、8.5サーバーを停止する前に`V$STREAMS`と関連SQLを別途記録します。 8.7.0では`SYS_STREAM_STMTS`、`V$STREAMS`、`V$HTTP_STATUS`、`V$RS_CACHE_LIST`、 `V$RS_CACHE_STAT`は登録されません。 アップグレード後、次の各クエリの結果が`0`であることを確認します。 ```sql SELECT COUNT(*) AS removed_property_count FROM V$PROPERTY WHERE NAME IN ( 'HTTP_AUTH', 'HTTP_ENABLE', 'HTTP_MAX_MEM', 'HTTP_PORT_NO', 'RS_CACHE_APPROXIMATE_RESULT_ENABLE', 'RS_CACHE_ENABLE', 'RS_CACHE_MAX_MEMORY_PER_QUERY', 'RS_CACHE_MAX_MEMORY_SIZE', 'RS_CACHE_MAX_RECORD_PER_QUERY', 'RS_CACHE_TIME_BOUND_MSEC', 'STREAM_THREAD_COUNT', 'STREAM_WAIT_MS' ); SELECT COUNT(*) AS removed_table_count FROM V$TABLES WHERE NAME IN ( 'SYS_STREAM_STMTS', 'V$HTTP_STATUS', 'V$RS_CACHE_LIST', 'V$RS_CACHE_STAT', 'V$STREAMS' ); ``` ### DDLの同時実行の互換性 Machbase 8.7.0では、EditionによってDDLの同時実行ポリシーが異なります。 | Edition | 8.7.0の動作 | `DDL_LOCK_TIMEOUT` | |---------|------------|--------------------| | Standard | 独立した異なるオブジェクトのDDLを同時に実行可能 | 提供。デフォルト値は`0`(NOWAIT) | | Cluster | 従来のカタログ範囲のDDLポリシーを維持 | 提供しない | Standard Editionで同じオブジェクトや直接関連するオブジェクトのDDLが競合すると、デフォルトでは `ERR-02031: Resource busy ()`が即座に返されます。旧バージョンの待機動作を前提とする デプロイスクリプトには、アップグレード後に次のいずれかを明示的に適用します。 - デプロイ用セッションで`ALTER SESSION SET DDL_LOCK_TIMEOUT = seconds`を使用して待機時間に上限を設定します。 - `ERR-02031`に限り、回数を制限した再試行と待機間隔を適用します。 - 再試行前にオブジェクトの状態を確認し、`already exists`、権限エラー、構文エラーは再試行しません。 競合関係と設定方法の詳細は、[DDLの同時実行とロック](/ja/dbms/reference/sql/syntax/ddl-syntax/#ddl-concurrency)を参照してください。 ### バックアップファイルの互換性 | バックアップのバージョン | 8.7.0での復元 | 備考 | |--------------|:-----------:|------| | 8.5バックアップ | O | `MOUNT`または`machadmin -r`を使用 | | 8.7.0バックアップ | O | | | 8.4以前のバックアップ | △ | バージョンによって異なるためテストが必要 | ## 正式なアップグレード手順 実行順序、対応プラットフォーム、事前確認は[アップグレード](../../../installation-deployment-upgrade/upgrade/)を参照してください。 このページではSQL・サーバー・クライアントの互換性に関する事実のみを管理します。 --- title: "16.7 エラーコード辞典" url: https://docs.machbase.com/ja/dbms/reference/error-codes/ language: ja kind: page --- # 16.7 エラーコード辞典 Machbaseのエラーは、machsql、ドライバーの例外メッセージ、サーバーのトレースログに表示されます。 このページではMachbase 8.7.0の代表的なエラーと、すべてのエラーメッセージを示します。 エラーメッセージは、実行経路に応じて`ERR-02010: ...`形式の文字列、またはドライバー固有の例外として 返されます。メッセージの文言は製品の改善に伴って変わる場合があるため、アプリケーションでは メッセージ文字列ではなくエラーコードを基準に処理します。 ## SQLパーサーと関数のエラー | コード | メッセージ | 主な原因 | |------|--------|-----------| | `ERR-02009` | `Insufficient parser memory.` | SQLパーサーのメモリ不足 | | `ERR-02010` | `Syntax error: near token (%s).` | SQL構文エラー | | `ERR-02011` | `Unrecognized token (%s).` | 認識できないトークンを使用 | | `ERR-02034` | `Invalid format of time expression.` | 時刻式の形式エラー | | `ERR-02035` | `Function [%s] does not exist.` | 存在しない関数の呼び出し | | `ERR-02036` | `Function [%s] has an invalid argument.` | 関数の引数の数または値のエラー | | `ERR-02037` | `Function [%s] argument data type does not match.` | 関数の引数の型が不一致 | | `ERR-02040` | `Invalid time range.` | 許容されない時間範囲 | ## テーブル、列、入力データのエラー | コード | メッセージ | 主な原因 | |------|--------|-----------| | `ERR-02014` | `Column name is duplicated: (%s).` | 重複する列名を使用 | | `ERR-02015` | `Invalid column type: (%s).` | 非対応の列型を指定 | | `ERR-02024` | `Table %s already exists.` | 同名のテーブルがすでに存在 | | `ERR-02025` | `Table %s does not exist.` | 対象テーブルが存在しない | | `ERR-02026` | `The number of insert values and that of columns are mismatched.` | INSERTの列数と値の数が不一致 | | `ERR-02030` | `Column name (%s) does not exist.` | 存在しない列を指定 | ## システムリソースのエラー | コード | メッセージ | 主な原因 | |------|--------|-----------| | `ERR-01007` | `There is no available disk space for writing <%lld>bytes to the file<%s>, errno = %d.` | データファイルを書き込むディスク領域の不足 | | `ERR-01346` | `Current Allocate Memory / PROCESS_MAX_SIZE (%llu/%llu), increase PROCESS_MAX_SIZE property and restart.` | `PROCESS_MAX_SIZE`の上限超過 | ## 全一覧の使用方法 以下の全一覧には、製品のエラーカタログの英語メッセージを表示します。`KEY`はソースコード内で エラーを区別する識別子です。`%s`、`%d`、`%llu`などのプレースホルダーは、エラー発生時に オブジェクト名や数値などの実際の値に置き換わります。メッセージを照合するときはこの違いを考慮し、 可能な場合は`ERR-xxxxx`コードで検索してください。 一覧はこのページ内で1,000番単位の範囲に分かれています。ブラウザーの検索機能でエラーコード、 エラー識別子、メッセージの一部を検索できます。メッセージだけで原因や再試行の可否を判断できない場合は、 [トラブルシューティング](/ja/dbms/troubleshooting/)と該当機能のドキュメントの制約も確認してください。 ## 全エラーメッセージ 以下の 1,062 件は、Machbase 8.7.0 NFX エラーカタログから、削除された機能の項目を除いた一覧です。 ### `ERR-00000`–`ERR-00999` (157) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-00001 | ERR_FILE_CREATE | Failed to create file<%s>, errno = %d. | | ERR-00002 | ERR_FILE_TRUNCATE | Failed to truncate file<%s>, errno = %d. | | ERR-00003 | ERR_FILE_DUP | Failed to duplicate file<%s>, errno = %d. | | ERR-00004 | ERR_FILE_COPY | Failed to copy file<%s> to file<%s>, errno = %d. | | ERR-00005 | ERR_FILE_RENAME | Failed to rename file<%s> to file<%s>, errno = %d. | | ERR-00006 | ERR_FILE_REMOVE | Failed to remove file<%s>, errno = %d. | | ERR-00007 | ERR_FILE_GETKEY | Failed to get key file<%s>, errno = %d. | | ERR-00008 | ERR_FILE_PIPE | Failed to create pipe<%s>, errno = %d. | | ERR-00009 | ERR_FILE_STAT | Failed to stat file<%s>, errno = %d. | | ERR-00010 | ERR_FILE_OPEN | Failed to open file<%s>, errno = %d. | | ERR-00011 | ERR_FILE_CLOSE | Failed to close file<%s>, errno = %d. | | ERR-00012 | ERR_FILE_SEEK | Failed to seek file<%s>, offset:%lld, Whence:%d, errno = %d. | | ERR-00013 | ERR_FILE_READ | Failed to read file<%s>, size:%llu, errno = %d. | | ERR-00014 | ERR_FILE_WRITE | Failed to write file<%s>, size:%llu, errno = %d. | | ERR-00015 | ERR_FILE_READ_SIZE | Failed to read file<%s> (offset:%llu, req size:%llu, read size: %llu), errno = %d. | | ERR-00016 | ERR_FILE_WRITE_SIZE | Failed to write file<%s> (offset:%llu, req size:%llu, read size: %llu), errno = %d. | | ERR-00017 | ERR_FILE_SYNC | Failed to sync file<%s>, errno = %d. | | ERR-00018 | ERR_FILE_LOCK | Failed to lock file<%s>, errno = %d. | | ERR-00019 | ERR_FILE_TRYLOCK | Failed to trylock file<%s>, errno = %d. | | ERR-00020 | ERR_FILE_UNLOCK | Failed to unlock file<%s>, errno = %d. | | ERR-00021 | ERR_FILE_NO_EXTENSION | There is no file extension. | | ERR-00022 | ERR_FILE_RENAME_RETRY | Failed to rename file<%s> to file<%s>, retry count<%d>, msec<%d>, errno = %d. | | ERR-00031 | ERR_STRING_SNPRINTF | Error occurred during snprintf: buffer size<%d>, errno = %d. | | ERR-00061 | ERR_ENV_GET | Failed to getenv variable<%s>, errno = %d. | | ERR-00062 | ERR_ENV_SET | Failed to setenv variable<%s> to value<%s>, errno = %d. | | ERR-00067 | ERR_DIR_OPEN | Failed to opendir <%s>, errno = %d. | | ERR-00068 | ERR_DIR_CLOSE | Failed to closedir, errno = %d. | | ERR-00069 | ERR_DIR_READ | Failed to readdir, errno = %d. | | ERR-00070 | ERR_DIR_REWIND | Failed to rewinddir, errno = %d. | | ERR-00071 | ERR_DIR_MAKE | Failed to makedir <%s>, errno = %d. | | ERR-00072 | ERR_DIR_REMOVE | Failed to removedir, errno = %d. | | ERR-00073 | ERR_DIR_SETCWD | Failed to setcwd, errno = %d. | | ERR-00074 | ERR_DIR_GETCWD | Failed to getcwd, errno = %d. | | ERR-00075 | ERR_DIR_GETHOME | Failed to gethome, errno = %d. | | ERR-00076 | ERR_DIR_PATH_TOO_LONG1 | Path<%s> is too long, errno = %d. | | ERR-00077 | ERR_DIR_PATH_TOO_LONG2 | Path<%s/%s> is too long, errno = %d. | | ERR-00078 | ERR_DIR_PATH_TOO_LONG3 | Path<%s/%s/%s> is too long, errno = %d. | | ERR-00079 | ERR_DIR_NOT_EXIST | The directory does not exist in this path<%s>, errno = %d. | | ERR-00080 | ERR_DIR_REMOVE_WITH_INFO | Failed to call removedir (%s), errno = %d. | | ERR-00091 | ULL_ERR_PMD_SQLITE3_ERROR | %1$s failed: [%2$d: %3$s]. | | ERR-00092 | ULL_ERR_PMD_SQLITE3_DISK_FULL | %1$s failed because the metadata store is full: [%2$d: %3$s]. | | ERR-00121 | ERR_STACK_CREATE | Stack create failed, errno = %d. | | ERR-00122 | ERR_STACK_PUSH | Stack push failed, errno = %d. | | ERR-00123 | ERR_STACK_POP | Stack pop failed, errno = %d. | | ERR-00131 | ERR_MEMORY_ALLOC | Failed to allocate memory(%lu bytes), errno = %d. | | ERR-00132 | ERR_MEMORY_ALLOC_BOUND | Memory allocation error (alloc'd: %llu, max: %llu). | | ERR-00133 | ERR_PM_PROCESS_MEMORY_LIMIT | Failed to allocate memory (ID = %d) (Request Size = %llu) : (Current Allocated Size / PROCESS_MAX_SIZE (%llu/%llu)). | | ERR-00141 | ERR_MEMPOOL_CREATE | Failed to create memory pool, errno = %d. | | ERR-00142 | ERR_MEMPOOL_ALLOC | Failed to allocate memory from memory pool, errno = %d. | | ERR-00151 | ERR_MUTEX_CREATE | Failed to create mutex, errno = %d. | | ERR-00152 | ERR_MUTEX_DESTROY | Failed to destroy mutex, errno = %d. | | ERR-00153 | ERR_MUTEX_LOCK | Failed to lock mutex, errno = %d. | | ERR-00154 | ERR_MUTEX_TRYLOCK | Failed to trylock mutex, errno = %d. | | ERR-00155 | ERR_MUTEX_UNLOCK | Failed to unlock mutex, errno = %d. | | ERR-00161 | ERR_QUEUE_CREATE | Failed to create queue, errno = %d. | | ERR-00162 | ERR_QUEUE_DESTROY | Failed to destroy queue, errno = %d. | | ERR-00163 | ERR_QUEUE_ENQUEUE | Failed to enqueue queue, errno = %d. | | ERR-00164 | ERR_QUEUE_DEQUEUE | Failed to dequeue queue, errno = %d. | | ERR-00171 | ERR_THR_ATTR_CREATE | Failed to create thread_attr, errno = %d. | | ERR-00172 | ERR_THR_ATTR_DESTROY | Failed to destroy thread_attr, errno = %d. | | ERR-00173 | ERR_THR_ATTR_SET_BOUND | Failed to set thread_attr bound, errno = %d. | | ERR-00174 | ERR_THR_ATTR_SET_DETACH | Failed to set thread_attr detach, errno = %d. | | ERR-00175 | ERR_THR_ATTR_SET_STACK_SIZE | Failed to set thread_attr stack size, errno = %d. | | ERR-00176 | ERR_THR_CREATE | Failed to create thread, errno = %d. | | ERR-00177 | ERR_THR_DETACH | Failed to detach thread, errno = %d. | | ERR-00178 | ERR_THR_JOIN | Failed to join thread, errno = %d. | | ERR-00179 | ERR_THR_GETID | Failed to get id of thread, errno = %d. | | ERR-00191 | ERR_THR_CV_CREATE | Failed to create thread condition variable, errno = %d. | | ERR-00192 | ERR_THR_CV_DESTROY | Failed to destroy thread condition variable, errno = %d. | | ERR-00193 | ERR_THR_CV_TIMEDWAIT | Failed to call cond_timedwait, errno = %d. | | ERR-00194 | ERR_THR_CV_SIGNAL | Failed to call cond_signal, errno = %d. | | ERR-00195 | ERR_THR_CV_BROADCAST | Failed to call cond_broadcast, errno = %d. | | ERR-00196 | ERR_THR_CV_WAIT | Failed to call cond_wait, errno = %d. | | ERR-00201 | ERR_RWMUTEX_CREATE | Failed to create rwlock, errno = %d. | | ERR-00202 | ERR_RWMUTEX_DESTROY | Failed to destroy rwlock, errno = %d. | | ERR-00203 | ERR_RWMUTEX_LOCK_READ | Failed to call rwlock_lock_read, errno = %d. | | ERR-00204 | ERR_RWMUTEX_TRYLOCK_READ | Failed to call rwlock_trylock_read, errno = %d. | | ERR-00205 | ERR_RWMUTEX_LOCK_WRITE | Failed to call rwlock_lock_write, errno = %d. | | ERR-00206 | ERR_RWMUTEX_TRYLOCK_WRITE | Failed to call rwlock_trylock_write, errno = %d. | | ERR-00211 | ERR_RBTREE_TOO_SMALL_BUFFER | RBTREE buffer<%d> is too small for value<%d>, errno = %d. | | ERR-00212 | ERR_RBTREE_CURSOR_OP_NOT_APPLICABLE | RBTREE cursor op not applicable. errno = %d. | | ERR-00213 | ERR_RBTREE_ALREADY_FREE_NODE | RBTREE node is already freed, errno = %d. | | ERR-00216 | ERR_TREEMAP_KEY_EXISTS | Key already exists. | | ERR-00221 | ERR_LZO_COMPRESS | LZO compress failed, errno = %d. | | ERR-00222 | ERR_LZO_DECOMPRESS | LZO decompress failed, errno = %d. | | ERR-00231 | ERR_GET_CPU_COUNT | Failed to get CPU count, errno = %d. | | ERR-00232 | ERR_CONF_NO_FILE | Configuration file does not exist(%S). | | ERR-00251 | ERR_TLSF_MEL_INITIALIZE | Tlsf memory manager initialization failed, errno = %d. | | ERR-00252 | ERR_TLSF_MEL_FINALIZE | Tlsf memory manager finalization failed, errno = %d. | | ERR-00253 | ERR_TLSF_MEL_ALLOC | Tlsf memory manager allocation(%lld) failed, errno = %d. | | ERR-00254 | ERR_TLSF_MEL_FREE | Tlsf memory manager free failed, errno = %d. | | ERR-00255 | ERR_TLSF_MEL_CONTROL | Tlsf memory manager control failed, errno = %d. | | ERR-00256 | ERR_TLSF_MEL_SHRINK | Tlsf memory manager shrink failed, errno = %d. | | ERR-00257 | ERR_TLSF_MEL_GETSTATISTICS | Tlsf memory manager getstatistics failed, errno = %d. | | ERR-00271 | ERR_SESSION_CLOSED | The session is closed. | | ERR-00272 | ERR_SESSION_CANCELED | The session is canceled. | | ERR-00291 | ERR_LICENSE_INVALID | The license is invalid or expired. | | ERR-00292 | ERR_LICENSE_NOTEXIST_VALUE | The value<%s> does not exist in the license file. | | ERR-00293 | ERR_LICENSE_GET_HARDWARE_KEY | Failed to get hardware key, errno =%d | | ERR-00294 | ERR_LICENSE_VERIFY | Failed to verify the license, errno = %d | | ERR-00300 | ERR_INVALID_DATE_VALUE | Invalid date value.(%s) | | ERR-00301 | ERR_INVALID_NETWORK_TYPE | Invalid network string.(%s) | | ERR-00321 | ERR_SHA_SHA1_INIT_ERROR | Error in initializing sha1, errno = %d | | ERR-00322 | ERR_SHA_SHA1_UPDATE_ERROR | Error in updating sha1, errno = %d | | ERR-00323 | ERR_SHA_SHA1_FINAL_ERROR | Error in finalizing sha1, errno = %d | | ERR-00324 | ERR_SHA_INVALID_TYPE_ERROR | Invalid SHA type.(%d) | | ERR-00325 | ERR_SHA_INVALID_HEX_STRING | Invalid SHA hex string.(%s) | | ERR-00341 | ERR_PARALLEL_JOB_MANAGER_THREAD_ABNORMAL_SHUTDOWN | Parallel job thread abnormally terminated | | ERR-00342 | ERR_PARALLEL_JOB_MANAGER_INVALID_THREAD_COUNT | The thread count should be between %d and %d | | ERR-00361 | ERR_RESFILE_BUFFER_SET_LOG_ERROR | Error in setting a log to the buffer of the result file: %s, errno = %d | | ERR-00381 | ERR_PCRE_COMPILE_ERROR | Regular expression error: an error occurred at offset %d of (%s). | | ERR-00400 | ERR_VERSION_NO_META | This DB file is older than binary (no meta-version table). Check database image and binary. | | ERR-00401 | ERR_VERSION_MISMATCH | Version mismatched. In Executable DB(%d.%d) META(%d.%d) CM(%d.%d) But, In File DB(%d.%d) META(%d.%d) CM(%d.%d) | | ERR-00402 | ERR_META_VERSION_TOO_HIGH | Incompatible meta version. File Meta Version(%d.%d) is higher than Executable Version(%d.%d) | | ERR-00420 | ERR_GET_SYS_INFO | Error in getting system information by the sysinfo, errno = %d | | ERR-00421 | ERR_GET_STACK_SIZE | Error in getting stack information by the pmuSysSetStackSize, errno = %d | | ERR-00422 | ERR_SET_STACK_SIZE | Error in setting stack information by the pmuSysSetStackSize, errno = %d | | ERR-00431 | ERR_MEM_MMAP | mmap (size<%u>) error, errno = %d | | ERR-00432 | ERR_MEM_UNMMAP | unmap (address<%p>, size<%u>) error, errno = %d | | ERR-00451 | ERR_CPU_AFFINITY_SET | Failed to set the CPU affinity [%u, %u), errno = %d | | ERR-00452 | ERR_CPU_AFFINITY_INVALID_CPUID | The IDs of CPUs should be between [0, %u), but [%u, %u) given. | | ERR-00453 | ERR_CPU_AFFINITY_INVALID_CPURANGE | Maximum abs value of CPU_AFFINITY_COUNT(%d) should be less than CPU count(%u). | | ERR-00461 | ERR_SYSCONF_CPUCNT | Failed to get the number of CPUs in sysconf, errno = %d | | ERR-00471 | ERR_PM_HEAP_INIT | Failed to initialize a heap. | | ERR-00472 | ERR_PM_HEAP_PUSH | Heap push failed, errno = %d | | ERR-00481 | ERR_PM_AUTH_NONCE_GENERATE | Failed to generate auth nonce. | | ERR-00482 | ERR_PM_AUTH_SIGN | Failed to sign auth challenge. | | ERR-00483 | ERR_PM_AUTH_VERIFY | Failed to verify auth signature. | | ERR-00484 | ERR_PM_AUTH_INVALID_KEY | Invalid auth key. | | ERR-00485 | ERR_PM_AUTH_INVALID_SIG_SCHEME | Invalid auth signature scheme. | | ERR-00486 | ERR_PM_AUTH_INVALID_SIGNATURE | Invalid auth signature. | | ERR-00487 | ERR_PM_AUTH_INVALID_NONCE | Invalid auth nonce. | | ERR-00488 | ERR_PM_AUTH_KEY_FILE_TOO_LARGE | Auth key file is too large. path=[%s], size=[%llu], limit=[%llu] | | ERR-00491 | ERR_JSON_DUMP | Error in json dump. | | ERR-00492 | ERR_JSON_LOAD | Error in json load. | | ERR-00493 | ERR_JSON_OBJ | json object error: %s | | ERR-00494 | ERR_JSON_ARR | Error in json-array. | | ERR-00495 | ERR_JSON_STR | Error in json-string (%s). | | ERR-00496 | ERR_JSON_INT | Error in json-integer (%lld). | | ERR-00497 | ERR_JSON_REAL | Error in json-real (%lf). | | ERR-00498 | ERR_JSON_COPY | Error in json copy. | | ERR-00499 | ERR_JSON_PACK | Error in json pack. | | ERR-00500 | ERR_JSON_UPACK | Error in json unpack. | | ERR-00501 | ERR_JSON_EXTR_PATH | No data matches for the json path (%s) | | ERR-00502 | ERR_JSON_PATH_LEN | Json path is too long. | | ERR-00503 | ERR_JSON_OBJECT_VALUE_SET | Error json object set (%s). | | ERR-00504 | ERR_JSON_OBJECT_ARRAY_APPEND | Error json array append. | | ERR-00505 | ERR_JSON_ENCODE | Error encode base64. | | ERR-00506 | ERR_JSON_DECODE | Error decode base64. | | ERR-00507 | ERR_JSON_OBJECT_VALUE_DEL | Error json object del (%s). | | ERR-00600 | ERR_INVALID_PROPERTY_VALUE | Invalid property value: %s. | | ERR-00601 | ERR_PM_CONVERSION_UTF8 | Failed to convert %s to UTF8. (%s, errno=%d) | | ERR-00602 | ERR_PM_CONVERTSION_STRING_LENGTH | Buffer size is not enough for code conversion. (%d > %d) | | ERR-00611 | ERR_INVALID_PROPERTY_EXPRESSION | Invalid property expression for %s: %s. | | ERR-00701 | ERR_PM_GEOHASH_INVALID_PRECISION | Geohash invalid precision (%u) | | ERR-00702 | ERR_PM_GEOHASH_INVALID_LENGTH | Geohash invalid length | | ERR-00703 | ERR_PM_GEOHASH_INVALID_DIRECTION | Geohash invalid direction | ### `ERR-01000`–`ERR-01999` (191) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-01000 | ERR_SM_INVALID_DISK_FILE | File<%s> is invalid. | | ERR-01001 | ERR_SM_INVALID_OBJ_STORAGE_ID | Invalid object storage id, errno = %d. | | ERR-01002 | ERR_SM_INVALID_ALREADY_FREE_OBJECT_STORAGE | Object storage<%d> already freed, errno = %d. | | ERR-01003 | ERR_SM_DBS_DIR_ALREADY_EXIST | Group storage dir<%s> already exists, errno = %d. | | ERR-01004 | ERR_SM_DBS_INVALID_OBJECT_FILENAME | Object filename<%s> is invalid, errno = %d. | | ERR-01005 | ERR_SM_DISK_FILE_IN_USE | Disk file<%s> is in use, errno = %d. | | ERR-01006 | ERR_SM_NOT_SUPPORT_FUNCTION | Functionality is not supported yet. | | ERR-01007 | ERR_SM_FILE_NO_AVAILABLE_DISK_SPACE | There is no available disk space for writing <%lld>bytes to the file<%s>, errno = %d. | | ERR-01008 | ERR_SM_FILE_DUPLICATE | Error in the duplicating file<%s>, errno = %d. | | ERR-01009 | ERR_SM_WRONG_READ_SIZE | Error in the read file size.(<io: %u>, <disk: %u>) | | ERR-01010 | ERR_SM_SPACE_NOT_AVAILABLE_4_APPEND | Used media space is reached to threshold. (%4.1lf%% cap < %4.1lf%% used) | | ERR-01011 | ERR_SM_FILE_WRITE_SIZE_MISMATCH | Error in the write file size.(<write: %u>, <written: %u>) | | ERR-01031 | ERR_SM_DB_ALREADY_MOUNTED | The database in <%s> has already been mounted. | | ERR-01032 | ERR_SM_DB_NOT_MOUNTED | The database in <%s> is not mounted. | | ERR-01033 | ERR_SM_DB_MOUNTING | The mount operation of database in <%s> is not completed. | | ERR-01034 | ERR_SM_DB_MOUNT_BUSY | The mounted database<%s> is busy. | | ERR-01035 | ERR_SM_DB_ALREADY_EXIST | The database creation is not complete. Destroy it and create a new one. | | ERR-01036 | ERR_SM_DB_CREATE_NOT_COMPLETE | The database creation is not complete. Destroy it and create a new one. | | ERR-01037 | ERR_SM_DB_MOUNT_INVALIDE_BASEDB | The mount database<%s> is not backed up from the primary database | | ERR-01038 | ERR_SM_DB_COULD_NOT_FIND_MOUNTDB | Cannot find MountDB with <TBSID: %lld>. | | ERR-01039 | ERR_SM_DB_STATE_OF_MOUNTDB_IS_ABNORMAL | Mount DB<%s>'s state is invalid. | | ERR-01101 | ERR_SM_COLUMN_PARTITION_CACHE_READ_BLOCK | Error in reading column partition cache block. Reading block of RID<%lld> in the column partition<%lld> failed, errno = %d. | | ERR-01102 | ERR_SM_INVALID_CACHE_OBJECT | Invalid cache object. | | ERR-01103 | ERR_SM_CHECKPOINT_THREAD_ABNORMAL_SHUTDOWN | Error occurred in checkpoint thread. Processing abnormal shutdown. | | ERR-01104 | ERR_SM_CACHE_WAIT_READ_PAGE | Error in waiting to read a page. | | ERR-01105 | ERR_SM_CACHE_PAGE_CLEAR_THREAD_ABNORMAL_SHUTDOWN | Error in clear thread of the page cache. | | ERR-01106 | ERR_SM_CACHE_PAGE_MAX_SET_SMALLER_SIZE | It<%llu> is smaller than the max size value of the page cache currently set<%llu>. | | ERR-01107 | ERR_SM_CACHE_PAGE_MAX_SET_IMPOSSIBLE_SIZE | It<%llu> is impossible to set a value larger than the memory size set in the current process<%llu>. | | ERR-01108 | ERR_SM_CP_INVALID_PAGE_ID | Invalid page id in column partition. Page id<%d> is greater than the page max id<%d>. | | ERR-01201 | ERR_SM_ALREADY_EXIST_TABLE_ID_TABLES | Duplicated table id<%llu> in SYS_STORAGE_TABLES, errno = %d. | | ERR-01202 | ERR_SM_ALREADY_EXIST_TABLE_ID_COLUMNS | Duplicated table id<%llu>, column id<%u> in the SYS_STORAGE_COLUMNS, errno = %d. | | ERR-01203 | ERR_SM_NOT_EXIST_TABLE_ID_IN_TABLES | Table id<%lld> does not exist in SYS_STORAGE_TABLES, errno = %d. | | ERR-01204 | ERR_SM_ALREADY_EXIST_INDEX_ID_INDEXES | Duplicated (table id<%llu>, index id<%llu>) in SYS_STORAGE_INDEXES, errno = %d. | | ERR-01205 | ERR_SM_ALREADY_EXIST_INDEX_ID_COLUMNS | Duplicated (table id<%llu>, index id<%llu>, column id<%u>) in SYS_STORAGE_INDEXES_COLUMNS, errno = %d. | | ERR-01206 | ERR_SM_NOT_EXIST_INDEX_ID_IN_INDEXES | Index ID<%llu> of table ID<%llu> does not exist in SYS_STORAGE_INDEXES, errno = %d. | | ERR-01207 | ERR_SM_INVALID_RECOVERY_MODE_STRING | Available recovery modes: simple, complex, reset | | ERR-01301 | ERR_SM_NOT_EXIST_PARTION_RANGE | Partition range does not exist. Partition id is less than <%lld> in the table(id<%lld>) with partitions between <%lld> and <%lld>. | | ERR-01302 | ERR_SM_NOT_EXIST_RECORD_RANGE | Invalid record range. No such record whose id is less than <%llu> in the table(id<%llu>) with records between <%llu> and <%llu>. | | ERR-01303 | ERR_SM_TOO_MANY_COLUMNS_FOR_TABLE | Maximum number of columns in a table is %d. | | ERR-01304 | ERR_SM_INVALID_COLUMN_ID | Invalid column ID (<%d>). | | ERR-01305 | ERR_SM_TABLE_NOT_EXIST | Invalid table ID (<%llu>). | | ERR-01306 | ERR_SM_TABLE_ALREADY_DROPPED | Table has been dropped. | | ERR-01307 | ERR_SM_TABLE_STRUCTURE_MODIFIED | Table structure was modified. | | ERR-01308 | ERR_SM_TABLE_INVALID_FIXED_COLUMN_SIZE | Invalid fixed column size. Invalid value size(<%u>) for the fixed column. | | ERR-01309 | ERR_SM_TABLE_VAR_COLUMN_SIZE_TOO_BIG | Invalid varying column size. Value size(<%u>) for the variable column is greater than the max size (<%u>). | | ERR-01310 | ERR_SM_TABLE_FLUSH_THREAD_ABNORMAL_SHUTDOWN | Table flush thread terminated abnormally. | | ERR-01311 | ERR_SM_TABLE_COLUMN_PARTITION_PREPARE_THREAD_ABNORMAL_SHUTDOWN | Table column partition prepare thread terminated abnormally. | | ERR-01312 | ERR_SM_TABLE_COLUMN_PARTITION_FILE_READ_HEAD | Failed to read the head of the table column partition file (<%s>). | | ERR-01313 | ERR_SM_TABLE_COLUMN_PARTITION_FILE_READ | Failed to read the table column partition file (<%s>). | | ERR-01314 | ERR_SM_TABLE_INDEX_BUILD_THREAD_ABNORMAL_SHUTDOWN | Index build thread terminated abnormally. | | ERR-01315 | ERR_SM_TABLE_INVALID_TYPE | Invalid table type<%d>. | | ERR-01316 | ERR_SM_TABLE_COLUMN_SIZE_TOO_BIG | Column size<%u> is too big. | | ERR-01317 | ERR_SM_TABLE_COLUMN_INVALID_TIME_VALUE | Value of the time column(<%lld>) is less than the last time value(<%lld>). | | ERR-01318 | ERR_SM_TABLE_COLUMN_INVALID_VARCHAR_SIZE | The size of VARCHAR column must be less than (<%llu>). | | ERR-01319 | ERR_SM_TABLE_COLUMN_INVALID_VALUE_SIZE | The size of column value must be less than (<%u>). | | ERR-01320 | ERR_SM_TABLE_COLUMN_REFERENCED_BY_INDEX | There is an index on the column(<%u>) of the table(<%llu>) | | ERR-01321 | ERR_SM_TABLE_NOT_SUPPORT_FUNCTION | This feature is not supported on this table type. | | ERR-01322 | ERR_SM_TABLE_COLUMN_INVALID_NEWSIZE | The new column size(<%u>) should be greater than the old one(<%u>) | | ERR-01323 | ERR_SM_TABLE_COLUMN_MAX | The table(%llu) reached max column count limit (%u) already. | | ERR-01324 | ERR_SM_TABLE_COLUMN_PARTITION_FILE_ADJUST_END_RID | An error occurred adjusting end rid of the table<%llu> column partition(<%llu>), errno = %d. | | ERR-01325 | ERR_SM_TABLE_COLUMN_TOO_SMALL_END_RID | The end RID<%lld> of the column<%d> is less than the end RID<%llu> of the table<%llu> | | ERR-01330 | ERR_SM_TABLE_COLUMN_NOT_FOUND | The column with ID<%hu> does not exist in the table with ID<%llu> | | ERR-01331 | ERR_SM_TABLE_CHECKPOINT_THREAD_ABNORMAL_SHUTDOWN | Table checkpoint thread terminated abnormally. | | ERR-01332 | ERR_SM_TABLE_NOT_EXIST_PARTION | Partition ID <%llu> of the table(id<%llu>) does not exist between <%llu> and <%llu>. | | ERR-01333 | ERR_SM_TABLE_MOUNT_ALREADY | The table<%llu> in the backup database<%s> has been mounted already. | | ERR-01334 | ERR_SM_TABLE_MOUNT_BUSY_WITH_MOUNTING | The table is busy with mounting. | | ERR-01335 | ERR_SM_TABLE_MOUNT_BUSY_WITH_UNMOUNTING | The mounted table is busy with unmounting. | | ERR-01336 | ERR_SM_TABLE_MOUNT_INVALID_STATE | The mounted table is invalid. | | ERR-01337 | ERR_SM_TABLE_MOUNT_IS_BUSY | The mounted table is busy. | | ERR-01338 | ERR_SM_TABLE_MOUNT_NOT_EXIST | The table is not mounted. | | ERR-01339 | ERR_SM_TABLE_MOUNT_TABLE_NOT_SAME_WITH_TABLE | The table<%llu> of the backup tablespace<%s> is different from the table in main database. | | ERR-01340 | ERR_SM_TABLE_MOUNT_TABLE_DROPPED_IN_MAIN_DATABASE | The table<%llu> of the backup tablespace<%s> is dropped from the main database. | | ERR-01341 | ERR_SM_TABLE_HAS_MOUNTED_TABLE | There is a mounted table in the table<%llu>. | | ERR-01342 | ERR_SM_TABLE_MOUNT_HAS_FUTURE_DATA | The mount table<end_rid:%llu> has more furture data than the base table<end_rid:%llu. | | ERR-01343 | ERR_SM_TABLE_UPDATE_COLUMN_INDEX_CREATED | Cannot update columns with indexes in VOLATILE / LOOKUP table. | | ERR-01344 | ERR_SM_TABLE_VOLITILE_MEMORY_LIMIT | The memory size<%llu bytes> of VOLATILE / LOOKUP tables exceeds <%llu bytes>. | | ERR-01345 | ERR_SM_TABLE_COLUMN_VALUE_NOT_NULL | The value of the column<%u> must not be NULL | | ERR-01346 | ERR_SM_PROCESS_MEMORY_LIMIT | Current Allocate Memory / PROCESS_MAX_SIZE (%llu/%llu), increase PROCESS_MAX_SIZE property and restart. | | ERR-01401 | ERR_SM_INDEX_INVALID_TYPE | Invalid index type. Index type<%d> does not exist. | | ERR-01402 | ERR_SM_INDEX_NOT_EXIST_IN_TABLE | Index id(<%llu>) does not exist in table id <%llu>. | | ERR-01403 | ERR_SM_INDEX_INVALID_COLUMN_COUNT | Index has invalid column count(<%d>). | | ERR-01404 | ERR_SM_INDEX_INVALID_KEYVALUE_COUNT | Index has invalid key value count(<%d>). | | ERR-01405 | ERR_SM_INDEX_INVALID_KEYVALUE_SIZE | Index has invalid key value size(<%d>). | | ERR-01406 | ERR_SM_INDEX_INVALID_FILE | Index column file(<%s>) is invalid. | | ERR-01407 | ERR_SM_INDEX_COLUMN_PARTITION_FILE_READ_HEAD | Failed to read the head of the index column partition file(<%s>). | | ERR-01408 | ERR_SM_INDEX_COLUMN_PARTITION_FILE_READ | Failed to read the index column partition file(<%s>). | | ERR-01409 | ERR_SM_INDEX_COLUMN_INVALID_COLUMN_TYPE | Type of the column for the index is invalid. | | ERR-01410 | ERR_SM_INDEX_FLUSH_THREAD_ABNORMAL_SHUTDOWN | Index flush thread terminated abnormally. | | ERR-01411 | ERR_SM_INDEX_BUILD_THREAD_ABNORMAL_SHUTDOWN | Index build thread terminated abnormally. | | ERR-01412 | ERR_SM_KDW_INDEX_INVALID_KEY_SIZE | The keyword size<%d> should be less than the max size<%d>. | | ERR-01413 | ERR_SM_INDEX_INVALID_WORDBITCNT | The word bit count(%d) is over than %d in the partition<%lld> of the index <%lld> | | ERR-01414 | ERR_SM_INDEX_INVALID_KEYVALCNT | Invalid key count <%u> is not equal to the count <%u> in partition <%lld> of index <%lld>. | | ERR-01415 | ERR_SM_INDEX_INVALID_LEVEL | The level<%u> of the index is bigger than the max level<%u> | | ERR-01416 | ERR_SM_INDEX_INVALID_LEVEL_PART_SIZE | The partition size<%u> of level<%u> is bigger than the max level<%u> | | ERR-01417 | ERR_SM_INDEX_ALREADY_DROPPED | The index has been dropped. | | ERR-01418 | ERR_SM_INDEX_UNIQUE_VIOLATION | The key already exists in the unique index. | | ERR-01419 | ERR_SM_INDEX_PRIMARY_INDEX_ALREADY_CREATED | The primary index is already created on the table. | | ERR-01420 | ERR_SM_INDEX_INVALID_KEYVALUE_N_BITVECTOR_COUNT | The number<%llu> of key values is different from the number<%llu> of bitvectors. | | ERR-01421 | ERR_SM_INDEX_LSM_INVALID_PART_FILE | The partition file<%llu> on the level<%u> of the index<%llu> is invalid.(KPC:%u, BPC:%u) | | ERR-01422 | ERR_SM_INDEX_PRAIMARY_INDEX_NOT_NULL | NULL value is not allowed for the primary index column | | ERR-01423 | ERR_SM_KEYVALUE_CACHE_EXHAUSTED | TAG cache exhausted, increase TAG_CACHE_MAX_MEMORY_SIZE(%llu) | | ERR-01424 | ERR_SM_KEYVALUE_CACHE_TIMEOUT | Could not allocate TAG cache: (Table,part=%llu,%llu) offset/size=%llu/%llu | | ERR-01425 | ERR_SM_KEYVALUE_INDEX_MEMORY_LIMIT | Failed to allocate index memory (Current Allocated Size / Threshold size (%llu/%llu)). | | ERR-01426 | ERR_SM_KEYVALUE_NOT_READY_TO_BUILD_INDEX | Not ready to build keyvalue index (Current Count / Target Count (%llu/%llu) in File). | | ERR-01501 | ERR_SM_CPFILE_INVALID_PAGE_ID | Invalid page id in cpfile. Page id<%d> for the column partition file<%s> is greater than the page max id. | | ERR-01502 | ERR_SM_CPFILE_INVALID_PAGE_TIMESTAMP | Error in reading page<%d> in the column partition file<%s>. Page timestamps <head:%lld, tail:%lld> are invalid. | | ERR-01503 | ERR_SM_CPFILE_INVALID_PAGE_CHECKSUM | Error in reading page<%d> in the column partition file<%s>. Page checksum <write:%#X, read:%#X> are invalid | | ERR-01504 | ERR_SM_CPFILE_FILE_INVALID_SIZE | The size<%u> of the column partition file<%s> is too small. It is supposed to be greater than the size<%u> | | ERR-01505 | ERR_SM_CPFILE_FILE_INVALID_PAGE_UPDATE | The offset<%u> and size<%u> of the update value for the page<id:%u, offset:%u, size:%u> in the column partition file<%s> is invalid | | ERR-01506 | ERR_SM_CPFILE_INVALIDE_FILE_HEAD_CRC | The checksum<write:%#X, read:%#X> of the head of the column partition file<%s> is invalid. | | ERR-01551 | ERR_SM_FDCACHE_GET_FD_FOR_FILE | Error in getting the fd of the file<%s> from the fd cache. | | ERR-01601 | ERR_SM_AGER_THREAD_ABNORMAL_SHUTDOWN | Ager thread terminated abnormally. | | ERR-01631 | ERR_SM_BACKUP_NOT_EXIST_BACKUP_ROOT_DIR | There is no root dir<%s> for the database backup. | | ERR-01632 | ERR_SM_BACKUP_NOT_DATABASE_DESTROYED | The database is not destroyed. | | ERR-01633 | ERR_SM_BACKUP_STATFILE_WRITE | Failed to write data<%u> of the backup stat file<%s>. | | ERR-01634 | ERR_SM_BACKUP_STATFILE_READ | Failed to read data<%u> of the backup stat file<%s>. | | ERR-01635 | ERR_SM_BACKUP_STATFILE_INVALID | The backup statfile<%s> is invalid(CRC<H:%u, B:%u, T:%u). | | ERR-01636 | ERR_SM_BACKUP_NOT_COMPLETE | The backup <%s> is not completed. | | ERR-01637 | ERR_SM_BACKUP_DIR_ALREADY_EXIST | The backup <%s> has already exist. | | ERR-01638 | ERR_SM_BACKUP_INVALID_END_RID | The end rid<%llu> of the table<%llu> in the restored database is invalid. | | ERR-01639 | ERR_SM_BACKUP_NAME_TOO_LONG | The name<%s> of backup is too long, errno = %d. | | ERR-01640 | ERR_SM_BACKUP_FILE_ALREADY_EXIST | The backup file<%s> already exists. | | ERR-01641 | ERR_SM_BACKUP_FILE_INVALID_MAGIC_STRING | The backup file<%s> has the invalid magic string<%s>. | | ERR-01642 | ERR_SM_BACKUP_FILE_HEAD_INVALID_CRC32 | The header of backup file<%s> has the invalid crc32<%u>. | | ERR-01643 | ERR_SM_BACKUP_FILE_INVALID_FILENAME_LEN | Length<%u> of backup file<%s> is too long. | | ERR-01644 | ERR_SM_BACKUP_FILE_INVALID_PAGESIZE | The page size <%u> of backup file<%s> is invalid. | | ERR-01645 | ERR_SM_BACKUP_FILE_INVALID_SIZE | The file size <%llu> of the head is different from the size<%llu> on the disk. | | ERR-01646 | ERR_SM_BACKUP_FILE_INVALID_STATE | The backup file is invalid since the backup is not completed. | | ERR-01647 | ERR_SM_INC_BACKUP_NOT_LATEST | An incremental backup requires a previous backup. | | ERR-01648 | ERR_SM_INC_BACKUP_TARGET_NOT_SAME | Backup targets are different from that of previous target. | | ERR-01701 | ERR_SM_TBS_REFERENCED_BY_OBJECTS | The tablespace<%s> is still referenced by other objects such as tables and indexes. | | ERR-01702 | ERR_SM_TBS_NOT_EXIST | The tablespace<%s> does not exist in the database. | | ERR-01703 | ERR_SM_TBS_CANNOT_DROP_SYSTEM_TBS | The SYSTEM_TABLESPACE cannot be dropped. | | ERR-01704 | ERR_SM_TBS_ALEADY_EXIST | Tablespace already exists. <%s> | | ERR-01705 | ERR_SM_TBS_DISKDIR_ALEADY_EXIST | The dir<%s> for the tablespace<%s> of datadisk<%s> already exists. | | ERR-01706 | ERR_SM_TBS_PHYDISK_NOT_EXIST | Disk<%s> does not exist in the tablespace<%s>. | | ERR-01707 | ERR_SM_TBS_PHYDISK_INVALID_PARALLEL_IO | The parallel I/O of a disk should be between %d and %d. | | ERR-01708 | ERR_SM_TBS_FILE_READ | Failed to read <%ld> bytes from the file<%s>, errno = %d. | | ERR-01709 | ERR_SM_TBS_FILE_PAGE_INVALID_TIMESTAMP | The page<offset:%u, size:%u> of the file<%s> is invalid because it has the invalid timestamp<head:%lld, tail:%lld> | | ERR-01710 | ERR_SM_TBS_FILE_PAGE_INVALID_CRC32 | The page<offset:%u, size:%u> of the file<%s> is invalid because it has the invalid crc<memory:%u, disk:%u> | | ERR-01711 | ERR_SM_TBS_VIRDISK_DIR_CREATE | Failed to create directory<%s> for virtual disk. | | ERR-01712 | ERR_SM_TBS_MEMORY_DIR_SHORTAGE | Failed to allocate memory for directory to be removed. | | ERR-01801 | ERR_SM_EXTCP_WAIT_READ_VALUE | Error in waiting to read value: value offset<%lld>, value size<%u>, and file<%s> | | ERR-01821 | ERR_SM_DWFILE_INVALID_IMAGE | The image in the DWFile<%s> is invalid. | | ERR-01841 | ERR_SM_ART_ABORT | The operation is aborted by ART. | | ERR-01851 | ERR_SM_NO_VAR_IN_TAG | Variable length columns are not allowed in tag table. | | ERR-01852 | ERR_SM_DELETE_IN_PROGRESS | Another deletion is in progress for table <%llX>. | | ERR-01853 | ERR_SM_KEYVALUE_CREATE_APPENDFILE | Cannot create append file for Key-Value table <%llX>, errno = %d. | | ERR-01854 | ERR_SM_KEYVALUE_SYNC_APPENDFILE | Cannot sync append file for Key-Value table <%llX>, errno = %d. | | ERR-01855 | ERR_SM_KEYVALUE_CLOSE_APPENDFILE | Cannot close append file for Key-Value table <%llX>, errno = %d. | | ERR-01856 | ERR_SM_KEYVALUE_CREATE_DATAFILE | Cannot create data file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01857 | ERR_SM_KEYVALUE_OPEN_DATAFILE | Cannot open data file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01858 | ERR_SM_KEYVALUE_READ_DATAFILE | Cannot read data file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01859 | ERR_SM_KEYVALUE_WRITE_DATAFILE | Cannot write data file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01860 | ERR_SM_KEYVALUE_CORRUPTED_DATAFILE | Data file <%llX> is corrupted for Key-Value table <%llX>. | | ERR-01861 | ERR_SM_KEYVALUE_CREATE_INDEXFILE | Cannot create index file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01862 | ERR_SM_KEYVALUE_OPEN_INDEXFILE | Cannot open index file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01863 | ERR_SM_KEYVALUE_READ_INDEXFILE | Cannot read <.%s> file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01864 | ERR_SM_KEYVALUE_WRITE_INDEXFILE | Cannot write <.%s> file <%llX> for Key-Value table <%llX>, errno = %d. | | ERR-01865 | ERR_SM_KEYVALUE_CORRUPTED_INDEXFILE | Index file <%llX> is corrupted for Key-Value table <%llX>. | | ERR-01866 | ERR_SM_KEYVALUE_IOERROR | Cannot perform I/O for Key-Value table <%llX>. | | ERR-01867 | ERR_SM_KEYVALUE_INVALID_PATH_APPENDFILE | Invalid path to append file for Key-Value table <%llX>, errno = %d. | | ERR-01868 | ERR_SM_KEYVALUE_OPEN_APPENDFILE | Cannot open append file for Key-Value table <%llX>, errno = %d. | | ERR-01869 | ERR_SM_KEYVALUE_NO_DATAFILE | RID-based SELECT is not allowed without datafile, Table<%llX>/RID<%llu>. | | ERR-01870 | ERR_SM_KEYVALUE_OPEN_MOUNTED_APPENDFILE | Cannot open append file for mounted Key-Value table <%llX>, errno = %d. | | ERR-01871 | ERR_SM_KEYVALUE_READ_MOUNTED_APPENDFILE | Cannot read append file for mounted Key-Value table <%llX>, errno = %d. | | ERR-01872 | ERR_SM_BACKUP_IN_PROGRESS | Another backup is in progress for table <%llX>. | | ERR-01873 | ERR_SM_KEYVALUE_NO_INDEXFILE | No index-file <%llx> for Key-Value table Table<%llX>. | | ERR-01874 | ERR_SM_KEYVALUE_OPEN_FILE | Cannot open file <%llX> for Key-Value table <%llX> path<%s>, errno = %d. | | ERR-01875 | ERR_SM_KEYVALUE_NO_UNPURGED_NODE | Cannot find unpurged node for Key-Value table <%llX>. | | ERR-01876 | ERR_SM_KEYVALUE_FILE_DECOMPRESS | Failed to use %s to decompress file <%llX> for key-value table <%llx>, error = %d. | | ERR-01877 | ERR_SM_KEYVALUE_NOT_FOUND_STAT_DATA | Tag stat for id[%llu] is not found. | | ERR-01878 | ERR_SM_STAT_WRITE_FILE | Cannot write stat file for Key-Value table <%llX> path<%s> errno = %d. | | ERR-01879 | ERR_SM_STAT_READ_FILE | Cannot read stat file for Key-Value table <%llX> path<%s> errno = %d. | | ERR-01880 | ERR_SM_STAT_OPEN_FILE | Cannot open stat file for Key-Value table <%llX> path<%s>, errno = %d. | | ERR-01881 | ERR_SM_STAT_INVALID_FILE | Stat File Invalid TableID[%llu], TablePath[%s]. | | ERR-01882 | ERR_SM_KEYVALUE_NO_KVINDEXFILE | No kvindex-file <%llx> for Key-Value table Table<%llX>. | | ERR-01883 | ERR_SM_KEYVALUE_INVALID_TIME_VALUE | Value of the time column(<%lld>) must be greater than or equal to <%lld>. | | ERR-01884 | ERR_SM_KEYVALUE_THREAD_STOPPED | keyvalue table<%llx> thread for [%s] stopped. | | ERR-01885 | ERR_SM_KEYVALUE_DATA_CORRUPTED | Data row value is corrupted: required RID<%llu>, value RID<%llu>. | | ERR-01886 | ERR_SM_KEYVALUE_VDATA_CORRUPTED | %s varchar data is corrupted: required VRID<%u>, value VRID<%u>. | | ERR-01887 | ERR_SM_UPDATE_IN_PROGRESS | Another update is in progress for table <%llX>. | | ERR-01900 | ERR_SM_SNAPSHOT_NOT_VALID | Snapshot ID <%s> is invalid. | | ERR-01901 | ERR_SM_SNAPSHOT_NO_TABLE | Cannot snapshot with no table. | | ERR-01902 | ERR_SM_SNAPSHOT_TIMEOUT | Snapshot timed out. | | ERR-01903 | ERR_SM_SNAPSHOT_NOT_EXISTS | Snapshot ID <%s> does not exist. | | ERR-01904 | ERR_SM_SNAPSHOT_ALREADY_EXISTS | Snapshot ID <%s> already exists. | | ERR-01910 | ERR_SM_FREEZE_NO_TABLE | Cannot freeze with no table. | | ERR-01911 | ERR_SM_ALREADY_FROZEN | Snapshot already frozen. | | ERR-01951 | ERR_SM_FUNCTION_CALL | Failed to call function <%s>, errno=%d | | ERR-01952 | ERR_SM_TABLE_RESOURCE_BUSY | Table (0x%llx) resource busy (%s). | ### `ERR-02000`–`ERR-02999` (420) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-02000 | QPE_TEST | Memory allocation error, Error code = %d | | ERR-02001 | ERR_QP_OPEN_META | Error in opening meta. | | ERR-02002 | ERR_QP_EXEC_META | Error in executing meta. | | ERR-02003 | ERR_QP_CLOSE_META | Error in closing meta. | | ERR-02004 | ERR_QP_CRT_HASH | Error in creating hash. (errno=%d) | | ERR-02005 | ERR_QP_ALLOC_MEM | Error in allocating memory. | | ERR-02006 | ERR_QP_HASH_ADD | Error in adding hash. (errno=%d) | | ERR-02007 | ERR_QP_FETCH_META | Error in fetching meta. | | ERR-02008 | ERR_QP_HASH_TRAV | Error in traversing hash. | | ERR-02009 | ERR_QP_MEMORY_INSUFFICIENT | Insufficient parser memory. | | ERR-02010 | ERR_QP_PARSE_ERROR | Syntax error: near token (%s). | | ERR-02011 | ERR_QP_TOKEN_ERROR | Unrecognized token (%s). | | ERR-02012 | ERR_QP_SINGLE_ROW_ERROR | Single row error. Single-row subquery returns more than one row. (NOT USED) | | ERR-02013 | ERR_QP_NEED_GROUPBY_ERROR | A GROUP BY clause is required before HAVING. | | ERR-02014 | ERR_QP_COLUMN_NAME_DUPLICATED | Column name is duplicated: (%s). | | ERR-02015 | ERR_QP_COLUMN_TYPE_INVALID | Invalid column type: (%s). | | ERR-02016 | ERR_QP_NO_TABLE_PROPETY_FOUND | Table property (%s) does not exist. | | ERR-02017 | ERR_QP_NO_TABLE_PROPETY_CONVERT | Error in converting table property. Cannot convert string (%s) to integer. | | ERR-02018 | ERR_QP_NO_TABLE_PROPETY_VALUE_RANGE | Table property value is out of range: (%s). | | ERR-02019 | ERR_QP_VARCHAR_TYPE_SIZE_ERROR | Column size must be specified for a variable-length column type. | | ERR-02020 | ERR_QP_TYPE_SIZE_ZERO | Invalid size specified. Cannot specify type size to (%s). | | ERR-02021 | ERR_QP_CREATE_INDEX_INVALID_BITMAP_DATATYPE | Cannot create bitmap index on data type (%s) | | ERR-02022 | ERR_QP_CREATE_INDEX_INVALID_KEYWORD_DATATYPE | Cannot create keyword index on data type (%s) | | ERR-02023 | ERR_QP_SNPRINTF_ERROR | snprintf function error (%d). | | ERR-02024 | ERR_QP_TABLE_CREATE_DUPLICATE | Table %s already exists. | | ERR-02025 | ERR_QP_TABLE_NO_EXISTS | Table %s does not exist. | | ERR-02026 | ERR_QP_TABLE_INSERT_COLUMN_MISMATCH | The number of insert values does not match the number of columns. | | ERR-02027 | ERR_QP_TABLE_INSERT_COLUMN_INT_CONVERSION | Error in table insert column integer conversion. Insert value conversion to integer error (%s). | | ERR-02028 | ERR_QP_TABLE_INSERT_COLUMN_DOUBLE_CONVERSION | Error in table insert column double conversion. Insert value conversion to double error (%s) | | ERR-02029 | ERR_QP_TABLE_INSERT_COLUMN_TIME_FORMAT | Error in table insert column time format. Insert _arrival_time value conversion error. | | ERR-02030 | ERR_QP_TABLE_INSERT_NO_COLUMN | Column name (%s) does not exist. | | ERR-02031 | ERR_QP_TABLE_RESOURCE_BUSY | Resource busy (%s). | | ERR-02032 | ERR_QP_TYPE_COMPARE_CONVERSION | Type conversion error: error occurred while comparing the values of type (%s) and type (%s). | | ERR-02033 | ERR_QP_TYPE_CONCAT | Cannot concatenate non varchar types. | | ERR-02034 | ERR_QP_TIME_FORMAT | Invalid format of time expression. | | ERR-02035 | ERR_QP_FUNCTION_NO_EXISTS | Function [%s] does not exist. | | ERR-02036 | ERR_QP_FUNCTION_ARG | Function [%s] has an invalid argument. | | ERR-02037 | ERR_QP_FUNCTION_ARG_TYPE | Function [%s] argument data type does not match. | | ERR-02038 | ERR_QP_TABLE_NO_SUCH_FOR_STAR | Table [%s] does not exist. | | ERR-02039 | ERR_QP_TABLE_NO_SPECIFIED_FOR_STAR | No table specified in the target list. | | ERR-02040 | ERR_QP_TIME_RANGE_ERROR | Invalid time range. | | ERR-02041 | ERR_QP_TIME_NEGATIVE_ERROR | Time value must be positive. | | ERR-02042 | ERR_QP_NULL_EXPRESSION | Expression cannot have a NULL value. | | ERR-02043 | ERR_QP_AGGR_WHERE | Group function is not allowed here. | | ERR-02044 | ERR_QP_NO_GROUPBY | Not a GROUP BY expression. | | ERR-02045 | ERR_QP_TYPE_UNKNOWN | Type is not supported(typecode is %u). Internal error. | | ERR-02046 | ERR_QP_BUFFER_SHORTAGE | String buffer is not enough. | | ERR-02047 | ERR_QP_LOCK_BUFFER_SHORTAGE | Lock buffer is not enough. Table counts are too many. | | ERR-02048 | ERR_QP_BIND_COUNT_OVERFLOW | Bind parameter count is overflowed. (max=%u) | | ERR-02049 | ERR_QP_BIND_UNABLE | Cannot apply bind parameter. | | ERR-02050 | ERR_QP_BIND_BUFFER_CORRUPTED | Bind data from client is corrupted. | | ERR-02051 | ERR_QP_BIND_TYPE_UNKNOWN | Bind data type unknown (typecode is %u). | | ERR-02052 | ERR_QP_INSERT_UNABLE_TABLE | Cannot insert data into this table (%s). | | ERR-02053 | ERR_QP_TYPE_VALUE_CONVERSION | Failed to convert type (%s) to type (%s). | | ERR-02054 | ERR_QP_AGGR_ERROR_ON_FUNCTION | Aggregation error on function usage (NOT USED) | | ERR-02055 | ERR_QP_ERROR_ON_INSERT_VALUE | Invalid insert value. | | ERR-02056 | ERR_QP_COLUMN_NAME_NOT_FOUND | Column name (%s) not found. | | ERR-02057 | ERR_QP_SEARCH_STRING_ERROR | Only literal type can be used in SEARCH keyword. | | ERR-02058 | ERR_QP_INDEX_CREATE_DUPLICATE | Index %s already exists | | ERR-02059 | ERR_QP_INDEX_NO_EXISTS | Index %s does not exist | | ERR-02060 | ERR_QP_INDEX_ONLY_ONE_COLUMN | Composite index is not supported. | | ERR-02061 | ERR_QP_DIVIDE_BY_ZERO | Cannot divide a value by zero. | | ERR-02062 | ERR_QP_DATE_CALC_INVALID | Cannot calculate date type. | | ERR-02063 | ERR_QP_SEARCH_TYPE_INVALID | Invalid search type. Search type must be VARCHAR. | | ERR-02064 | ERR_QP_ADD_TIME_FORMAT_ERROR | Invalid time format. (format: "year/mon/day hour:min:sec") | | ERR-02065 | ERR_QP_NO_INDEX_PROPETY_FOUND | Index property (%s) does not exist. | | ERR-02066 | ERR_QP_INDEX_PROPETY_VALUE_INVALID | Invalid index property value: (%s). | | ERR-02067 | ERR_QP_TO_ADDR4_FUNCTION_ARG | Error in TO_ADDR4 function aggregate. Argument type to TO_ADDR4 function must be an integer. | | ERR-02068 | ERR_QP_IPV4_FORMAT | Invalid IPv4 address format (%s). | | ERR-02069 | ERR_QP_INDEX_FOR_INVALID_TABLE | %s index can only be created for %s table. | | ERR-02070 | ERR_QP_INDEX_NEEDED_FOR_SEARCH | Search predicate needs keyword index. | | ERR-02071 | ERR_QP_INDEX_COUNT | Only one index is allowed for a single column. | | ERR-02072 | ERR_QP_DELETE_UNABLE_TABLE | Cannot delete data from this table (%s). | | ERR-02073 | ERR_QP_TABLE_DELETE_CONDITION | Invalid DELETE condition. %s | | ERR-02074 | ERR_QP_TABLE_DELETE_TIME_RANGE | Invalid delete time range. BEFORE time range should be older than present. | | ERR-02075 | ERR_QP_TABLE_DROP_NO_INFO_IN_DB | Table(%s) record does not exist in meta database. | | ERR-02076 | ERR_QP_TABLEID_DROP_NO_INFO_IN_DB | Table(%lld) record does not exist in meta database. | | ERR-02077 | ERR_QP_VARCHAR_SIZE_MAX | Invalid %s size. %s type size cannot be more than %d. | | ERR-02078 | ERR_QP_UNKNOWN_STMT_TYPE | Invalid statement type. Statement type(%d) is unsupported. | | ERR-02079 | ERR_QP_FUNCTION_ARG_COUNT | The number of arguments for function (%s) does not match. | | ERR-02080 | ERR_QP_USER_NOT_EXIST | User (%s) does not exist. | | ERR-02081 | ERR_QP_USER_PASSWORD_ERROR | Invalid username/password. | | ERR-02082 | ERR_QP_USER_ALREADY_EXISTS | User (%s) already exists. | | ERR-02083 | ERR_QP_USER_SELF_DROP | You cannot drop yourself(%s). | | ERR-02084 | ERR_QP_USER_TABLE_EXIST | User drop error. This user's tables still exist. Drop those tables first. | | ERR-02085 | ERR_QP_USER_NO_ALTER_PRIV | The user(%s) does not have alter privileges. | | ERR-02086 | ERR_QP_USER_NO_CONNECT_PRIV | The user(%s) does not have connect privileges. | | ERR-02087 | ERR_QP_USER_NO_PRIV_TABLE_ACCESS | The user does not have access privileges on table(%s.%s). | | ERR-02088 | ERR_QP_ALTER_TABLE_NO_RIGHT | Error in altering table. Only the LOG table can be altered. | | ERR-02089 | ERR_QP_ALTER_TABLE_SAME_COLUMN_EXISTS | Error in altering table. Column name(%s) already exists. | | ERR-02090 | ERR_QP_ALTER_TABLE_MODIFY_TYPE | Error in altering table. Only varchar type can be modified. | | ERR-02091 | ERR_QP_ALTER_TABLE_MODIFY_VARCHAR_SIZE | Error in altering table. Varchar length should be greater than previous value length | | ERR-02092 | ERR_QP_ALTER_TABLE_DROP_BUILTIN_COLUMN | Error in altering table. Column (%s) cannot be dropped. | | ERR-02093 | ERR_QP_ALTER_TABLE_DROP_COLUMN_ON_INDEX | Error in altering table. Column (%s) having index cannot be dropped. | | ERR-02094 | ERR_QP_ALTER_TABLE_DUP_COLUMN | Error in altering table. Column (%s) already exists. | | ERR-02095 | ERR_QP_TRUNCATE_NON_LOG_TABLE | Error in truncating table. Only the LOG table can be truncated. | | ERR-02096 | ERR_QP_TABLE_TRUNCATE_NO_EXISTS | Error in truncating table. Table %s does not exist. | | ERR-02097 | ERR_QP_TABLE_DROP_COLUMN_LIMIT | Error in altering table. The table must have at least one column. | | ERR-02098 | ERR_QP_NOT_EQUJOIN | Error in joining tables. Only equi-join is allowed. | | ERR-02099 | ERR_QP_JOIN_OR | Error in joining tables. The OR condition for a join predicate is not allowed. | | ERR-02100 | ERR_QP_JOIN_FUNCTION_EXPR | Error in joining tables. The join predicate cannot use functions. | | ERR-02101 | ERR_QP_JOIN_PERMUTATION | Error in joining tables. Cannot join without join predicate. | | ERR-02104 | ERR_QP_COLLECTOR_NO_TEMPLATE_EXISTS | The template file (%s) does not exist. | | ERR-02105 | ERR_QP_COLLECTOR_TEMPLATE_FORMAT_INVALID | The template format (%s : %s : %d) is invalid. | | ERR-02109 | ERR_QP_JOIN_LOG_LOG | Cannot join two or more LOG tables. | | ERR-02110 | ERR_QP_KEYWD_MIN_LENGTH | Search condition argument is too short. It needs more than (%d) characters. | | ERR-02111 | ERR_QP_NO_SUCH_COMMAND | Invalid option. | | ERR-02112 | ERR_QP_NO_DISTINCT_GRBY | Cannot use DISTINCT with GROUP BY clause. | | ERR-02113 | ERR_QP_NO_DISTINCT_AGGR | Cannot use DISTINCT with aggregation function. | | ERR-02114 | ERR_QP_FUNCTION_DISTINCT | DISTINCT clause is not allowed here. | | ERR-02115 | ERR_QP_INVALID_COL_NAME | Internal column cannot be modified. | | ERR-02116 | ERR_QP_SEARCH_FILTER | Search predicate must use an index. | | ERR-02117 | ERR_QP_TABLE_NAME_INVALID | DDL on table (%s) is forbidden. | | ERR-02118 | ERR_QP_TABLE_LOCK_ALREADY_INIT | Lock object was already initialized. (Do not use select and append simultaneously in single session.) | | ERR-02119 | ERR_QP_NOT_IMPLEMENTED | This functionality has not been implemented. | | ERR-02120 | ERR_QP_SESSION_ID_INVALID | Invalid session ID (%s). | | ERR-02121 | ERR_QP_SESSION_PRIV_OF_KILL | No privileges to kill the session. | | ERR-02122 | ERR_QP_SESSION_PRIV_OF_CANCEL | No privileges to cancel the session. | | ERR-02123 | ERR_QP_NOT_EXIST_TABLE_ID_META | Table id (%lld) does not exist in meta database. | | ERR-02124 | ERR_QP_NOT_EXIST_COLUMN_ID_META | Column id (%llu) does not exist in table (%llu). | | ERR-02125 | ERR_QP_VARCHAR_TO_DATE_HEURISTIC | Error in converting string (%s) to datetime with heuristic method. Check the default date string format in this session. | | ERR-02126 | ERR_QP_NO_ORDERBY_SUBQ | ORDER BY clause is not allowed in a subquery | | ERR-02127 | ERR_QP_ORDERBY_TERMS | Only integer constants must be used for ORDER BY column position. | | ERR-02128 | ERR_QP_ORDERBY_OOR | ORDER BY column position %d is out of range - should be between 1 and %d. | | ERR-02129 | ERR_QP_GRBY_INT | GROUP BY terms must be integer constants | | ERR-02130 | ERR_QP_NO_GRBY_HAVING | A GROUP BY clause is required before HAVING | | ERR-02131 | ERR_QP_SUBQ_NOT_SINGLE | Single row error. Single-row subquery returns more than one row. | | ERR-02132 | ERR_QP_SUBQ_NOT_ALLOWED | Cannot use subquery on HAVING, ORDER BY and GROUP BY clauses. | | ERR-02133 | ERR_QP_INVALID_SUBQ | Invalid subquery. | | ERR-02134 | ERR_QP_REGEX_MAX_COUNT | Too many REGEXP in WHERE clause. No more than %d REGEXP in WHERE clause. | | ERR-02135 | ERR_QP_WHERE_TYPE | WHERE clause has to return a boolean result. | | ERR-02136 | ERR_QP_TBS_INVALID_TYPE | Invalid tablespace type. | | ERR-02137 | ERR_QP_TBS_TOO_MANY_DISKS | There are too many disks<%ud> for tablespace %s. | | ERR-02138 | ERR_QP_TBS_DISK_INVALID_PARALLEL_IO_VALUE | The PARALLEL_IO value<%d> for the disk<%s> must be higher than <%d>. | | ERR-02139 | ERR_QP_NO_MINMAX_ON_VARCHAR | MINMAX CACHE is not allowed for VARCHAR column(%s). | | ERR-02140 | ERR_QP_TABLE_NOT_SUPPORT_TABLESPACE | This type of tables do not support the tablespace functionality. | | ERR-02141 | ERR_QP_TYPE_COMPARE_NOT_APPLICABLE | Type comparison error. | | ERR-02142 | ERR_QP_NO_AGGR_LOB | Cannot use lob type in the GROUP BY clause. | | ERR-02143 | ERR_QP_NO_ORDER_LOB | Cannot use lob type in the ORDER BY clause. | | ERR-02144 | ERR_QP_OUTERJOIN_LIMIT | Outerjoin permits only 2 tables. | | ERR-02145 | ERR_QP_NOT_NUMBER_STRING | The string cannot be converted to number value.(%s) | | ERR-02146 | ERR_QP_TS_JOIN_LIMIT | Cannot join tables with timeseries function. | | ERR-02147 | ERR_QP_TS_VIEW_LIMIT | Cannot use inline view with timeseries function. | | ERR-02148 | ERR_QP_IPV6_FORMAT | Invalid IPv6 address format.(%s) | | ERR-02149 | ERR_QP_CONTAINS_TYPE_INVALID | Error in executing CONTAINS. Cannot convert from type(%d) to type(%d). | | ERR-02150 | ERR_QP_IP_NETWORK_TYPE_CLASS_MISMATCHED | Network type error. Network Mask length does not match with the column's length.(mask=%s, column=%s) | | ERR-02151 | ERR_QP_NO_MORE_DISK_FOR_EVALUATION | Error in adding disk to tablespace. You cannot use multiple disks for tablespace without valid license. | | ERR-02152 | ERR_QP_PARTITION_PROPERTY_NOT_COMPLETE | Error in setting column property. You should specify a positive value of column property PARTITION_PAGE_COUNT as well as PAGE_VALUE_COUNT. | | ERR-02153 | ERR_QP_UNKNOWN_COLUMN_PROPERTY | Invalid column property name (%s). Specify a valid property name. | | ERR-02154 | ERR_QP_SET_OP_NO_SELECT | Select set operator parsing error. | | ERR-02155 | ERR_QP_UNSURPPORTED_SET_OP | Only UNION ALL set operator is supported. | | ERR-02156 | ERR_QP_SET_OP_TARGET_MISMATCH | Set operator column types do not match at column (%d). | | ERR-02157 | ERR_QP_VALIDATE_INTERNAL | Internal error on validating query | | ERR-02158 | ERR_QP_INVALID_TYPE | Error in evaluating data type. You must specify a valid data type. | | ERR-02159 | ERR_QP_INVALID_BACKUP_RANGE | 'FROM DATETIME' must be earlier than 'TO DATETIME'. | | ERR-02160 | ERR_QP_UNMOUNT_NOT_MOUNTED_TABLE | Error in doing unmount table(%s). You can unmount only mounted tables. | | ERR-02161 | ERR_QP_NO_DDL_ON_MOUTE_MODE | Error in executing DDL. You cannot execute DDL with mounted DB. (*NOT USED*) | | ERR-02162 | ERR_QP_NO_UNMOUTE_DB | Error in doing unmount DB. You cannot umount database which is not mounted. | | ERR-02163 | ERR_QP_WRONG_RESTORE_PATH | Invalid directory path (%s). You should specify a valid path. | | ERR-02164 | ERR_QP_INVALID_ALTER_INDEX_PROPETY | Invalid index property. Property (%s) for index cannot be altered. | | ERR-02165 | ERR_QP_FUNCTION_POS | Function (%s) is not allowed here. | | ERR-02166 | ERR_QP_FUNCTION_ORDER_BY | Cannot use ORDER BY clause with aggregation function. | | ERR-02167 | ERR_QP_FUNCTION_GROUP_CONCAT_WRONG_SEPARATOR | GROUP_CONCAT function error. Separator should be a string constant. | | ERR-02168 | ERR_QP_OPERATOR_ARG_ERROR | Operator argument count or type does not match. | | ERR-02169 | ERR_QP_WRONG_COLUMN_PROPERTY_VALUE | Invalid column property value: (%s) | | ERR-02170 | ERR_QP_NO_ALIAS_IN_TABLE_INLINE_VIEW | Every specified table or inline view in FROM clause must have its own alias. | | ERR-02171 | ERR_QP_PRIMARY_KEY_DUPLICATE_PK_DECL | VOLATILE / LOOKUP / TRANSACTION table cannot have more than one primary key. | | ERR-02172 | ERR_QP_PRIMARY_KEY_INVALID_TABLE | Primary key is allowed only for VOLATILE / LOOKUP / TRANSACTION table. | | ERR-02173 | ERR_QP_VOLATILE_TABLE_INVALID_TYPE | Cannot create columns with data type (%s) in VOLATILE / LOOKUP table. | | ERR-02174 | ERR_QP_INDEX_TARGET_COLUMN_DUPLICATE | The index already exists in the column(%s). | | ERR-02175 | ERR_QP_VTABLE_UPDATE_INVALID_FORM | SET clause must be written as a list of 'column = value' expression. | | ERR-02176 | ERR_QP_VTABLE_UPDATE_TO_PRIMARY_KEY | Cannot update primary key column in SET clause. | | ERR-02177 | ERR_QP_VTABLE_UPDATE_NOT_IN_VOLATILE | ON DUPLICATE UPDATE clause is allowed only in LOOKUP / VOLATILE / TRANSACTION table. | | ERR-02178 | ERR_QP_TABLE_UPDATE_NO_COLUMN | Error in updating table. Column name (%s) does not exist in this table. | | ERR-02179 | ERR_QP_VTABLE_INSERT_WITHOUT_PRIMARY_KEY_VAL | INSERT on a %s table without primary key value cannot be proceeded. | | ERR-02180 | ERR_QP_VTABLE_UPDATE_ON_NO_PRIMARY_KEY | Primary key is mandatory for UPDATE. | | ERR-02181 | ERR_QP_INDEX_WITH_PRIMARY_KEY_PREFIX | Invalid index name starting with (%s) which is the same as primary key index. | | ERR-02182 | ERR_QP_PRIMARY_KEY_INDEX_DROP | You cannot drop the primary key index (%s). | | ERR-02183 | ERR_QP_APPEND_TO_VTABLE_UNSUPPORTED | Append mode for table (%s) is not supported. | | ERR-02184 | ERR_QP_PROPERTY_ON_INVALID_TABLE_TYPE | Specified property value is invalid in %s table. | | ERR-02185 | ERR_QP_MOUNT_DB_DUPLICATED | Invalid database name. This database name is already used for mount. | | ERR-02186 | ERR_QP_MOUNT_DB_INVALID | Invalid database name. | | ERR-02187 | ERR_QP_UNMOUNT_TABLE_IN_ACCESS | Error in unmounting database. Some tables in mounted database are accessed by other transactions | | ERR-02188 | ERR_QP_MOUNT_DB_NOT_FOUND | The database is not mounted. | | ERR-02189 | ERR_QP_DELETE_WHERE_INVALID_TABLE | Error in deleting rows. Only rows in VOLATILE / LOOKUP table can be deleted. | | ERR-02190 | ERR_QP_UPDATE_DELETE_WHERE_INVALID_CONDITION | Invalid UPDATE/DELETE condition. Specify it as (primary key column) = (value) | | ERR-02191 | ERR_QP_DELETE_WHERE_UNSUPPORTED | WHERE clause in DELETE statement is not supported yet. | | ERR-02192 | ERR_QP_KEYWORD_INDEX_TYPE | Index type for keyword index only supports keyword bitmap or keyword LSM. | | ERR-02195 | ERR_QP_BUFFER_OVERFLOW | Buffer size insufficient. | | ERR-02196 | ERR_QP_NO_FILE_TO_LOAD | Error in loading data. File (%s) does not exist. | | ERR-02197 | ERR_QP_LOAD_TABLE_ALREADY_EXISTS | Error in loading data with automatic mode. The table (%s) already exists. | | ERR-02198 | ERR_QP_LOAD_TABLE_NON_EXISTS | Error loading data. Table (%s) does not exist. | | ERR-02199 | ERR_QP_LOAD_TABLE_PARSING_ERROR | CSV parsing error on line %d: [%s]. | | ERR-02200 | ERR_QP_LOAD_TABLE_DELIMITOR_ERROR | [%s] is not a valid string terminator or enclosure. | | ERR-02201 | ERR_QP_LOAD_TABLE_UNKNOWN_AUTOMODE | The automatic loading mode is invalid. | | ERR-02202 | ERR_QP_LOAD_TABLE_HEADER_DETECT_ERROR | Automatic column detection failed because the data is empty or the headers are invalid. | | ERR-02203 | ERR_QP_LOAD_TABLE_UNKNOWN_ENCODINGMODE | Invalid encoding. | | ERR-02204 | ERR_QP_LOAD_TABLE_CHAR_CONVERSION_ERROR | Failed to convert %s to UTF8. | | ERR-02205 | ERR_QP_NO_SUPPORT_DOUBLE_MOD | A modulo operator can be applied only for integer types. | | ERR-02206 | ERR_QP_NO_SUPPORT_TBS_NON_AUTO | Tablespace name cannot be specified in non automode | | ERR-02207 | ERR_QP_SAVE_FILE_ALREADY_EXISTS | Error in saving table into file (%s). File already exists. | | ERR-02208 | ERR_QP_EXPR_TYPE | Expression argument type does not match. | | ERR-02221 | ERR_QP_NO_MANAGER_NAME_SETTED | Manager name is not specified. | | ERR-02222 | ERR_QP_RECEIVE_DIFF_PROTOCOL | Error in read protocol. Send %s protocol, but received %d protocol. | | ERR-02223 | ERR_QP_COLLECTORMANAGER_CONNECT | Unable to establish connection with collectormanager (%s). | | ERR-02224 | ERR_QP_NO_COLLECTOR_NAME_SETTED | Manager name is not specified. | | ERR-02225 | ERR_QP_SET_COLUMN_UNIT_ERROR | Invalid set column unit. | | ERR-02226 | ERR_QP_INVALID_CHARACTER | Invalid character ('%c'). | | ERR-02228 | ERR_QP_UNSUPPORT_PROCEDURE | Invalid procedure (%s). | | ERR-02229 | ERR_QP_INVALID_ARG_VALUE | Invalid argument value for function (%s). | | ERR-02230 | ERR_QP_PROCEDURE_WRONG_NUMBER_OF_ARGUMENTS | Wrong number of arguments in call to '%s'. | | ERR-02231 | ERR_QP_STRCPY_ERROR | strcpy function error (%d). | | ERR-02232 | ERR_QP_CALC_TYPE | Calculation argument type (%s), (%s) error. | | ERR-02233 | ERR_QP_INSERT_VALUE_LOCATION | Error occurred at column (%u): (%s) | | ERR-02234 | ERR_QP_SET_OP_COUNT | Set operator column counts do not match (%d and %d). | | ERR-02235 | ERR_QP_SERIES_BY | SERIES BY clause is not allowed here. | | ERR-02236 | ERR_QP_TOO_MANY_TABLES_IN_JOIN | For a table list in FROM clause, The number of tables should be less than 32. | | ERR-02237 | ERR_QP_INDEX_NOT_CREATED_ON_TABLE | The index <%s> is not an index for the table <%s>. | | ERR-02238 | ERR_QP_NO_JOIN_TYPE | This type of join is not allowed. | | ERR-02239 | ERR_QP_INVALID_USE_AGGR_FUNC | Invalid use of aggregation function. | | ERR-02240 | ERR_QP_INVALID_COLUMN_TYPE_FOR_FETCH | Cannot fetch column with type (%s). | | ERR-02241 | ERR_QP_UNSUPPORTED_JOIN_TABLES | Join between LOG table and fixed table is not supported in Cluster Edition. | | ERR-02242 | ERR_QP_EQUIJOIN_WITH_LOGTABLE_JOIN | Only equality predicates are supported when joining LOG tables in Cluster Edition. | | ERR-02243 | ERR_QP_UNSUPPORTED_ROW_BASED_DELETE | DELETE statement with the number of rows is not supported in Cluster Edition. | | ERR-02246 | ERR_QP_IDENTIFIER_TOO_LONG | Identifier %.*s is too long. | | ERR-02247 | ERR_QP_DATETIME_NOT_PROPER | DATETIME earlier than 1970-01-01 00:00:00 (UTC) is not valid. | | ERR-02248 | ERR_QP_INSUFFICIENT_COLUMN_DEF | Insufficient column definitions. | | ERR-02249 | ERR_QP_TABLE_DELETE_INVALID_COND | Invalid DELETE condition. | | ERR-02250 | ERR_QP_TAGDATA_COMPONENT_DDL_BLOCKED | You cannot execute DDL on compoment table/index of TAGDATA table explictly. | | ERR-02251 | ERR_QP_TAGDATA_DUPLICATE_FLAG | You cannot define columns with duplicate flag (%s) in TAGDATA table. | | ERR-02252 | ERR_QP_TAGDATA_INVALID_TYPE_FOR_FLAG | Invalid column type (%s) for flag (%s) in TAGDATA table. | | ERR-02253 | ERR_QP_TAGDATA_INSUFFICIENT_MANDATORY | Mandatory column definition (PRIMARY KEY / BASE TIME) is missing. | | ERR-02254 | ERR_QP_INVALID_TAGDATA_FLAG_ON_OTHER_TABLE | Column flag (%s) is only allowed for TAG table. | | ERR-02255 | ERR_QP_TAGDATA_INSERT_META_NO_PK | Primary key of TAGDATA table is not defined in metadata. | | ERR-02256 | ERR_QP_TAGDATA_INVALID_META_COLUMN_CLAUSE | Metadata column definition is allowed only in TAGDATA table. | | ERR-02257 | ERR_QP_TAGDATA_INSERT_META_INVALID_TYPE | Metadata insertion is allowed only in TAGDATA table. | | ERR-02258 | ERR_QP_TAGDATA_ALREADY_INSERTED | Metadata key (%.*s) for the TAG table has already been inserted. | | ERR-02259 | ERR_QP_TAGDATA_NOT_FOUND | Metadata of TAGDATA table is not found. (Key = %s) | | ERR-02260 | ERR_QP_TAGDATA_ALLOC_FAILURE | Failed to allocate new metadata of TAGDATA table (Current Size=%llu). | | ERR-02261 | ERR_QP_NO_TAGDATA_METADATA_INSERT_UPDATE | You cannot insert metadata into TAGDATA table with ON DUPLICATE KEY UPDATE clause. | | ERR-02262 | ERR_QP_TAGDATA_DIRECT_DML_BLOCKED | Direct DML on component tables of TAGDATA table is not allowed. | | ERR-02263 | ERR_QP_TAGDATA_MORE_TAGDATA_TABLE | You can create only one TAGDATA table. | | ERR-02264 | ERR_QP_TAGDATA_SCAN_OTHER_COLUMN_IN_ROLLUP | Cannot read a column (%s) in ROLLUP query because it is not a ROLLUP column. | | ERR-02265 | ERR_QP_TAGDATA_SCAN_WITHOUT_KEY_CONDITION | Reading TAGDATA table without primary key condition is not allowed. | | ERR-02266 | ERR_QP_TAGDATA_DELETE_RAW_CONDITION | You cannot delete raw data of TAGDATA table with WHERE condition. | | ERR-02267 | ERR_QP_TAGDATA_UNSUPPORTED_KEY_PREDICATE | Primary key in TAGDATA table should be compared by '=' or 'IN' operation. | | ERR-02268 | ERR_QP_TAGDATA_COMPARE_KEY_ONLY_CONSTANT | Primary key in TAGDATA table should be compared with constant value. | | ERR-02269 | ERR_QP_TAGDATA_OUTERJOIN | Outerjoin on TAGDATA table is not allowed. | | ERR-02270 | ERR_QP_TAGDATA_NAME_VIOLATION | TAGDATA table's name should be 'TAG'. | | ERR-02271 | ERR_QP_TAGDATA_NOT_CONSTANT_PK_VALUE | You must insert key value of TAGDATA table as constant. | | ERR-02272 | ERR_QP_NOT_EXIST_INDEX_ID_META | Index id (%llu) does not exist in meta database. | | ERR-02273 | ERR_QP_TAGDATA_USER_NO_PRIV_DDL | The user does not have privileges on TAGDATA DDL. | | ERR-02274 | ERR_QP_TAGDATA_FREE_FAILURE | Failed to free new metadata of TAGDATA table. | | ERR-02275 | ERR_QP_TAGDATA_INSERT_SELECT_IN_EE | The INSERT SELECT statement to the TAGDATA table is not allowed in enterprise edition. | | ERR-02276 | ERR_QP_TAGDATA_COMPONENT_EXISTS | Component table (%s) of TAGDATA table already exists. | | ERR-02277 | ERR_QP_TAGDATA_COMPONENT_NAME_RESERVED | Table or index name that starts with '_TAG' is reserved. | | ERR-02278 | ERR_QP_UPDATE_INVALID_TABLE_TYPE | UPDATE statement is not allowed for %s. | | ERR-02279 | ERR_QP_TAGDATA_INVALID_PRIMARY_NAME | Invalid tag name insertion to TAGDATA table (name = '%s'). | | ERR-02280 | ERR_QP_TAGDATA_INVALID_BIND_TAGNAME | Invalid tag name insertion due to wrong bind variable. | | ERR-02281 | ERR_QP_DURATION_NOT_APPLICABLE | DURATION clause is not applicable on %s. | | ERR-02282 | ERR_QP_DELETE_ALREADY_DOING | The DELETE statement for table '%s' is already been executed. | | ERR-02283 | ERR_QP_TAGDATA_IN_SUBQUERY_NOT_ALLOWED | IN subquery on TAGDATA table is not allowed. | | ERR-02284 | ERR_QP_INTERNAL_NULL_EXIST | Internal NULL value exists in the condition expression. | | ERR-02285 | ERR_QP_INTERNAL_ERROR | Internal error: %s. | | ERR-02286 | ERR_QP_KV_TABLE_MEMORY_ALLOC | Memory allocation failed while creating TAGDATA table. You may need to decrease TAG_DATA_PART_SIZE in machbase.conf. | | ERR-02287 | ERR_QP_TAGDATA_NAME_TRUNCATED | TAGDATA name value (%s) is too long. | | ERR-02288 | ERR_QP_AGGR_EXPECTED | Aggregate function is expected at (%.*s). | | ERR-02289 | ERR_QP_NON_CONST | Non-constant expression is not allowed for PIVOT values. | | ERR-02290 | ERR_QP_CANNOT_ALTER | %s cannot be altered. | | ERR-02291 | ERR_QP_INVALID_TABLE_NAME_TAG | Table name 'TAG' must be used for TAGDATA table. | | ERR-02292 | ERR_QP_TAGDATA_INVALID_CONSTRAINT_ORDER | The order of columns in TAGDATA table must be (PRIMARY, BASE TIME, SUMMARIZED, other columns, .. ). | | ERR-02293 | ERR_QP_NO_BIND_PARAM_COLUMN | Column meta for bind param[%d] is not available. | | ERR-02294 | ERR_QP_TAGDATA_JOIN | Joining more than one TAGDATA table is not supported. | | ERR-02295 | ERR_QP_INVALID_ORDINAL_NUMBER | Invalid ordinal number ID_COLUMN (%lld) and TIME_COLUMN (%lld). | | ERR-02296 | ERR_QP_INTERPOLATION_ONE_BETWEEN | Interpolation requires only one BETWEEN expression. | | ERR-02297 | ERR_QP_BETWEEN_HAS_INVALID_EXPR | BETWEEN has invalid expression (%s). | | ERR-02298 | ERR_QP_NOT_FACTOR_OF_INTERPOLATION_INTERVAL | FREQUENCE must be a factor of INTERPOLATION_INTERVAL (%lld). | | ERR-02299 | ERR_QP_ONLY_BETWEEN_SUPPORTED | Only BETWEEN condition is supported. | | ERR-02300 | ERR_QP_INSUFFICIENT_COLUMN_FOR_INTERPOLATION | Interpolation column is missing. (%s) | | ERR-02301 | ERR_QP_INSUFFICIENT_PROPERTIES_FOR_INTERPOLATION | Some properties are missing for interpolation. | | ERR-02302 | ERR_QP_INVALID_INTERVAL_INTERPOLATION_PROPERTY | Invalid interpolation interval property: %lld. | | ERR-02303 | ERR_QP_INVALID_ROLLUP_UNIT | You must use higher ROLLUP unit. | | ERR-02304 | ERR_QP_INTERPOLATION_VIEW_LIMIT | Interpolation is not applicable on (%s). | | ERR-02305 | ERR_QP_INTERPOLATION_ONE_TARGET | JOIN is not applicable for interpolation. | | ERR-02306 | ERR_QP_CHEKPOINT_INVALID_SIZE | Interpolation interval value(%lld) should be less than checkpoint interval value(%lld). | | ERR-02307 | ERR_QP_ROLLUPUNIT_INTERVALVALUE | Interpolation interval value(%lld) should be less than ROLLUP unit (%s). | | ERR-02308 | ERR_QP_ROLLUPUNIT_CHECKPOINTVALUE | Checkpoint interval value(%lld) should be less than ROLLUP unit (%s). | | ERR-02309 | ERR_QP_INVALID_INTERPOLATION_DIVIDE | Checkpoint interval value(%lld) should be divide by interpolation value(%lld). | | ERR-02310 | ERR_QP_INVALID_CHECKPOINT_INTERPOLATION_PROPERTY | Invalid interpolation checkpoint property: %lld. | | ERR-02311 | ERR_QP_INVALID_KEYWORD_INTERPOLATION | %s cannot be used in interpolation query. | | ERR-02312 | ERR_QP_NOT_INTERPOLATION_TABLE | Rollup delete can only be done on the Interpolation Tag table. | | ERR-02313 | ERR_QP_ROLLUP_REBUILD_RANGE_ERROR | Unable to execute ROLLUP DELETE with the given range. | | ERR-02314 | ERR_QP_TAG_UNSUPPORT_DURATION_BACKUP | Regular duration backup does not support a backup of the TAG table (Try incremental backup which permits the action on the TAG table). | | ERR-02315 | ERR_QP_FOG_SNAPSHOT_NOT_SUPPORTED | Snapshot is not supported. | | ERR-02316 | ERR_QP_INVALID_EXPR_IN_DURATION | Invalid expression in DURATION clause: %.*s | | ERR-02317 | ERR_QP_FUNCTION_EXECUTION | Function execution failed: %s | | ERR-02318 | ERR_QP_LOOKUP_NODE_CONNECT_FAIL | Cannot connect to the lookup node. | | ERR-02319 | ERR_QP_LOOKUP_NODE_ERROR | Error on Lookup Node | | ERR-02320 | ERR_QP_LOOKUP_NODE_PENDING | Lookup Node is not ready | | ERR-02321 | ERR_QP_LOOKUP_NODE_NIL | No data was found in the lookup node. | | ERR-02322 | ERR_QP_LOOKUP_TABLE_MISSING_PRIMARY_KEY | Mandatory column definition (PRIMARY KEY) is missing. | | ERR-02323 | ERR_QP_EXEC_FUNCTION_NOT_SUPPORTED_TABLE_TYPE | EXEC %s is not supported for %s table type. | | ERR-02324 | ERR_QP_USED_TAG_ID_DATA | Cannot delete tagmeta. there exist data with deleted_tag key. | | ERR-02325 | ERR_QP_INTEGER_OVERFLOW | Integer %s type overflow. | | ERR-02326 | ERR_QP_EDGE_BACKUP_MOUNT_NOT_SUPPORTED | Backup/Mount is not supported. | | ERR-02327 | ERR_QP_PIVOT_IN_ROLLUP_NOT_SUPPORTED | Pivot is not supported in rollup query. | | ERR-02328 | ERR_QP_TAGMETA_INSERT_COUNT_EXCEEDED | Cannot insert a new tag since the number of tags has exceeded MAX_TAG_COUNT(%lld). | | ERR-02329 | ERR_QP_TAGMETA_INSERT_COUNT_EXCEEDED_LIMIT | Cannot insert a new tag since the number of tags has exceeded TAG_COUNT_LIMIT(%lld). | | ERR-02330 | ERR_QP_KV_INSUFFICIENT_MANDATORY | Mandatory column definition (ULONG / DATETIME) is missing. | | ERR-02331 | ERR_QP_RANGE_EXPR | RANGE expression is not applicable on the table (%s). | | ERR-02332 | ERR_QP_UNABLE_CREATE_INDEX_ON_COLUMN | Unable to create an index on the column (%s). | | ERR-02333 | ERR_QP_KV_TABLE_PREDICATE_MAX_OVER | Column (%s) cannot exceed %d. | | ERR-02334 | ERR_QP_TAG_INDEX_NOT_YET_SUPPORTED | Tag Index is not yet supported. | | ERR-02335 | ERR_QP_FAILED_TO_DELETE_ALL | Failed to delete all on this table. It is recommended to use EXEC TABLE_REFRESH(%s). | | ERR-02336 | ERR_QP_CASCADE_ONLY_TAG_TABLE | CASCADE option is not applicable on %s. | | ERR-02337 | ERR_QP_TAGMETA_DUPLICATE_FLAG | Unable to define more than one column attribute (%s). | | ERR-02339 | ERR_QP_TAGMETA_DIFFERENT_SUMMARY_TYPE | The type of %s column (%s) is different from that of VALUE column (%s). | | ERR-02340 | ERR_QP_TAGMETA_NOT_FOUND_SUMMARY_VALUE | SUMMARIZED column does not exist for %s. | | ERR-02341 | ERR_QP_SUMMARY_GREATER_THAN_USL | SUMMARIZED value is greater than UPPER LIMIT. | | ERR-02342 | ERR_QP_SUMMARY_LESS_THAN_LSL | SUMMARIZED value is less than LOWER LIMIT. | | ERR-02343 | ERR_QP_LSL_GREATER_THAN_USL | LOWER LIMIT must not be greater than UPPER LIMIT. | | ERR-02344 | ERR_QP_NOT_NUMERIC_TYPE | Not numeric type. (%s) | | ERR-02345 | ERR_QP_INVALID_TAGMETA_FLAG_ON_OTHER_TABLE | Column flag (%s) is only allowed for TAGMETA table. | | ERR-02346 | ERR_QP_DEFAULT_ONLY_FOR_TYPE_DATETIME | Column type (%s) is not allowed for default value. | | ERR-02347 | ERR_QP_DEFAULT_ONLY_FOR_FLAG_SYSDATE | SYSDATE is only allowed for default value. | | ERR-02348 | ERR_QP_ALTER_SET_PROP_NOT_SUPPORT_ON_CLUSTER | Alter table set %s not support on cluster. | | ERR-02349 | ERR_QP_BIND_VARIABLE_NOT_SUPPORTED_NEW_TAG | Bind variable is not supported for new tag. | | ERR-02350 | ERR_QP_WINDOW_FUNCTION_OVER_EXISTS | The function (%s) requires OVER clause. | | ERR-02351 | ERR_QP_NO_WINDOW_CONTEXT | Window function is allowed only in SELECT list. | | ERR-02352 | ERR_QP_FUNCTION_OVER | OVER clause is not applicable on (%s). | | ERR-02353 | ERR_QP_OVER_INVALID_TYPE | Invalid data type (%s) in OVER clause. | | ERR-02354 | ERR_QP_OVER_CONSTANT | Constant is not allowed in OVER clause. | | ERR-02355 | ERR_QP_TYPE_UNSUPPORTED | Type (%s) is not supported. | | ERR-02356 | ERR_QP_FIRST_DAY_OF_THE_MONTH | Origin must be the first day of the month. | | ERR-02357 | ERR_QP_JOIN_NOT_APPLICABLE | JOIN is not applicable on the table (%s). | | ERR-02358 | ERR_QP_INVALID_METADATA_ALTER_TABLE | When altering a table, the METADATA keyword is only applied to the tag table. | | ERR-02359 | ERR_QP_TAG_TABLE_ONLY_META_CHANGE | Tag table (%s) can only be modified in the metadata area. | | ERR-02360 | ERR_QP_WINDOW_FUNCTION_NOT_ALLOWED | Window function is not allowed with %s. | | ERR-02361 | ERR_QP_TABLE_STRUCTURE_MODIFIED | Table (%d) structure was modified. | | ERR-02362 | ERR_QP_STATEMENT_NOT_SUPPORTED | This statement is not supported. | | ERR-02600 | ERR_QP_WRONG_SEQUENCE_TABLE_TYPE | SEQUENCE property is not applicable in the table. | | ERR-02601 | ERR_QP_INVALID_FUNCTION_IN_SEQUENCE_COLUMN | Invalid function in a SEQUENCE column. NEXTVAL must be used. | | ERR-02602 | ERR_QP_INVALID_NEXTVAL_FUNCTION_QUERY | NEXTVAL is applicable only in INSERT statement. | | ERR-02603 | ERR_QP_INVALID_COLUMN_NEXTVAL | NEXTVAL is applicable only in SEQUENCE columns. | | ERR-02604 | ERR_QP_INVALID_SEQUENCE_COLUMN_DATA_TYPE | Sequence column must be LONG type. | | ERR-02651 | ERR_QP_EXIST_DEPENDENT_ROLLUP_TABLE | Dependent ROLLUP (%s) exists. | | ERR-02652 | ERR_QP_NOT_ROLLUP_TABLE | Not a ROLLUP table. (%s) | | ERR-02653 | ERR_QP_ROLLUP_INTERVAL_GREATER_THAN_SRC_ROLLUP | Rollup interval must be greater than source rollup interval. | | ERR-02654 | ERR_QP_ROLLUP_NOT_FOUND | ROLLUP (%s) is not found. | | ERR-02655 | ERR_QP_ROLLUP_INTERVAL_DIVIDE_REMAINDER_ZERO | Rollup interval source rollup interval Must Divide Zero. | | ERR-02656 | ERR_QP_ROLLUP_INTERVAL_POSITIVE_INTEGER | Rollup interval must positive integer. | | ERR-02657 | ERR_QP_ROLLUP_INTERVAL_SMALLER_THAN_YEAR | Rollup interval must be smaller than year. | | ERR-02658 | ERR_QP_ROLLUP_NOT_ENABLE | ROLLUP is not enabled for %s. | | ERR-02659 | ERR_QP_ROLLUP_MAX_COUNT | Rollup maximum count is 100. | | ERR-02670 | ERR_QP_ROLLUP_SOURCE_USERID | Rollup user ID(%d) is not equal to Source user ID(%d) | | ERR-02671 | ERR_QP_ROLLUP_COLUMN_INVALID_TYPE | Invalid type for ROLLUP column (%s). | | ERR-02672 | ERR_QP_ROLLUP_JSON_PATH_NOT_EXISTS | Json path is not specified on %s. | | ERR-02673 | ERR_QP_ROLLUP_JSON_PATH_EXISTS | Json path is not applicable on %s. | | ERR-02674 | ERR_QP_ROLLUP_NOT_FOUND_COLUMN | ROLLUP query must have a target column. | | ERR-02675 | ERR_QP_CAN_SCAN_ONE_ROLLUP_COLUMN | Cannot use more than one ROLLUP column in a ROLLUP query. | | ERR-02676 | ERR_QP_NOT_TAG_TABLE | Not a TAG table. | | ERR-02677 | ERR_QP_INVALID_ROLLUP_TIME_UNIT | Invalid rollup time unit (%s). | | ERR-02678 | ERR_QP_NEED_SUMMARIZED_COLUMN | WITH ROLLUP requires a SUMMARIZED column. | | ERR-02679 | ERR_QP_AUTO_GENERATE_ROLLUP_FAIL | Failed to create ROLLUP by WITH ROLLUP option. | | ERR-02680 | ERR_QP_PROCESS_ALREADY_START | PROCESS %s (%s) is already started. | | ERR-02681 | ERR_QP_PROCESS_ALREADY_STOP | PROCESS %s (%s) is already stopped. | | ERR-02682 | ERR_QP_ROLLUP_EXT_TYPE_DIFFER | ROLLUP extension type is different. | | ERR-02683 | ERR_QP_TAGDATA_SCAN_OTHER_TIME_COLUMN_IN_ROLLUP | Cannot read a column (%s) in ROLLUP query because it is not a ROLLUP time column. | | ERR-02684 | ERR_QP_NOT_EXIST_DEPENDENT_ROLLUP_TABLE | Dependent ROLLUP table does not exist. | | ERR-02685 | ERR_QP_NO_APPLICABLE_ROLLUP_TABLE | There are no applicable ROLLUP tables. | | ERR-02686 | ERR_QP_RENAME_NO_APPLICABLE_ROLLUP_TABLE | The names of column(%s) associated with ROLLUP cannot be changed. | | ERR-02687 | ERR_QP_ROLLUP_WAKEUP_INTERVAL_SMALLER_THAN_SRC_ROLLUP | Rollup wakeup interval must be same or smaller than rollup interval. | | ERR-02688 | ERR_QP_ROLLUP_WAKEUP_INTERVAL_DIVIDE_REMAINDER_ZERO | Rollup wakeup interval must exactly divide the rollup interval. | | ERR-02689 | ERR_QP_CUSTOM_ROLLUP_FROM_ALIAS_NOT_ALLOWED | Cannot use alias in custom ROLLUP SELECT FROM clause. | | ERR-02690 | ERR_QP_CUSTOM_ROLLUP_OWNER_MISMATCH | Custom ROLLUP source and destination table owners must be same. (source:%s, destination:%s) | | ERR-02691 | ERR_QP_INDEX_TABLE_OWNER_MISMATCH | Index owner and table owner must be same. (index owner:%s, table owner:%s) | | ERR-02692 | ERR_QP_CIRCULAR_VIEW_DEFINITION | Circular view definition is not allowed: (%s). | | ERR-02700 | ERR_QP_DUPLICATE_RETENTION | Policy (%s) already exists. | | ERR-02701 | ERR_QP_NOT_EXISTS_RETENTION | Policy (%s) does not exist. | | ERR-02702 | ERR_QP_EXIST_DEPENDENT_RETENTION_TABLE | Policy (%s) is in use. | | ERR-02703 | ERR_QP_NOT_EXISTS_RETENTIONJOB | Table (%s) has no retention policy. | | ERR-02704 | ERR_QP_DUPLICATE_RETENTIONJOB | Table (%s) already has a retention policy. | | ERR-02705 | ERR_QP_RETENTION_DURATION_RANGE | Retention duration must be longer than 1 day. | | ERR-02706 | ERR_QP_RETENTION_INTERVAL_RANGE | Retention interval must be longer than 1 hour. | | ERR-02707 | ERR_QP_RETENTION_TABLE_TYPE | Retention is not applicable on the table (%s). | | ERR-02708 | ERR_QP_RETENTION_PRIVILEGE | Only SYS user can create or drop RETENTION. | | ERR-02813 | ERR_QP_INVALID_ROLLUP_EXPR | Invalid ROLLUP expression. (Token = %s, Unit = %ld) | | ERR-02814 | ERR_QP_INVALID_ROLLUP_TARGET | Invalid ROLLUP target. BASETIME column of TAGDATA table is the only target. | | ERR-02815 | ERR_QP_DIFFERENT_ROLLUP_EXPR | Different ROLLUP expressions are used in a single SELECT query. | | ERR-02816 | ERR_QP_INVALID_USE_IN_ROLLUP | Only rollup column with aggregate function can be referenced in ROLLUP SELECT query. | | ERR-02817 | ERR_QP_INVALID_ROLLUP_NOT_SELECT | ROLLUP expression must be used in SELECT query. | | ERR-02818 | ERR_QP_UNSUPPORT_ROLLUP_TARGET | Invalid ROLLUP target (%s). | | ERR-02819 | ERR_QP_ROLLUP_RUNNING | ROLLUP thread is running. | | ERR-02820 | ERR_QP_ROLLUP_NOT_RUNNING | ROLLUP thread is not running. | | ERR-02821 | ERR_QP_OPERATION_IN_PROGRESS | Another DDL/DELETE/SNAPSHOT is in progress. | | ERR-02822 | ERR_QP_INVALID_EXPRESSION_IN_ROLLUP_QUERY | Invalid expression in ROLLUP query : %.*s | | ERR-02823 | ERR_QP_ROLLUP_SELECT_FROM | Invalid table in ROLLUP query: %s | | ERR-02824 | ERR_QP_CUSTOM_ROLLUP_FIRST_COLUMN_NOT_TAGNAME | In custom ROLLUP SELECT, first column must be TAG key column (%s). | | ERR-02825 | ERR_QP_INVALID_EXTENDED_COLUMN_ROLLUP_QUERY | Extended column(%s) cannot be used in ROLLUP query. | | ERR-02826 | ERR_QP_CANT_REVOKE | User (%s) can't revoke from table (%s.%s). | | ERR-02827 | ERR_QP_USER_NO_GRANT_PRIV | User does not have grant privileges. | | ERR-02828 | ERR_QP_USER_NO_REVOKE_PRIV | User does not have revoke privileges. | | ERR-02829 | ERR_QP_USER_ONLY_SYS_CAN_DO_CREATE_DROP | Only SYS user can create or drop user. | | ERR-02830 | ERR_QP_USER_NO_PRIV_TABLE_FOR_EACH_CASE | The user does not have (%s) privilege on table(%s.%s). | | ERR-02831 | ERR_QP_USER_NO_GRANT_UPDATE_PRIV_FOR_LOG_TABLE | You can't grant UPDATE privilege on Log Table. | | ERR-02832 | ERR_QP_USER_NO_REVOKE_UPDATE_PRIV_FOR_LOG_TABLE | You can't revoke UPDATE privilege on Log Table. | | ERR-02833 | ERR_QP_USER_SELECT_ONLY_FOR_MOUNT_TABLE | You can only grant SELECT privileges on Mounted database. | | ERR-02834 | ERR_QP_PASSWORD_REUSED | Cannot use new password as previously used. | | ERR-02835 | ERR_QP_USER_NO_PRIV_DATABASE_FOR_EACH_CASE | The user does not have (%s) privilege on database(%s). | | ERR-02837 | ERR_QP_CUSTOM_ROLLUP_NOT_SUPPORTED_IN_CLUSTER | Custom rollup is not supported in cluster edition. | | ERR-02838 | ERR_QP_USER_NO_MOUNT_PRIV | The user(%s) does not have mount privileges. | | ERR-02839 | ERR_QP_DATABASE_NOT_FOUND | Database (%s) does not exist. | | ERR-02840 | ERR_QP_DATABASE_NOT_ACTIVE | Database (%s) is not an active database. | | ERR-02841 | ERR_QP_DATABASE_USE_IN_TRANSACTION | Cannot change the current database while a transaction is active. | | ERR-02842 | ERR_QP_DATABASE_ALREADY_EXISTS | Database (%s) already exists. | | ERR-02843 | ERR_QP_DATABASE_SELF_DROP | Cannot drop current database (%s). | | ERR-02844 | ERR_QP_DATABASE_DEFAULT_DROP | Default database (%s) cannot be dropped. | | ERR-02845 | ERR_QP_DATABASE_READ_ONLY | Database (%s) is read only. | | ERR-02846 | ERR_QP_DATABASE_RESERVED_NAME | Database name (%s) is reserved and cannot be used. | | ERR-02847 | ERR_QP_PREPARED_CATALOG_CHANGED | Prepared statement target database (%s) changed. | ### `ERR-03000`–`ERR-03999` (65) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-03000 | MMP_STMT_OVERFLOWS | Statement ID overflow (Limit = %u, Curr = %u). | | ERR-03001 | MMP_STMT_QUERY_ZERO | Statement query length is zero. | | ERR-03002 | MMT_TASK_POOL_INITIALIZE_ERROR | Task pool initialization error. | | ERR-03003 | MMS_STMT_POOL_INITIALIZE_ERROR | Statement pool initialization error. | | ERR-03004 | MMT_QUEUE_CREATE_ERROR | Queue creation error. | | ERR-03005 | MMS_STMT_ALLOC_ERROR | Statement allocation error. | | ERR-03006 | MMP_META_UNKNOWN_TYPE_ERROR | Unknown meta type error (typecode is %u). Internal error. | | ERR-03007 | MMP_PROTOCOL_BUFFER_INSUFFICIENT | Insufficient protocol buffer size. Increase it. | | ERR-03008 | MMP_PROTOCOL_STATE_INVALID | Invalid protocol state. Check your application again. (Protocol = %s, State = %s) | | ERR-03009 | MMP_EXECUTE_PROTOCOL_DATA_INVALID | Invalid execute protocol data (%s). | | ERR-03010 | MMS_FETCH_PROTOCOL_INSUFFICIENT | Error in fetch protocol: not enough buffer size to execute it. Increase the size. | | ERR-03011 | MMP_SEND_ERROR | Send error. | | ERR-03012 | MMP_MEMORY_ALLOC_ERROR | Memory allocation error. | | ERR-03013 | MMP_STMT_APPEND_TABLE_ZERO | Invalid table name for append table. Table name is omitted. | | ERR-03014 | MMP_APPEND_PROTOCOL_DATA_INVALID | Invalid append protocol data (%s). | | ERR-03015 | MMP_STMT_APPEND_NO_ENDIAN | Endian is not specified for append. Check endian information. | | ERR-03016 | MMP_STMT_APPEND_MAX_COLUMN | Too many columns are specified for append. Cannot append more than %d columns | | ERR-03017 | MMP_STMT_APPEND_MAX_RECORD_SIZE | Too large record size for append. Cannot append more than %d bytes per record. | | ERR-03018 | MMP_STMT_APPEND_MAX_BLOCK_SIZE | The specified maximum block size (%d) was exceeded. Check the application's append data structure. | | ERR-03019 | MMP_STMT_EXPLAIN_PLAN_ERROR | Explain plan error. Use it for SELECT statement only. | | ERR-03020 | MMP_STMT_EXPLAIN_ONLY_DIRECT_EXECUTE | Explain plan is not allowed in prepared mode. | | ERR-03021 | MMP_CONNECT_VERSION_MISMATCHED | Protocol versions do not match: server (%d.%d.%d), client (%d.%d.%d). | | ERR-03022 | MMP_OS_GET_HANDLE_LIMIT_ERROR | Failed to get handle limit from the system. | | ERR-03023 | MMP_OS_CHECK_HANDLE_LIMIT_ERROR | Handle limit(%d) from the system is less than that of property(%d). Tune system handle limit or decrease the property 'HANDLE_LIMIT' | | ERR-03024 | ERR_MM_SESSION_ID_NOT_FOUND | Invalid session ID (%llu). | | ERR-03025 | ERR_MM_SESSION_SELF_OP_ERROR | Not enough privileges to manipulate the session. (%llu) | | ERR-03026 | ERR_MM_SESSION_DIFF_USER_CANCEL | You should log in with the same user name in the target session. Now (%d) Target(%d) | | ERR-03027 | ERR_MM_SESSION_CANCELLED | This statement has been canceled. | | ERR-03028 | ERR_MM_NO_SESSION_PROPETY | Invalid session property name. Name (%s) does not exist. | | ERR-03029 | ERR_MM_SESSION_PROPETY_CONVERT | Error in converting session property (%s). Cannot convert string (%s) to integer. | | ERR-03030 | ERR_MM_SESSION_PROPETY_VALUE_RANGE | Invalid session property value. Check the session value (%s) | | ERR-03031 | ERR_MM_PROTOCOL_BROKEN | Protocol error. | | ERR-03032 | ERR_MM_LICENSE_NO_META | Error in getting license meta. Check DB image and binary. | | ERR-03033 | ERR_MM_LICENSE_OPEN_META | Error in opening meta. | | ERR-03034 | ERR_MM_LICENSE_EXEC_META | Error in executing meta. | | ERR-03035 | ERR_MM_LICENSE_CLOSE_META | Error in closing meta. | | ERR-03036 | ERR_MM_LICENSE_EXPIRED | The license is expired(%s). | | ERR-03037 | ERR_MM_LICENSE_INVALID | The license is invalid or the license file does not exist(%s). | | ERR-03038 | ERR_MM_LICENSE_VIOLATION | License violation detected (%s). contact sales@machbase.com | | ERR-03039 | ERR_MM_SESSION_COUNT_EXCEED | Session count exceeded the maximum (%llu). | | ERR-03040 | ERR_MM_SHUTDOWN_FAIL | Unable to shutdown since the server is busy. | | ERR-03041 | ERR_MM_APPEND_BATCH | AppendBatch error: %s. | | ERR-03042 | ERR_MM_RECOVERY_BEGUN | Recovery in progress. | | ERR-03043 | ERR_MM_EXECARRAY_NOT_FOR_SELECT | Array Execute is not applicable for SELECT query. | | ERR-03044 | MMP_CONNECT_WRONG_TIMEZONE | Invalid TIMEZONE string: %s. | | ERR-03045 | ERR_MM_INVALID_CONTEXT | Invalid context at %s. | | ERR-03046 | ERR_MM_CM_ERROR | Communication module error (rc=%d): [%s]. | | ERR-03047 | ERR_MM_FUNCTION | Failed to call function %s (rc=%d) | | ERR-03048 | ERR_MM_PREPARED_STMT_USER_CHANGED | Prepared statement cannot be used after CONNECT USER. | | ERR-03200 | ERR_MM_SERVER_NOT_RUNNING | Server is not running. | | ERR-03201 | ERR_MM_INVALID_STMT_STATE | Invalid statement state: (%d) | | ERR-03202 | ERR_MM_COLUMN_RANGE | Column index is out of range. | | ERR-03203 | ERR_MM_BUFFER_SIZE_EXCEEDED | The data length exceeded the buffer size. | | ERR-03204 | ERR_MM_APPEND_PARAM_IP_STRING_NULL | Append data ip string is null. | | ERR-03205 | ERR_MM_APPEND_PARAM_DATETIME_STRING_NULL | Append data datetime string(%s) is null. | | ERR-03206 | ERR_MM_INVALID_COLUMN_TYPE | Invalid column type (%d). | | ERR-03207 | ERR_MM_INVALID_STMT_TYPE | Invalid statement type (%d). | | ERR-03208 | ERR_MM_SERVER_THREAD_ERR | Server thread error: %d - %s | | ERR-03209 | ERR_MM_BUSY_STMT_STATE | statement is busy. (%d) | | ERR-03210 | ERR_MM_CONN_INVALID_STATE | This connection already has been already disconnected | | ERR-03211 | ERR_MM_DB_EXIST | Database already exists. | | ERR-03212 | ERR_MM_DB_NOT_EXIST | Database does not exist. | | ERR-03213 | ERR_MM_SERVER_RUNNING | Server is running. | | ERR-03214 | ERR_MM_DBS_OPEN_FAIL | Failed to open dbs(%s) directory. | | ERR-03215 | ERR_MM_ALTER_SESSION | ALTER SESSION statement is not supported. | ### `ERR-04000`–`ERR-04999` (23) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-04000 | CMI_PROTOCOL_MSG_ERROR_IN_CONNECTION | Protocol message error in connection. | | ERR-04001 | CMI_PROTOCOL_LENGTH_ERROR_IN_CONNECTION | Protocol length error in connection (%llu but %llu). | | ERR-04002 | CMI_DOUBLE_CREATE_COMMUNICATION_CHANNEL | Cannot create duplicate communication channels. | | ERR-04003 | CMI_SOCKET_CREATION_ERROR | Socket creation error (%d). | | ERR-04004 | CMI_BIND_ERROR | Socket bind error. Errorcode is (%d) | | ERR-04005 | CMI_LISTEN_ERROR | Listen error (%d). | | ERR-04006 | CMI_POLL_CREATION_ERROR | Poll creation error (%d). | | ERR-04007 | CMI_POLL_ADD_ERROR | Poll add error (%d). | | ERR-04008 | CMI_CONNECTION_ERROR | Creation error (%d). | | ERR-04009 | CMI_SEND_ERROR | Send error (%d). | | ERR-04010 | CMI_RECV_ERROR | Receive error (%d). | | ERR-04011 | CMI_DISPATCH_ERROR | Dispatch error (%d). | | ERR-04012 | CMI_SETSOCKOPT_ERROR | nbp_sock_set_opt() error (%d). | | ERR-04013 | CMI_RECV_RETRY_ERROR | Failed to receive accept data repeatedly in %u milliseconds. | | ERR-04014 | CMI_MEMORY_ALLOC_ERROR | Memory allocation error. | | ERR-04015 | CMI_INVALID_PROTOCOL_ERROR | Receive invalid protocol (%d). | | ERR-04016 | CMI_TIMEDOUT_ERROR | Communication timed out error. (%d) | | ERR-04017 | CMI_SOCKET_CLOSED | Remote socket closed. | | ERR-04018 | CMI_INVALID_BIND_IP_ADDR | BIND_IP_ADDRESS [%s] is invalid | | ERR-04019 | CMI_BIND_ADDR_NOT_AVAILABLE | BIND_IP_ADDRESS [%s] is not available. Errorcode is[%d] | | ERR-04020 | CMI_BIND_PORT_INUSE | Port[%d] is already in use. Errorcode is [%d] | | ERR-04021 | CMI_OS_NOT_SUPPORT_FUNCTION | Function[%s] is not supported in this OS[%s] | | ERR-04999 | ERR_QP_ROLLUP_NOT_SUPPORTED_ON_DISTANCE_AXIS | ROLLUP is not supported on DISTANCE axis TAG table. | ### `ERR-05000`–`ERR-05999` (1) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-05002 | AD_MANAGER_GENERATE_ERROR | msg does not used | ### `ERR-06000`–`ERR-06999` (35) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-06000 | ERR_LM_FUNCTION_EXECUTION | Function execution failed: "%s". | | ERR-06001 | ERR_LM_RESPONSE_FAILED | Response failed: %s | | ERR-06002 | ERR_LM_ACCEPT_TIMEOUT | Accept timeout: "%s:%u". | | ERR-06003 | ERR_LM_SEND_BUFFER_OVERFLOW | Send buffer overflow: "%s". | | ERR-06004 | ERR_LM_COMMAND_EXECUTION_FAILED | Command execution failed: Application-Id = %u, Command-Code = %u. | | ERR-06005 | ERR_LM_UNSUPPORTED_COMMAND | Unsupported command: Application-Id = %u, Command-Code = %u. | | ERR-06006 | ERR_LM_ALREADY_CONNECTED | Already connected: "%s". | | ERR-06007 | ERR_LM_CSTR_TO_INT32_FAILED | Failed to convert string "%s" to int. | | ERR-06008 | ERR_LM_DESTINATION_HOST_TOO_LONG | Destination-Host too long: "%s". | | ERR-06009 | ERR_LM_DISCONNECTED | Disconnected: "%s". | | ERR-06010 | ERR_LM_HOST_NOT_FOUND | Host not found: "%s". | | ERR-06011 | ERR_LM_GROUPED_AVP_TOO_DEEP | Grouped AVP too deep: %d. | | ERR-06012 | ERR_LM_HANDSHAKE_TIMEOUT | Handshake timeout: "%s". | | ERR-06013 | ERR_LM_INITIALIZED | Link manager already initialized. | | ERR-06014 | ERR_LM_INVALID_HEADER | Invalid header: "%s". | | ERR-06015 | ERR_LM_INVALID_HOST | Invalid host: "%s" and "%s". | | ERR-06016 | ERR_LM_INVALID_PORT_NO | Invalid port no: %d. | | ERR-06017 | ERR_LM_MESSAGE_TOO_LONG | Message too long: %d | | ERR-06018 | ERR_LM_MISSING_AVP | Missing AVP: "%s" | | ERR-06019 | ERR_LM_NOT_INITIALIZED | Link manager not initialized. | | ERR-06020 | ERR_LM_NO_OPENED_GROUPED_AVP_FOUND | No opened grouped AVP found. | | ERR-06021 | ERR_LM_NULL_POINTER_ACCESS | NULL pointer access: "%s". | | ERR-06022 | ERR_LM_ORIGIN_HOST_TOO_LONG | Origin-Host too long: "%s". | | ERR-06023 | ERR_LM_REQUIRE_REQUEST_MESSAGE | Require request message. | | ERR-06024 | ERR_LM_SESSION_ID_TOO_LONG | Session-Id too long: "%s". | | ERR-06025 | ERR_LM_CONNECTION_TIMEOUT | Connection timeout: "%s". | | ERR-06026 | ERR_LM_UNABLE_TO_BIND_ADDRESS | Unable to bind address: "%s". | | ERR-06027 | ERR_LM_ABORT_CALLBACK_TIMEOUT | Abort callback: "Timeout". | | ERR-06028 | ERR_LM_ABORT_CALLBACK_DISCONNECTED | Abort callback: "Disconnected". | | ERR-06029 | ERR_LM_ABORT_CALLBACK_SHUTDOWN | Abort callback: "Shutdown". | | ERR-06030 | ERR_LM_NO_MORE_ADDRESS | No more address: "%s". | | ERR-06031 | ERR_LM_HANDSHAKE_FAILED | Handshake failed: "%s". | | ERR-06032 | ERR_LM_PROCESS_MEMORY_LIMIT | Failed to allocate connection (Current Allocate Memory / PROCESS_MAX_SIZE (%llu/%llu)). | | ERR-06033 | ERR_LM_ABORT_CONN_FREED | connection object for (%s) has been freed. please retry. | | ERR-06034 | ERR_LM_ABORT_SEND_RETRY_COUNT_EXHAUSETED | The number of send repetitions has been exhausted. | ### `ERR-07000`–`ERR-07999` (50) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-07000 | ERR_XM_CREATE_HASH | Error in creating hashtable for global metadata. | | ERR-07001 | ERR_XM_OPEN_META | Error in opening meta. Cannot open meta database. | | ERR-07002 | ERR_XM_EXEC_META | Error in executing meta. Cannot execute meta database | | ERR-07003 | ERR_XM_CLOSE_META | Error in closing meta. Cannot close meta database. | | ERR-07004 | ERR_XM_FETCH_META | Error in fetching meta. | | ERR-07005 | ERR_XM_GLOB_OBJECT_NOT_EXISTS_BY_LOID | No global object found. (Local Object ID=%llu, Host=%s) | | ERR-07006 | ERR_XM_GLOB_OBJECT_NOT_EXISTS_BY_GOID | No global object found. (Global Object ID=%llu, Host=%s) | | ERR-07007 | ERR_XM_GLOB_OBJECT_EXISTS | Global object already exists. (Global Object ID=%llu, Host=%s) | | ERR-07008 | ERR_XM_HASH_ADD_FAILURE | Error in hash add (Memory allocation failed). | | ERR-07009 | ERR_XM_STATEMENT_ALREADY_EXISTS | Failed to add query statement due to unfinished one. | | ERR-07010 | ERR_XM_STATEMENT_NO_EXISTS | Failed to find query statement. | | ERR-07011 | ERR_XM_NOT_SUPPORTED_YET | This query type is not supported yet. | | ERR-07012 | ERR_XM_NOT_SUPPORTED_PLANNODE_YET | This plan node (%s) is not supported yet. | | ERR-07013 | ERR_XM_STATEMENT_CANCELLED | Statement is canceled by the broker. | | ERR-07014 | ERR_XM_NODE_INFO_EXISTS | Node information already exists. | | ERR-07015 | ERR_XM_INVALID_MESSAGE | Invalid message from XM: %u | | ERR-07016 | ERR_XM_DDL_ON_WAREHOUSE_NOT_SUPPORTED | DDL/DELETE statement on warehouse node is not supported. | | ERR-07017 | ERR_XM_NOT_SUPPORTED_AGG_FUNC_YET | This aggregate function (%s) is not supported yet. | | ERR-07018 | ERR_XM_STANDBY_INSERT | INSERT/APPEND to warehouse standby is not available. | | ERR-07019 | ERR_XM_UNSUPPORTED_STMT_TYPE | Unsupported query statement type in the Cluster Edition. | | ERR-07020 | ERR_XM_INTERNAL_ERROR | XM internal error (XMART_POINT:%s) | | ERR-07021 | ERR_XM_XMART_TARGET_NOT_NODE_ID | [XM-ART] Targeted node is not valid. (%s) | | ERR-07022 | ERR_XM_ERROR_VIA_ANSWER_MSG | An error occurred after processing a %s message. [Src='%s']: %s | | ERR-07023 | ERR_XM_ERROR_STAFF_ALREADY_GONE | Execution unit from remote note is already gone. | | ERR-07024 | ERR_XM_INVALID_APPEND_ON_WAREHOUSE | APPEND operation on warehouse node is not supported. | | ERR-07025 | ERR_XM_INVALID_NODE_HOSTS | Host information from broker is invalid. Please check coordinator's status. | | ERR-07026 | ERR_XM_CLUSTER_INVALID | Cluster node information is invalid. | | ERR-07027 | ERR_XM_CLUSTER_CHANGED | Cluster node information has changed during query execution. | | ERR-07028 | ERR_XM_CANNOT_EXPLAIN_STAGE | This execution plan does not need to generate stage(s). | | ERR-07029 | ERR_XM_CLUSTER_CONNECTION_ABORT_TIMEOUT | Cluster connection aborted: Time-out | | ERR-07030 | ERR_XM_CLUSTER_CONNECTION_ABORT_LINK_BROKEN | Cluster connection aborted: Disconnected by warehouse. | | ERR-07031 | ERR_XM_BLOCKED_BY_DEACTIVATED_MODE | DML/DDL is disabled in DEACTIVATED mode. | | ERR-07032 | ERR_XM_DELETE_NOT_AVAILABLE | DELETE is not available since a read-only group exists. | | ERR-07033 | ERR_XM_WAREHOUSE_DROPPED_OUT | Participating warehouse has been dropped out. | | ERR-07034 | ERR_XM_INVALID_BROKER_STORED | Broker info has been changed. Please free statement and initalize again. | | ERR-07035 | ERR_XM_WAREHOUSE_DIRECT_DML_NOW_ALLOWED | Direct DML on warehouse is not allowed. | | ERR-07036 | ERR_XM_WAREHOUSE_NOT_AVAILABLE | Warehouse is not available. | | ERR-07037 | ERR_XM_STAGE_MEMORY_LIMIT | Execution stage memory usage exceeded the limit. (used: %llu, maximum: %llu) | | ERR-07038 | ERR_XM_ARCHIVE_INTERNAL_ERROR | XM archiving error occurred. (%s) | | ERR-07039 | ERR_XM_BROKER_DISCONN | Broker (%s) is disconnected. | | ERR-07040 | ERR_XM_BROKER_NOT_LEADER | Only leader broker can execute DML on LOOKUP table. | | ERR-07041 | ERR_XM_BROKER_REMOTE_ERROR | Remote error. (%s) | | ERR-07042 | ERR_XM_RESTORE_LOOKUP_TIMEOUT | LOOKUP table restore timeout: (%s) | | ERR-07043 | ERR_XM_BROKER_NOT_ACTIVE | Broker is not ACTIVE. | | ERR-07044 | ERR_XM_VERSION_NOT_MATCH | XM version does not match. (%s - %s) | | ERR-07045 | ERR_XM_SNAPSHOT_FAIL | Snapshot failed: %s. | | ERR-07046 | ERR_XM_MESSAGE_EXPIRED | Message %d is expired. | | ERR-07047 | ERR_XM_SNAPSHOT_RECOVER_IN_PROGRESS | Snapshot recover is in progress. | | ERR-07048 | ERR_XM_QUEUE_TIMEOUT | Queue timeout. | | ERR-07049 | ERR_XM_VERSION_UNMATCHED | XM version does not match. (%d - %d) | ### `ERR-08000`–`ERR-08999` (109) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-08000 | ERR_CC_FUNCTION_EXECUTION | Function execution failed: "%s". | | ERR-08001 | ERR_CC_BUFFER_OVERRUN | Buffer overrun. | | ERR-08002 | ERR_CC_END_OF_FILE | End of file. | | ERR-08003 | ERR_CC_HEADER_OCCURS_TOO_MANY_TIMES | Header occurs too many times: "%s". | | ERR-08004 | ERR_CC_JSON_DEPTH_OUT_OF_RANGE | JSON depth: Out of range. | | ERR-08005 | ERR_CC_CONNECTION_TIMEOUT | Connection timeout. | | ERR-08006 | ERR_CC_PACKAGE_NOT_FOUND | Package not found: "%s". | | ERR-08007 | ERR_CC_FILE_NAME_MISMATCH | File name mismatch: "%s" and "%s" | | ERR-08008 | ERR_CC_BLOCK_SIZE_OVERRUN | Block size overrun: %llu and %llu | | ERR-08009 | ERR_CC_FILE_SIZE_MISMATCH | File size mismatch: %llu and %llu | | ERR-08010 | ERR_CC_FILE_READ_SIZE_MISMATCH | File read size mismatch: %llu and %llu | | ERR-08011 | ERR_CC_FILE_WRITE_SIZE_MISMATCH | File write size mismatch: %llu and %llu | | ERR-08012 | ERR_CC_NODE_NOT_FOUND | Node not found: "%s" | | ERR-08013 | ERR_CC_NODE_EXIST | Node exist: "%s" | | ERR-08014 | ERR_CC_INVALID_PACKAGE_FILE_SIZE | Invalid package file size: "%s" = %llu / %llu | | ERR-08015 | ERR_CC_UNMATCHED_HOST | Unmatched host: "%s" and "%s" | | ERR-08016 | ERR_CC_DASHBOARD_INITIALIZED | Dashboard initialized | | ERR-08017 | ERR_CC_DASHBOARD_NOT_INITIALIZED | Dashboard is not initialized | | ERR-08018 | ERR_CC_NULL_POINTER_ACCESS | NULL pointer access: "%s". | | ERR-08019 | ERR_CC_STATUS_NOT_FOUND | Status not found: "%s" | | ERR-08020 | ERR_CC_HASH_INSERT_FAILED | Hash insert failed: "%s" | | ERR-08021 | ERR_CC_HASH_DELETE_FAILED | Hash delete failed: "%s" | | ERR-08022 | ERR_CC_HOST_TOO_LONG | Host too long: "%s" | | ERR-08023 | ERR_CC_ACTIVE_TOO_LONG | Active too long: "%s" | | ERR-08024 | ERR_CC_COORDINATOR_HOST_TOO_LONG | Coordinator-Host too long: "%s" | | ERR-08025 | ERR_CC_SPIN_TIMEOUT | Spin timeout | | ERR-08026 | ERR_CC_DDL_DISABLED | DDL disabled: %s | | ERR-08027 | ERR_CC_STATUS_UNINITALIZED | Status uninitialized | | ERR-08028 | ERR_CC_UNSUPPORTED_NODE_TYPE | Unsupported Node-Type: %u | | ERR-08029 | ERR_CC_SEQUENCE_NUMBER_UNINITIALIZED | Sequence number uninitialized | | ERR-08030 | ERR_CC_SEQUENCE_NUMBER_UNMATCHED | Sequence number unmatched: %lld and %lld | | ERR-08031 | ERR_CC_DDL_INCOMPLETED | DDL[%lld] incomplete: [%s] | | ERR-08032 | ERR_CC_INVALID_BROKER_COUNT | Invalid broker count: %lld | | ERR-08033 | ERR_CC_DDL_FAILED | DDL failed | | ERR-08034 | ERR_CC_DDL_SEQUENCE_NOT_FOUND | DDL sequence not found | | ERR-08035 | ERR_CC_INVALID_DDL_STATE | Invalid DDL state: %lld | | ERR-08036 | ERR_CC_INVALID_DDL_RETURNED | Invalid DDL returned: %lld and %lld | | ERR-08037 | ERR_CC_STANDBY_TOO_LONG | Standby too long: "%s" | | ERR-08038 | ERR_CC_INVALID_STATE_CHANGE | Invalid state change: %u => %u | | ERR-08039 | ERR_CC_INVALID_STATE | Invalid state: %u | | ERR-08040 | ERR_CC_INVALID_NODE_TYPE | Invalid Node-Type: %u | | ERR-08041 | ERR_CC_COORDINATOR_INACTIVE | Coordinator inactive | | ERR-08042 | ERR_CC_NOT_LEADER | Only leader can execute DDL. | | ERR-08043 | ERR_CC_DDL_TIMEOUT | DDL timeout | | ERR-08044 | ERR_CC_DDL_ERROR_MESSAGE | %s | | ERR-08045 | ERR_CC_DDL_NOT_FOUND | DDL not found: %llu | | ERR-08046 | ERR_CC_DDL_INCOMPLETNESS | DDL incompleteness: "%s" | | ERR-08047 | ERR_CC_UNSUPPORTED_PACKAGE | Unsupported package: "%s" | | ERR-08048 | ERR_CC_DDL_DISABLED_BY_MODE_CHANGE | DDL disabled by mode change | | ERR-08049 | ERR_CC_FAILED_TO_FORKED_COMMAND | Failed to fork and execute command: %s. Please check deployer's trace log. | | ERR-08050 | ERR_CC_FUNCTION_EXECUTION_WITH_RC | Function execution failed: "%s" (errno=%d). | | ERR-08051 | ERR_CC_DDL_DISABLED_READONLY_GROUP | DDL disabled because a part of group is not normal. | | ERR-08052 | ERR_CC_DDLSYNC_EXECUTE_FAILED_AFTER_RETRY | DDL[%llu] execution during DDL-Sync failed after several attempts. | | ERR-08053 | ERR_CC_INVALID_OPTION | Invalid option (%s). | | ERR-08054 | ERR_CC_GROUP_NOT_FOUND | Group (%s) is not found. | | ERR-08055 | ERR_CC_PORT_CHECK_REQUIRED | Check %s port number (%d). | | ERR-08056 | ERR_CC_DEPLOYER_DISABLED | Deployer is disabled: "%s". | | ERR-08057 | ERR_CC_ONLY_PRIMARY_COORDINATOR_AVAILABLE | Command is not available in the secondary coordinator. | | ERR-08058 | ERR_CC_CLUSTER_SYNC_FAILURE | Cluster synchronization failed. | | ERR-08059 | ERR_CC_INVALID_DECISION_STATE | Invaid decision state: %s | | ERR-08060 | ERR_CC_MISSING_ATTRIBUTE | Missing attribute: %s | | ERR-08061 | ERR_CC_ATTRIBUTE_OCCURS_TOO_MANY_TIMES | Attribute occurs too many times: %s | | ERR-08062 | ERR_CC_EXECUTE_COMMAND_FAILURE | Failed to execute command (%s). | | ERR-08063 | ERR_CC_PACKAGE_ALREADY_EXISTS | Package name or file name already exists (%s = %s). | | ERR-08064 | ERR_CC_HOST_RES_INFO_NOT_FOUND | Host resource info not found: "%s" | | ERR-08065 | ERR_CC_DISK_INFO_NOT_FOUND | Disk info not found: "%s" | | ERR-08066 | ERR_CC_INTEGER_OVERFLOW | Integer overflow. | | ERR-08067 | ERR_CC_COORDINATOR_COUNT_EXCEEDED | The number of coordinators exceeded %d. | | ERR-08068 | ERR_CC_DDL_DISABLED_BY_INITIAL_STATE | DDL disabled since some of nodes are in initial states. | | ERR-08069 | ERR_CC_COORD_ROLE_HANDSHAKE | Coordinator role handshake failed: [%s] | | ERR-08070 | ERR_CC_HOST_RESOURCE_DISABLED | Collecting host resource is disabled. | | ERR-08071 | ERR_CC_REQUEST_FAILED | Request to execute command %s failed. (code=%d) | | ERR-08072 | ERR_CC_CLUSTER_ACTIVATION_FAILED | Cluster activation failed: %lld / %lld. | | ERR-08073 | ERR_CC_ENVIRONMENT_VARIABLE_NOT_SET | Environment (%s) is not set. | | ERR-08074 | ERR_CC_OPTION_DUPLICATED | Option duplicated. | | ERR-08075 | ERR_CC_OPTION_REQUIRED | Option required (%s). | | ERR-08076 | ERR_CC_LOCK_FAILED | Cannot read Lock File! Check $MACHBASE_COORDINATOR_HOME/conf/machbasecoordinator.lock* and Tracelog in $MACHBASE_COORDINATOR_HOME/trc. | | ERR-08077 | ERR_CC_COORDINATOR_RUNNING | Machbase coordinator is running. | | ERR-08078 | ERR_CC_COORDINATOR_NOT_RUNNING | Machbase coordinator is not running. | | ERR-08079 | ERR_CC_COORDINATOR_PHASE1_FAILED | Machbase Coordinator %s Phase1 failed: %s | | ERR-08080 | ERR_CC_COORDINATOR_PHASE2_FAILED | Machbase Coordinator %s Phase2 failed: %s | | ERR-08081 | ERR_CC_COORDINATOR_DEAD | Machbase Coordinator has been DEAD! Check Tracelog in $MACHBASE_COORDINATOR_HOME/trc. | | ERR-08082 | ERR_CC_METADATA_NOT_CREATED | Machbase Coordinator metadata is not created. Check Tracelog in $MACHBASE_COORDINATOR_HOME/trc. | | ERR-08083 | ERR_CC_METADATA_ALREADY_CREATED | Machbase Coordinator metadata is already created. Check Tracelog in $MACHBASE_COORDINATOR_HOME/trc. | | ERR-08084 | ERR_CC_INVALID_PROCESS_ID | Invalid process id. | | ERR-08085 | ERR_CC_OPTION_INIT_FAILED | Option initialization error: %d. | | ERR-08086 | ERR_CC_OPTION_CHECK_FAILED | Option check error: %d. | | ERR-08087 | ERR_CC_OPTION_GET_FAILED | Option retrieval error: %d (%s). | | ERR-08088 | ERR_CC_COMMAND_OPTION_NOT_FOUND | Command option is not found. | | ERR-08089 | ERR_CC_COLLECTING_HOST_RES_FAILED | Failed to collect '%s': %s. | | ERR-08090 | ERR_CC_INVALID_ATTRIBUTE | Invalid attribute: %s | | ERR-08091 | ERR_CC_DDL_RECOVERY_FAILED | DDL recovery failed: %s. | | ERR-08092 | ERR_CC_DESIRED_STATE_NOT_APPLICABLE | Desired state (%s) is not applicable. | | ERR-08093 | ERR_CC_NODE_STILL_RUNNING | %s is still running. | | ERR-08094 | ERR_CC_SNAPSHOT_NOT_EXIST | SNAPSHOT on %s does not exist. | | ERR-08095 | ERR_CC_RECOVER_NON_READONLY | Group %s is not readonly mode. Snapshot recovery works only for a readonly group | | ERR-08096 | ERR_CC_SNAPSHOT_NOT_AVAILABLE | Snapshot is not available: %s | | ERR-08097 | ERR_CC_NOT_SCRAPPED | Warehouse %s is not scrapped. %s only works on a scrapped warehouse. | | ERR-08098 | ERR_CC_MASTER_NOT_FOUND | Cannot add lookup node %s (%s) before adding the lookup master node. | | ERR-08099 | ERR_CC_MASTER_NOT_MONITOR | Lookup monitor node (%s) cannot change the lookup master node. | | ERR-08100 | ERR_CC_SNAPSHOT_FAIL_PUBLISH | Failed to publish SnapshotID to warehouse. | | ERR-08101 | ERR_CC_NOT_READONLY | Group (%s) is not readonly. | | ERR-08102 | ERR_CC_NODE_FIX | Fix node (%s) failed. (refcnt=%d) | | ERR-08103 | ERR_CC_LOOKUP_ALREADY_RUNNING | Lookup node running already. (%s:%d) | | ERR-08104 | ERR_CC_LOOKUP_CONNECT_FAILED | Connect to lookup node failed. (%s:%d) | | ERR-08105 | ERR_CC_LOOKUP_STARTUP_FAILED | Startup lookup node failed. (%s:%d) | | ERR-08106 | ERR_CC_NORMAL_SHUTDOWN | Unable to shutdown warehouse (%s) since it is not INACTIVE status. | | ERR-08107 | ERR_CC_MESSAGE_EXPIRED | Expired message (%llu) received. | | ERR-08108 | ERR_CC_SNAPSHOT_FAIL | Snapshot failed: %s | ### `ERR-09000`–`ERR-09999` (11) | コード | シンボル | メッセージ原文 | |------|------|------| | ERR-09000 | ERR_RP_BUFFER_POOL_ITEM_ALLOC_FAIL | Failed to allocate buffer pool item. | | ERR-09001 | ERR_RP_TARGET_FILE_OPEN_FAIL | Failed to open replication target file <Table %llu, FileID %llu, PartID %llu - Level %d Type %d> | | ERR-09002 | ERR_RP_PROTOCOL_ERROR | Invalid protocol received. | | ERR-09003 | ERR_RP_SOCKET_ERROR | Socket write failed. | | ERR-09004 | ERR_RP_APPEND_VALUE_ERROR | Failed to append target table<%llu>. | | ERR-09005 | ERR_RP_VALUE_BUFFER_ALLOC_MEM_FAIL | Failed to allocate value buffer. | | ERR-09006 | ERR_RP_TABLE_CURSOR_OPEN_FAIL | Failed to open table <%llu>'s cursor. | | ERR-09007 | ERR_RP_POLL_REMOVE | Failed to remove poll socket. (%d) | | ERR-09008 | ERR_RP_POLL_DESTROY | Failed to destroy poll socket. (%d) | | ERR-09009 | ERR_RP_CANNOT_REPLICATE2_LARGER | Cannot replicate to larger dbs. | | ERR-09010 | ERR_RP_HOST_NOT_FOUND | Host not found: "%s". | ## エラーコードの確認方法 - machsqlまたはドライバーが返すエラー文字列を確認します。 - サーバーログは`$MACHBASE_HOME/trc/`内のトレースログを確認します。 エラー発生後に原因を特定できない場合は、[サーバーログの分析](/ja/dbms/operations-configuration-recovery/diagnosis-observability/#log-diagnosis-logs-log-server-logs)と[障害の兆候の確認](/ja/dbms/operations-configuration-recovery/diagnosis-observability/#monitoring-capacity-failure)を参照してください。 --- title: "16.8 AI Agent Reference" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/ language: ja kind: section --- # 16.8 AI Agent Reference AI Agent Referenceは、AIエージェントとRAGシステムがMachbase DBMS 8.7のドキュメントから 正しい公式リファレンスを見つけるための案内です。SQL構文、SDKのサポート範囲、運用手順は ここでは再定義せず、各機能の正式なドキュメントにリンクします。 ## 構成 | ページ | 目的 | |--------|------| | [エージェント利用ガイド](./guide-agent/) | 質問の分類、検証順序、回答の原則 | | [canonical-url-map](./canonical-url-map/) | トピック別の正規ドキュメントURL | | [task-map](./task-map/) | ユーザーの作業別の参照・検証順序 | | [support-matrix](./support-matrix/) | Edition・テーブル・SDKの正式なサポート表の検索 | | [constraints-index](./constraints-index/) | 制約とエラー条件の正式な参照先 | | [evidence-map](./evidence-map/) | 主張の種類に応じた根拠の選択 | | [terminology-disambiguation](./terminology-disambiguation/) | 混同しやすい用語の確認 | | [sql-generation-rules](./sql-generation-rules/) | SQL生成前の検証規則 | | [sdk-api-selection-rules](./sdk-api-selection-rules/) | SDKとAPIの選択順序 | | [operations-checklist](./operations-checklist/) | 安全な運用回答の作成順序 | | [error-resolution-map](./error-resolution-map/) | エラー診断の正式な参照先 | | [llms.txt](./llms-txt/) | 機械可読の簡潔なドキュメントマップ | | [全文とRAGインデックス](./llms-full-txt-chunk-index/) | 全文MarkdownとJSONドキュメントインデックス | ## 機械可読の出力 - [llms.txt](/ja/llms.txt) - [llms-full.txt](/ja/llms-full.txt) - [llms-chunks.json](/ja/llms-chunks.json) 上記の出力には現行の日本語DBMSドキュメントのみを含みます。Machbase Neoと 保存用のDBMS 8.5ドキュメントは含みません。 ## 利用原則 1. サーバーバージョン、Edition、テーブルタイプ、SDKを最初に確認します。 2. 機能の正式なリファレンスとサポート範囲を併せて読みます。 3. 未確認の構文、デフォルト値、制限、エラーコードを作らないでください。 4. 運用変更では対象、影響、復旧方法、完了条件を明記します。 5. 回答のリンクには公開の正規URLを使用します。 --- title: "16.8.1 エージェント利用ガイド" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/guide-agent/ language: ja kind: page --- # 16.8.1 エージェント利用ガイド このガイドは、正式なドキュメントを根拠にMachbaseの質問へ回答する手順を定義します。 ## 質問の分類 | 質問の種類 | 最初に確認するドキュメント | |----------|------------------| | インストール・アップグレード | [インストール、デプロイ、アップグレード](/ja/dbms/installation-deployment-upgrade/) | | テーブルの選択・設計 | [テーブルタイプの概念と選択](/ja/dbms/data-modeling-table-design/) | | SQL構文・関数 | [SQLリファレンス](/ja/dbms/reference/sql/) | | SDK・連携 | [開発とアプリケーション連携](/ja/dbms/development-tools-integration/) | | サポート可否・制約 | [サポート範囲と制約](/ja/dbms/reference/support-scope-constraints/) | | 運用・復旧 | [運用、設定、復旧](/ja/dbms/operations-configuration-recovery/) | | エラー・性能 | [トラブルシューティング](/ja/dbms/troubleshooting/)と[パフォーマンスチューニング](/ja/dbms/performance-tuning/) | ## 回答の作成順序 1. 質問から製品バージョン、Edition、テーブルタイプ、SDK、作業対象を特定します。 2. [用語の区別](../terminology-disambiguation/)でMachbaseでの意味を確認します。 3. [サポート表](../support-matrix/)と[制約インデックス](../constraints-index/)を確認します。 4. 構文・API・運用手順の正規ページで実際の形式を確認します。 5. 例には前提条件、実行、結果確認、後処理を含めます。 6. 不確かな事実は断定せず、確認に必要なバージョン・コマンド・ドキュメントを提示します。 ## 根拠とリンク - 公開の回答にはdocs.machbase.comの正規URLを使用します。 - 内部issue、commit、ソースパスを公開製品の動作を裏付ける根拠の代わりに使用しません。 - ドキュメント間に矛盾があれば、対象バージョンの最新の正式リファレンスと実際のサポート範囲を優先します。 ## 安全性 まず参照クエリと診断を提示します。データ削除、サーバー再起動、セッション終了、設定変更、復旧は、 ユーザーの対象と承認範囲を確認せずに実行手順として提示しないでください。 --- title: "16.8.2 canonical-url-map" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/canonical-url-map/ language: ja kind: page --- # 16.8.2 canonical-url-map Machbase DBMS 8.7ドキュメントの主な正規URLです。詳細ページは各章の目次から探し、 旧URLよりも以下の正式な参照先を優先します。 ## はじめにと基本概念 | トピック | 正規URL | |------|---------------| | DBMSマニュアル | `/dbms/` | | はじめに | `/dbms/getting-started/` | | 基本概念 | `/dbms/core-concepts/` | | インストール・アップグレード | `/dbms/installation-deployment-upgrade/` | | テーブルタイプの選択 | `/dbms/data-modeling-table-design/` | ## テーブルと分析 | トピック | 正規URL | |------|---------------| | TAG | `/dbms/tag-table-usage/` | | ROLLUP | `/dbms/tag-rollup-usage/` | | LOG | `/dbms/log-table-usage/` | | TRANSACTION | `/dbms/rdb-table-usage/` | | LOOKUP | `/dbms/lookup-table-usage/` | | VOLATILE | `/dbms/volatile-table-usage/` | ## 開発・運用・リファレンス | トピック | 正規URL | |------|---------------| | SDK/API | `/dbms/development-tools-integration/` | | 性能 | `/dbms/performance-tuning/` | | 運用・復旧 | `/dbms/operations-configuration-recovery/` | | セキュリティ | `/dbms/security-access-control/` | | トラブルシューティング | `/dbms/troubleshooting/` | | SQL | `/dbms/reference/sql/` | | 設定 | `/dbms/reference/configuration/` | | システムカタログ | `/dbms/reference/system-catalog/` | | サポート範囲 | `/dbms/reference/support-scope-constraints/` | | エラーコード | `/dbms/reference/error-codes/` | ## 機械可読のURL | 出力 | 韓国語 | 英語 | 日本語 | |------|--------|------|--------| | 簡潔なマップ | `/kr/llms.txt` | `/llms.txt` | `/ja/llms.txt` | | 全文 | `/kr/llms-full.txt` | `/llms-full.txt` | `/ja/llms-full.txt` | | ドキュメントインデックス | `/kr/llms-chunks.json` | `/llms-chunks.json` | `/ja/llms-chunks.json` | --- title: "16.8.3 task-map" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/task-map/ language: ja kind: page --- # 16.8.3 task-map ユーザーの作業ごとに、正式な参照先の確認順序と完了条件を示します。 | 作業 | 確認順序 | 完了の確認 | |------|-----------|-----------| | 初回インストール | [インストール](/ja/dbms/installation-deployment-upgrade/) → [はじめに](/ja/dbms/getting-started/) | サーバー状態、接続、サンプルクエリ | | テーブルの選択 | [選択基準](/ja/dbms/data-modeling-table-design/) → 該当テーブルの章 | Edition・DML・軸・保持要件を満たすこと | | 大量データ入力 | [連携の共通概念](/ja/dbms/development-tools-integration/concepts-common/) → SDKページ | 成功/失敗件数とフラッシュの確認 | | SQLの作成 | [SQLリファレンス](/ja/dbms/reference/sql/) → [サポート範囲](/ja/dbms/reference/support-scope-constraints/) | 実際のスキーマと結果の確認 | | SDKの選択 | [連携方法の選択](/ja/dbms/development-tools-integration/selection-integration-method/) → [SDKのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/) | サーバー・SDKバージョンとAPIの一致 | | 性能診断 | [性能改善の進め方](/ja/dbms/performance-tuning/performance-approach/) → 症状別チューニング | 基準値と変更後の測定値の比較 | | 障害診断 | [トラブルシューティング](/ja/dbms/troubleshooting/) → [エラーコード](/ja/dbms/reference/error-codes/) | 原因、対処、再発防止策の記録 | | バックアップ・復旧 | [バックアップ・復旧](/ja/dbms/operations-configuration-recovery/backup-restore-mount/) | 復元またはMOUNTによる参照の検証 | 書き込み・削除・再起動を含む作業では、対象と影響範囲を確定してから実行手順を選択します。 --- title: "16.8.4 support-matrix" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/support-matrix/ language: ja kind: page --- # 16.8.4 support-matrix このページではサポート表を複製せず、質問の観点を確認して現行の正式な参照先へ案内します。 ## 確認順序 1. [Edition別サポート表](/ja/dbms/reference/support-scope-constraints/edition/)でStandardとClusterの範囲を確認します。 2. [テーブルタイプ別サポート表](/ja/dbms/reference/support-scope-constraints/table-types-type/)で対象テーブルのSQL・APIの範囲を確認します。 3. [SDKのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/)でクライアントAPIと最低限の根拠を確認します。 4. 機能別の詳細サポート表で条件と例外を確認します。 | 機能群 | 正式な参照先 | |--------|------| | TAGデータのUPDATE | [TAG UPDATEサポート表](/ja/dbms/reference/support-scope-constraints/tag-data-update/) | | ROLLUP | [ROLLUPのサポート範囲](/ja/dbms/reference/support-scope-constraints/rollup/) | | TRANSACTION | [TRANSACTIONのサポート範囲](/ja/dbms/reference/support-scope-constraints/rdb/) | | バックアップ・MOUNT | [バックアップ/MOUNTサポート表](/ja/dbms/reference/support-scope-constraints/backup-mount/) | | 権限 | [権限サポート表](/ja/dbms/reference/support-scope-constraints/privileges/) | サポート可否を回答するときは、`O/△/X`だけでなくEdition、テーブルタイプ、サーバーとSDKの バージョン、必須条件も併せて示します。 --- title: "16.8.5 constraints-index" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/constraints-index/ language: ja kind: page --- # 16.8.5 constraints-index 制約に関する質問では、機能名だけでなく対象オブジェクトと実行経路も確認します。 | 制約の分類 | 正式な参照先 | |-----------|------| | Edition・テーブルタイプ | [サポート範囲と制約](/ja/dbms/reference/support-scope-constraints/) | | SQL条件とSET対象 | [SQL構文辞典](/ja/dbms/reference/sql/syntax/) | | TAG | [TAGの制約とトラブルシューティング](/ja/dbms/tag-table-usage/constraints-errors-troubleshooting/) | | ROLLUP | [ROLLUPの制約とトラブルシューティング](/ja/dbms/troubleshooting/rollup/) | | LOG | [LOGの制約とトラブルシューティング](/ja/dbms/log-table-usage/constraints-errors-troubleshooting/) | | TRANSACTION | [TRANSACTIONの制約とトラブルシューティング](/ja/dbms/rdb-table-usage/constraints-errors-troubleshooting/) | | LOOKUP | [LOOKUPの制約とトラブルシューティング](/ja/dbms/lookup-table-usage/constraints-errors-troubleshooting/) | | VOLATILE | [VOLATILEの制約とトラブルシューティング](/ja/dbms/volatile-table-usage/constraints-errors-troubleshooting/) | エラーが発生したら、SQL全文、スキーマ、Edition、サーバーバージョン、エラーコードを保存し、 正式なリファレンスの許容条件と比較します。 --- title: "16.8.6 evidence-map" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/evidence-map/ language: ja kind: page --- # 16.8.6 evidence-map 回答で述べる内容の種類に応じて、適切な公開の根拠を選択します。 | 主張の種類 | 優先する根拠 | |----------|-----------| | SQL構文・関数・型 | [SQLリファレンス](/ja/dbms/reference/sql/) | | Edition・テーブル・SDKのサポート | [サポート範囲と制約](/ja/dbms/reference/support-scope-constraints/)と[SDKのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/) | | 設定キー・デフォルト値 | [設定リファレンス](/ja/dbms/reference/configuration/)と配布パッケージの設定ファイル | | システム状態の列 | [システムカタログ](/ja/dbms/reference/system-catalog/) | | CLIオプション | [コマンドラインツール](/ja/dbms/reference/command-line-tools/)と配布パッケージの`--help` | | エラーの意味・対処 | [エラーコード](/ja/dbms/reference/error-codes/)と[トラブルシューティング](/ja/dbms/troubleshooting/) | | 運用手順 | [運用、設定、復旧](/ja/dbms/operations-configuration-recovery/) | ## 検証規則 - バージョンとEditionの条件を根拠とともに保持します。 - 例の結果を一般的な保証や性能値として扱わないでください。 - 公開の正式リファレンスにない事実は、確認が必要であることを明記します。 - 内部の開発履歴は公開マニュアルのリンクの代わりにはなりません。 --- title: "16.8.7 terminology-disambiguation" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/terminology-disambiguation/ language: ja kind: page --- # 16.8.7 terminology-disambiguation ユーザーの用語を一般的なデータベースの意味で推測せず、Machbaseの正式なリファレンスで確認します。 | 用語 | 正式な参照先 | |------|-------------| | TAG, LOG, LOOKUP, VOLATILE, TRANSACTION | [基本概念](/ja/dbms/core-concepts/)と[テーブルタイプの選択](/ja/dbms/data-modeling-table-design/) | | AppendとSQL INSERT | [連携の共通概念](/ja/dbms/development-tools-integration/concepts-common/) | | ROLLUP | [ROLLUPの利用](/ja/dbms/tag-rollup-usage/) | | BASETIME, BASE DISTANCE, SUMMARIZED | [TAGの構造とスキーマ](/ja/dbms/tag-table-usage/table-structure-schema/) | | AUTH KEY | [認証とAUTH KEY](/ja/dbms/security-access-control/authentication-auth-key/) | | Broker, Warehouse | [EditionとClusterの概念](/ja/dbms/core-concepts/concepts-edition/) | | database, owner, tablespace | [複数データベースの運用](/ja/dbms/operations-configuration-recovery/multi-database/) | 回答では製品のオブジェクト名とSQLキーワードをそのまま保持します。ユーザーが一般的な意味で使う 用語がMachbaseのオブジェクトと異なる場合は、最初に区別します。 --- title: "16.8.8 sql-generation-rules" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/sql-generation-rules/ language: ja kind: page --- # 16.8.8 sql-generation-rules AIがSQLを生成するときに適用する検証順序です。実際の構文は [SQLリファレンス](/ja/dbms/reference/sql/)を正式な参照先とします。 ## 生成前の確認 1. サーバーバージョンとEditionを確認します。 2. 対象のデータベース、所有者、テーブルタイプ、`DESC`の結果を確認します。 3. [SQL構文辞典](/ja/dbms/reference/sql/syntax/)でステートメントの形式を確認します。 4. [関数辞典](/ja/dbms/reference/sql/functions/)で引数と戻り値の型を確認します。 5. [サポート範囲](/ja/dbms/reference/support-scope-constraints/)でEdition・テーブルの制約を確認します。 ## 生成規則 - 他のDBMSのキーワード、関数、ヒント、トランザクション動作を推測で使用しないでください。 - 識別子をパラメーターマーカーで置き換えないでください。 - 時間・距離範囲、DELETE、UPDATEでは、対象となる予定の行を先に参照できるようにします。 - 結果の順序が必要な場合は`ORDER BY`を明示します。 - 変更の例には結果確認と後処理を含めます。 エラーが発生したら構文を任意に変更せず、エラー全文とスキーマを使って [トラブルシューティング](/ja/dbms/troubleshooting/)の手順で確認します。 --- title: "16.8.9 sdk-api-selection-rules" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/sdk-api-selection-rules/ language: ja kind: page --- # 16.8.9 sdk-api-selection-rules SDK名だけで機能を判断せず、要件と実際のサポート範囲を併せて確認します。 ## 選択順序 1. 言語と標準インターフェースの要件を[連携方法の選択](/ja/dbms/development-tools-integration/selection-integration-method/)で確認します。 2. Append、トランザクション、プリペアドステートメント、名前付きバインド、メタデータ、AUTH KEYの要件を整理します。 3. [SDKのサポート範囲](/ja/dbms/development-tools-integration/sdk-support-scope/)でサポート可否と根拠を確認します。 4. 選択したSDKのページでインストール、接続オプション、型マッピング、エラー処理を確認します。 | 環境 | 正式な参照先 | |------|------| | C/C++ SQLCLI・ODBC | [SQLCLIとODBC](/ja/dbms/development-tools-integration/cli-odbc/) | | Java | [JDBC](/ja/dbms/development-tools-integration/jdbc/) | | Python | [Python](/ja/dbms/development-tools-integration/python/) | | Node.js・TypeScript | [Node.js / TypeScript](/ja/dbms/development-tools-integration/node-js-typescript/) | | .NET | [.NET Connector](/ja/dbms/development-tools-integration/net-connector/) | | Go | [Go](/ja/dbms/development-tools-integration/go/) | サーバーとSDKのバージョンの組み合わせは、[互換性](/ja/dbms/reference/support-scope-constraints/compatibility-xma-protocol/)も確認します。 --- title: "16.8.10 operations-checklist" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/operations-checklist/ language: ja kind: page --- # 16.8.10 operations-checklist 運用に関する回答では[運用、設定、復旧](/ja/dbms/operations-configuration-recovery/)の手順を 参照し、次の安全な順序に従います。 1. 症状、発生時刻、エラー全文、対象のデータベース・ノード・テーブルを特定します。 2. `machadmin -e`、関連する`V$`ビュー、ログで現在の状態を読み取り専用で確認します。 3. 正常動作と障害状態を区別し、変更が必要な根拠を提示します。 4. 変更対象、影響、ダウンタイム、ロールバック、成功条件を明記します。 5. ユーザーの承認範囲を確認し、1段階ずつ実行して結果を再確認します。 サーバー再起動、セッション終了、データ削除、設定変更、バックアップからの復元、 クラスターノードの変更を診断コマンドのように自動提案しないでください。 コマンドとSQLは該当する[運用の章](/ja/dbms/operations-configuration-recovery/)で確認します。 --- title: "16.8.11 error-resolution-map" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/error-resolution-map/ language: ja kind: page --- # 16.8.11 error-resolution-map エラー番号や原因を推測せず、エラー全文と実行時の状況を保存します。 ## 診断順序 1. `ERR-XXXXX`メッセージ全文、SQL・コマンド、発生時刻を収集します。 2. サーバーとSDKのバージョン、Edition、対象のデータベース・所有者・テーブル、接続オプションを記録します。 3. [エラーコード辞典](/ja/dbms/reference/error-codes/)でメッセージを確認します。 4. [トラブルシューティング](/ja/dbms/troubleshooting/)の症状別診断手順を適用します。 5. 対処後、同じ入力と確認クエリで復旧を検証します。 | 症状 | 正式な参照先 | |------|------| | サーバー・認証・接続 | [サーバーと接続の問題](/ja/dbms/troubleshooting/server-connection/) | | 入力・Append・ファイル | [入力とロードの問題](/ja/dbms/troubleshooting/item/) | | クエリ・性能・メモリ | [クエリと性能の問題](/ja/dbms/troubleshooting/performance/) | | バックアップ・復旧 | [バックアップと復旧の問題](/ja/dbms/troubleshooting/recovery-backup/) | | Cluster | [Clusterの問題](/ja/dbms/troubleshooting/cluster/) | エラーメッセージの一部だけから任意のエラーコードを割り当てたり、問題を再現せずに 破壊的な回避策を推奨したりしないでください。 --- title: "16.8.12 llms.txt" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/llms-txt/ language: ja kind: page --- # 16.8.12 llms.txt `llms.txt`は、LLMが現行のMachbase DBMSマニュアルの構造と主な正式リファレンスを すばやく見つけるための、UTF-8プレーンテキスト形式の目次です。 ## URL | 言語 | URL | |------|-----| | 英語 | [https://docs.machbase.com/llms.txt](/llms.txt) | | 韓国語 | [https://docs.machbase.com/kr/llms.txt](/kr/llms.txt) | | 日本語 | [https://docs.machbase.com/ja/llms.txt](/ja/llms.txt) | 出力には現行の`/dbms/`ドキュメントのみを含みます。Machbase Neo、保存用のDBMS 8.5、 ドラフト、エイリアスページは含みません。 ## 内容 - 製品とマニュアルのバージョン - DBMSの上位章と正規URL - SQL、SDK、運用、サポート範囲、エラーコードの正式な参照先 - AI Agent Reference - 全文とJSONインデックスのURL ## 利用方法 1. `llms.txt`で質問のトピックに対応する正規セクションを探します。 2. 個別のMarkdownが必要な場合は、該当ドキュメントURLの`index.md`を読みます。 3. コーパス全体が必要な場合は[llms-full.txt](../llms-full-txt-chunk-index/)を使用します。 4. クローラーでドキュメント単位のメタデータが必要な場合は`llms-chunks.json`を使用します。 `llms.txt`は参照先を探すためのインデックスであり、製品仕様の正式な根拠ではありません。 回答を作成するときはリンク先の現行ドキュメントを確認します。 --- title: "16.8.13 全文とRAGドキュメントインデックス" url: https://docs.machbase.com/ja/dbms/reference/ai-agent-reference/llms-full-txt-chunk-index/ language: ja kind: page --- # 16.8.13 全文とRAGドキュメントインデックス 現行のDBMSマニュアルは、全文Markdownとページ単位のJSONインデックスを提供します。 ## 全文 | 言語 | URL | |------|-----| | 英語 | [llms-full.txt](/llms-full.txt) | | 韓国語 | [llms-full.txt](/kr/llms-full.txt) | | 日本語 | [llms-full.txt](/ja/llms-full.txt) | 全文は、公開済みDBMSページをナビゲーションのweight順に連結します。各ページの境界には タイトル、言語、正規URLを記載し、本文はソースのMarkdownを保持します。 ## JSONインデックス | 言語 | URL | |------|-----| | 英語 | [llms-chunks.json](/llms-chunks.json) | | 韓国語 | [llms-chunks.json](/kr/llms-chunks.json) | | 日本語 | [llms-chunks.json](/ja/llms-chunks.json) | スキーマバージョン1の最上位フィールドは次のとおりです。 | フィールド | 説明 | |------|------| | `schema_version` | JSONの仕様バージョン。現在は`1` | | `product` | `Machbase DBMS` | | `manual_version` | マニュアルの対象製品バージョン | | `language` | `en`、`kr`、`ja` | | `document_count` | `documents`配列の要素数 | | `documents` | ドキュメントのメタデータ配列 | 各ドキュメントは`id`、`title`、`url`、`markdown_url`、`kind`、`parent_url`、`weight`、 `last_modified`を提供します。JSONには本文を重複保存しません。`markdown_url`から ページ別のMarkdownを取得するか、`llms-full.txt`をコーパスとして使用します。 ## チャンクの境界 現在のインデックスは、1つの公開済みページを1つのドキュメントチャンクとして扱います。 SQL構文、SDKの作業、運用手順は可能な限り個別ページに保持されるため、URLとタイトルを 安定したチャンク識別子として使用できます。大きな辞典ページを細分化するときも既存ページの`id`を保持します。 ビルド時刻などの非決定的な値は出力しません。Neo、DBMS 8.5、ドラフト、エイリアスページは インデックスと全文の両方から除外します。