SQL クエリのトラブルシューティング
SQL クエリは、実行に失敗したり、行を返さなかったり、妥当ではあるが間違った結果を生成したりする可能性があります。それらを別の問題として扱います。テーブル、スキーマ、時間範囲を証明する最小の読み取りから始めて、分析ロジックを一度に 1 ステップずつ復元します。
Telemetry は Apache DataFusion SQL を使用します。 PostgreSQL、BigQuery、Snowflake、MySQL、または別のエンジンからコピーされた構文は、分析上のアイデアが適切であっても、書き直す必要がある場合があります。
1. 応答クラスを読み取る
同期クエリ API の場合:
400通常、無効な JSON、SQL の欠落、互換性のない SQL、テーブルまたはフィールドの欠落、または型エラーを意味します401API キーが見つからないか無効であることを意味します403キーに読み取りスコープがないことを意味します429リクエストは待機して制限付きバックオフを使用する必要があることを意味します5xx限られた回数だけ再試行できる
変更されていない無効な SQL を再試行しないでください。安全なエラー テキスト、エンドポイント、およびリクエスト ID をキャプチャしますが、クエリが失敗したという理由だけでキーをログに記録しないでください。
非同期クエリでは queued、running、completed、failed、cancelled を区別します。小さな JSON 結果は result から直接読み取り、大きな JSON 結果と Parquet ファイルは download_url から取得します。結果のエクスポートを参照してください。
2. テーブルと時間範囲を証明する
元のクエリを制限されたサンプルに置き換えます。
SELECT *
FROM api_requests
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
ORDER BY timestamp_utc DESC
LIMIT 10;
これで行が返されない場合:
- 正規化されたテーブル名を確認します
- UTC 時間の範囲を広げる
- オプションのフィルターを削除する
- テーブル ビューで最近のサンプル行とスキーマを検査する
- 一意の識別子を持つ合成イベントを送信する
合成行も欠落している場合は、次のようにします イベント取り込みのトラブルシューティング SQL をさらに編集する前に。
3. フィールド名とタイプを比較する
アプリケーション コードから列名を推測しないでください。ネストされた点線のパスや正確な型を含むテーブル スキーマを検査します。
一般的なエラーには次のようなものがあります。
- 問い合わせる
timestamp生成されたものの代わりにtimestamp_utc - を使用して
durationイベントコントラクトストア時duration_ms - 整数のステータス コードと文字列を比較する
- プロデューサが型を変更した後、数値識別子をテキストとして扱う
- 格納されたスキーマに必要な識別子形式を使用せずにネストされたパスを参照する
- 数値ではないフィールドを集計する
単純な正確なフィールドから始めます SELECT。次に、比較、関数、または集計を追加します。これにより、問題が列の解決にあるのか、それとも列に適用された操作にあるのかが特定されます。
4. レイヤーごとにクエリを削減する
複数の CTE、結合、ウィンドウを含むクエリの場合:
- 最初の CTE を単独で実行する
- 次の CTE を追加し、その行粒度を検査します
- 識別子と行数を表示して各結合をテストします
- 結合された行が正しくなった後に集計を追加します
- ウィンドウ計算を最後に追加します
次のような一時的な診断列を使用します。 COUNT(*) そして COUNT(DISTINCT account_id) 行の乗算を検出します。結果の粒子が理解された後にのみそれらを削除してください。
5. サポートされていない方言構文を翻訳する
で示されている構文を使用します。 DataFusion SQL リファレンス そして テスト済みのレシピライブラリ。特に:
- 使う
SUM(CASE WHEN condition THEN 1 ELSE 0 END)条件付きカウントの場合 - 使う
approx_percentile_cont(latency_ms, 0.95)約p95の場合 - 使う
date_trunc('hour', timestamp_utc)タイムバケット用 - 次のような区間演算を使用します。
now() - INTERVAL '24 hours' - 比率を保護する
NULLIF(denominator, 0) - 使う
LAG(value) OVER (ORDER BY bucket)以前のバケットの比較用
関数名とシグネチャは方言固有です。別のデータベースにある同じ目的の関数は、DataFusion がそのスペルを受け入れるという証拠にはなりません。
6. 空の結果を診断する
空の結果は多くの場合、データが欠落しているのではなく、フィルター操作によるものです。述語を一度に 1 つずつ削除します。
SELECT
environment,
status,
COUNT(*) AS events
FROM workflow_events
WHERE timestamp_utc >= now() - INTERVAL '7 days'
GROUP BY environment, status
ORDER BY events DESC;
これにより、実際に格納されている値が公開されます。狭い述語を復元する前に、大文字と小文字、空白、NULL、名前変更されたステータス、環境境界、および不完全な最近の期間をチェックしてください。
ファネルとコホートの場合、すべてのマイルストーンが同じ ID ユニットを使用していること、および観察ウィンドウが後のステップを実行するのに十分な長さであることを確認します。
7. 合計の前に結合を監査する
それぞれの面で 1 行が何を表しているかを書き留めます。両側に識別子ごとに複数の行が含まれている場合、直接結合により収益、イベント数、またはアクティブ ユーザーが増加する可能性があります。
各面を目的の粒子に事前に集約します。
WITH requests AS (
SELECT
request_id,
MIN(timestamp_utc) AS requested_at
FROM request_events
GROUP BY request_id
),
outcomes AS (
SELECT
request_id,
MAX(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS succeeded
FROM outcome_events
GROUP BY request_id
)
SELECT
COUNT(*) AS requests,
SUM(COALESCE(outcomes.succeeded, 0)) AS succeeded
FROM requests
LEFT JOIN outcomes ON requests.request_id = outcomes.request_id;
結合の前後で個別の識別子を比較します。内部結合によって欠落した結果が消去されるのではなく、一致しない行を意図的に含めます。
8. レート、パーセンタイル、ウィンドウを検証する
レートには分子と分母の両方が必要です。計算が信頼できるまでパーセンテージの横にそれらを返し、グループをランク付けする前に意味のある最小ボリュームを設定します。
パーセンタイルでは、文書化された 1 つの単位を持つ数値フィールドを使用する必要があります。 p50 と p95 を比較して、分布全体が変化したか、それともその末尾のみが変化したかを理解します。
ローリング ウィンドウでは、シリーズの開始時に観測値が少なくなります。最新のタイム バケットが不完全である可能性があります。ローリング ベースラインでアラートを生成する前に、両方の条件にラベルを付けるか除外します。
9. フィクスチャを使用して期待される結果を証明する
答えを手動で計算できる小さな合成フィクスチャを作成します。
- 一つの成功
- 1 つの永続的な障害
- 後で回復する 1 つの失敗
- 1 つの重複した識別子
- 1 つの null オプションフィールド
- 正確に時間境界上の 1 つのイベント
中間 CTE を実行し、最終行を予想される答えと比較します。計画では構文と型を証明します。備品は解釈を証明するのに役立ちます。
クエリレビューチェックリスト
- 正確なテーブルとスキーマが検査されました
- UTC ウィンドウとバケットの完全性が確認されました
- フィールドのタイプと単位が操作と一致する
- すべての結合の前に行粒度を文書化する
- 分子、分母、および表示される最小ボリューム
- 再試行、重複、遅延イベント、および null には明示的な動作があります
- 合成境界ケースが期待される出力と一致する
- 保存された結果には定義、所有者、応答が含まれます
Telemetry は、エンジンのバージョンと自動チェックを公開します。 SQL テスト方法。のレシピからスタート API の信頼性, バックグラウンドジョブ, 製品分析、または データ品質 既知の互換性のあるパターンが必要な場合。