SQL 查詢故障排除
SQL 查詢可能無法執行、不返回任何行或生成看似合理但不正確的結果。將這些視為不同的問題。從證明資料表、模式和時間範圍的最小讀取開始,然後一步一步地恢複分析邏輯。
Telemetry 使用 Apache DataFusion SQL。即使分析思路是合理的,從 PostgreSQL、BigQuery、Snowflake、MySQL 或其他引擎複製的語法也可能需要重寫。
1.讀取回應類
對於同步查詢API:
400通常意味著無效的JSON、缺少SQL、不相容的SQL、缺少資料表或欄位或者型別錯誤401表示 API 金鑰丟失或無效403表示金鑰缺少讀取範圍429表示請求應該等待並使用有界退避5xx可以重試有限次數
請勿重試未更改的無效 SQL。捕獲安全錯誤文字、端點和請求 ID,但切勿僅僅因為查詢失敗而記錄金鑰。
非同步查詢請區分 queued、running、completed、failed 和 cancelled。從 result 直接讀取較小的 JSON 結果;從 download_url 下載較大的 JSON 結果和 Parquet 檔案。請參閱匯出查詢結果。
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_ms時使用duration - 將整數狀態程式碼與字串進行比較
- 在生產者更改型別後將數字識別符號視為文字
- 引用沒有儲存模式所需的識別符號形式的巢狀路徑
- 聚合非數字欄位
從簡單的 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. 診斷空結果
空結果通常是過濾器互動,而不是丟失資料。一次刪除一個謂詞:
SELECT
environment,
status,
COUNT(*) AS events
FROM workflow_events
WHERE timestamp_utc >= now() - INTERVAL '7 days'
GROUP BY environment, status
ORDER BY events DESC;
這公開了實際儲存的值。在恢復狹窄謂詞之前檢查大小寫、空格、空值、重新命名狀態、環境邊界和不完整的最近週期。
對於漏斗和佇列,確認每個里程碑都使用相同的身分單位,並且觀察視窗足夠長,以便後續步驟發生。
7. 在總計之前審查加入
寫下每一行代表什麼。如果雙方每個識別符號都包含多行,則直接聯接可能會增加收入、事件計數或活躍使用者數。
將每一面預先聚集到預期的顆粒上:
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. 驗證比率、百分位數和視窗
比率需要分子和分母。將它們返回到百分比旁邊,直到計算可信為止,並在對組進行排名之前設定最小有意義的數量。
百分位數應使用帶有一個記錄單位的數字欄位。比較 p50 和 p95,瞭解是整個分佈發生變化還是僅尾部發生變化。
在本系列開始時,滾動視窗的觀察較少。最新的時間段可能不完整。在滾動基線上發出警示之前標記或排除這兩種情況。
9. 用夾具證明預期結果
建立一個小型合成夾具,其答案可以手動計算:
- 一次成功
- 一次永久性故障
- 一次故障隨後恢復
- 一個重複的識別符號
- 一個空可選欄位
- 一個事件正好發生在一個時間界限上
執行中間 CTE 並將最終行與預期答案進行比較。規劃證明語法和型別;固定裝置有助於證明解釋。
查詢審查清單
- 檢查了精確的資料表和模式
- UTC 視窗和儲存桶完整性已確認
- 欄位型別和單位與操作相匹配
- 在每次連線之前記錄行粒度
- 分子、分母和可見的最小體積
- 重試、重複、延遲事件和空值具有明確的行為
- 合成邊界情況與預期輸出匹配
- 儲存的結果包括定義、所有者和回應
Telemetry 在 SQL測試方法 中發布引擎版本和自動檢查。當您需要已知的相容模式時,請從 API 可靠性、後台工作、產品分析 或 資料品質 中的配方開始。