LogQL、KQL、および SPL クエリを SQL に移行する
操作クエリを SQL に移動することは、検索と置換の作業ではなく、データ モデルの移行です。 LogQL はログ ストリームとラベル セレクターから始まり、Kusto クエリ言語は表形式のパイプラインを使用し、Splunk SPL はコマンドを通じて検索結果を変換します。 SQL はリレーションから始まり、選択、グループ化、結合、射影を明示的に行います。
最も安全な移行では、構文を変更する前に質問と結果のコントラクトが保存されます。
まずセマンティックコントラクトを書き留めます
すべてのクエリについて、以下を記録します。
- それが支持する決定。
- ソースとタイムウィンドウ。
- 行またはイベントの粒度。
- 解析されたフィールドとその型。
- ディメンションのグループ化。
- 分子と分母。
- null、重複、再試行、および遅延到着ルール。
- 予想される列と並べ替え順序。
古いクエリと新しいクエリを同じ制限された間隔で実行します。最初に合計を比較し、次にグループレベルの結果を比較し、次に代表的な生の行を比較します。視覚的に似た結果であっても、異なる分母を使用することができます。
共有されたイベントの例
以下の変換では、完了した API リクエストごとに 1 つの型指定された行を想定しています。
{
"timestamp": "2026-07-28T16:04:00Z",
"event_name": "api_request_completed",
"service": "checkout-api",
"route": "/v1/orders/:id",
"status_code": 503,
"latency_ms": 842,
"request_id": "req_01J...",
"release": "2026.07.28"
}
古いシステムが次のようなメッセージのみを保存している場合、 "GET /v1/orders/123 returned 503 in 842ms"、まずパーサーを追加するか、インストルメンテーションを変更します。 SQL は、記録されていない安定したルート テンプレートまたは信頼できる数値タイプを回復できません。
コンセプトマップ
| 意図 | LogQL | KQL | SPL | SQL |
|---|---|---|---|---|
| ソースを選択してください | ストリームセレクター | テーブル式 | インデックスとソース検索 | FROM table |
| 行をフィルタリングする | 行またはラベルのフィルター | where |
search または where |
WHERE |
| フィールドを解析する | パーサー式 | parse, extend |
rex, spath, eval |
クエリの前に列を入力することが望ましい |
| 列の選択 | 行フォーマット | project |
fields または table |
SELECT |
| 集合体 | メトリッククエリ | summarize |
stats または timechart |
集計プラス GROUP BY |
| パイプライン | ` | ` ステージ | ` | ` 演算子 |
| タイムバケット | 範囲ベクトル | bin() |
timechart span= |
date_trunc() |
この表は、正確な同等性ではなく、意図をマッピングしています。たとえば、Loki ラベルはストリームのインデックス付けとカーディナリティの制約に関与します。 SQL 列は、自動的には同じストレージ動作をしません。
例 1: 最近のエラーをフィルタリングする
LogQL
{service="checkout-api"} | json | status_code >= 500
KQL
ApiRequestCompleted
| where Timestamp > ago(1h)
| where Service == "checkout-api" and StatusCode >= 500
| project Timestamp, Route, StatusCode, LatencyMs, RequestId
| order by Timestamp desc
SPL
index=production service=checkout-api status_code>=500 earliest=-1h
| table _time route status_code latency_ms request_id
| sort - _time
SQL
SELECT
timestamp_utc,
route,
status_code,
latency_ms,
request_id
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '1 hour'
AND service = 'checkout-api'
AND status_code >= 500
ORDER BY timestamp_utc DESC
LIMIT 200;
明示的な制限により、探索クエリが無制限のインシデント ウィンドウを返さないように保護されます。これは集計レポートの一部ではありません。
例 2: ルートごとにエラー率を計算する
パイプライン言語では、多くの場合、分子が見やすくなり、分母は前の段階で暗黙的に示されます。両方を SQL 結果に保持します。
SELECT
route,
COUNT(*) AS requests,
SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END) AS errors,
ROUND(
100.0 * SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END)
/ NULLIF(COUNT(*), 0),
2
) AS error_rate_pct
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
AND service = 'checkout-api'
GROUP BY route
ORDER BY error_rate_pct DESC, requests DESC;
LogQL は翻訳しないでください count_over_time に COUNT(*) 1 つの解析されたログ エントリが 1 つの SQL 行に対応し、再試行または複数行のメッセージによって粒度が変更されないことを確認するまで。
例 3: タイム チャートを作成する
KQL summarize ... by bin(Timestamp, 5m)、SPL timechart span=5m、および LogQL 範囲集計はすべて時系列を表します。 DataFusion SQL では、ポータブルな最初のステップは時間バケットです。
SELECT
date_trunc('hour', timestamp_utc) AS hour,
release,
COUNT(*) AS requests,
approx_percentile_cont(latency_ms, 0.95) AS p95_latency_ms
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '7 days'
GROUP BY date_trunc('hour', timestamp_utc), release
ORDER BY hour ASC, release ASC;
エンジンによってサポートされ、イベントの量に適したバケットを選択します。最新のバケットが不完全な場合は、除外するか注釈を付けます。
例 4: パイプラインを共通のテーブル式に置き換える
各ステージが前のテーブルを変換するため、パイプラインは読み取り可能です。 SQL の共通テーブル式はその形状を維持できます。
WITH recent_requests AS (
SELECT *
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
AND service = 'checkout-api'
),
route_summary AS (
SELECT
route,
COUNT(*) AS requests,
SUM(CASE WHEN status_code >= 500 THEN 1 ELSE 0 END) AS errors
FROM recent_requests
GROUP BY route
)
SELECT
route,
requests,
errors,
ROUND(100.0 * errors / NULLIF(requests, 0), 2) AS error_rate_pct
FROM route_summary
WHERE requests >= 100
ORDER BY error_rate_pct DESC;
ステージに名前を付けるのではなく、その意味に基づいて名前を付けます。 step1 または filtered。結果として得られるクエリは、レビューやテストが容易です。
解析は移行のリスクです
既存のクエリは、正規表現、JSON 抽出、自動フィールド検出、またはベンダー固有の検索時の解析に依存している場合があります。各派生フィールドのインベントリを作成します。
| 派生フィールド | 新しいイベントフィールド | タイプ | カットオーバー中のフォールバック |
|---|---|---|---|
| リクエストメソッド | method |
文字列カテゴリ | 古いメッセージを解析する |
| ルートテンプレート | route |
文字列カテゴリ | 生のパスをテンプレートにマップする |
| 応答コード | status_code |
整数 | 解析された値をキャストする |
| 期間 | latency_ms |
整数 | 秒またはマイクロ秒を正規化する |
| リリース | release |
文字列カテゴリ | デプロイメントメタデータから強化する |
型付きフィールドが存在し、プロデューサー間で正しくなるまで、デュアル コレクションを実行します。単一の happy-path サービスが一致したため、古いパーサーを削除しないでください。
再設計が必要なベンダー固有の機能
一部の構造は汎用 SQL に強制的に組み込むべきではありません。
- LogQL ストリーム ラベルとラップ解除操作は、ストレージ選択と解析を組み合わせます。
- KQL には、豊富な動的値、時系列、異常関数が備わっています。
- SPL には、検索時のナレッジ オブジェクト、トランザクション、およびコマンド固有の動作があります。
- 各システムは、異なるデフォルトのタイムゾーン、ヌル セマンティクス、制限、および近似集計アルゴリズムを適用します。
ベンダー クエリがインシデントまたはデータ タイプに最適なツールである場合は、ベンダー クエリを保持します。目標は、言語の純粋さではなく、共有された質問のための信頼できる SQL イベント モデルです。
現在のファーストパーティのリファレンスを参照してください。 LogQL クエリの例, Kusto クエリ演算子、そして Splunk 検索リファレンス.
検証とカットオーバー
移行された各クエリについて:
- 代表的な間隔を固定します。
- ソース行数を比較します。
- 異なる操作識別子を比較します。
- null と解析失敗の数を比較します。
- 総計だけでなく、すべての出力グループを比較します。
- 受け入れられている違いを説明する。
- 少なくとも 1 つの通常のトラフィック サイクルを通じて両方のダッシュボードを実行します。
- ユーザーが新しい結果を受け入れるまで、古いクエリへのロールバック リンクを保持します。
使用する SQL クエリのトラブルシューティング エンジンや型式の問題については、 ログを構造化イベントに移行する インストルメンテーションのロールアウト用、および SQL クックブック 完全な契約と視覚的な出力を実現します。