用途
structured-logging 用于在数据分析场景中,用 SQLite 取代临时编写的解析代码。它的核心原则是:SQLite 只是一个文件,无需服务器、无需配置、零依赖。当本来要写自定义解析代码,或同一份数据会被反复处理时,就应改用 SQLite。
决策检查
在编写任何数据分析代码之前,先评估以下问题:
- 数据是否会被查询超过一次?→ 使用 SQLite
- 是否需要 GROUP BY、COUNT、AVG 或 JOIN 操作?→ 使用 SQLite
- 是否即将编写自定义的 Python/jq 解析代码?→ 改用 SQLite
- 数据集是否超过 100 条记录?→ 使用 SQLite
以上任一问题答案为“是”,就使用 SQLite,不要编写自定义解析代码。
示例对比:
自定义代码为每个查询重复编写:
cat data.json | jq '.[] | select(.status=="failed")' | jq -r '.error_type' | sort | uniq -c
SQL 完成同样的工作:
sqlite3 data.db "SELECT error_type, COUNT(*) FROM errors WHERE status='failed' GROUP BY error_type"
何时使用 SQLite
满足以下任一条件时适用:
- 超过 100 条记录——JSON/grep 变得难以处理
- 需要多种聚合——GROUP BY、COUNT、AVG
- 需要多次查询——预期会对同一份数据提出后续问题
- 需要关联——连接来自多个来源的数据
- 需要状态跟踪——需要可查询的进度/状态随时间变化
何时不使用 SQLite
当以下条件全部成立时,跳过 SQLite:
- 总记录数少于 50 条
- 只有单个简单查询
- 不需要聚合
- 不预期有后续问题
对于访问方式简单的小数据集,JSON/grep 即可。
危险信号——应改用 SQLite
当即将做以下事情时,停下来改用 SQLite:
- 编写 Python/Node 代码来解析 JSON/CSV 以进行分析
- 用略有变化的 jq/grep 命令反复运行
- 编写自定义聚合逻辑(在代码中实现 COUNT、AVG、GROUP BY)
- 按时间戳或 ID 手动关联数据
- 创建临时文件存储中间结果
- 为不同问题多次处理同一份数据
以上都意味着:一次性载入 SQLite,用 SQL 查询。
阈值对照
| 场景 | 工具 | 原因 |
|---|---|---|
| 50 条测试结果,一次性汇总 | Python/jq | 快速、合适 |
| 200+ 条测试结果,查找不稳定测试 | SQLite | GROUP BY 比代码更简单 |
| 3 个日志文件,按时间关联 | SQLite | JOIN 比手动 grep 更简单 |
| 跟踪 1000+ 文件处理状态 | SQLite | 查询优于 JSON 解析 |
经验法则:如果正在编写解析代码,或数据会被反复处理,就改用 SQLite。
可用工具
sqlite3(始终可用)
sqlite3 ~/.claude-logs/project.db
sqlite-utils(可选,简化导入)
使用前先检查是否可用:
command -v sqlite-utils >/dev/null 2>&1 && echo "available" || echo "not installed"
如果 sqlite-utils 可用:
sqlite-utils insert data.db table_name data.json --pk=id
sqlite-utils query data.db "SELECT * FROM table"
如果 sqlite-utils 不可用,回退到 sqlite3 手动导入:
sqlite3 data.db <<EOF
CREATE TABLE IF NOT EXISTS results (status TEXT, error_message TEXT);
.mode json
.import data.json results
EOF
也可以安装 sqlite-utils:
uv tool install sqlite-utils
快速开始
存储位置
~/.claude-logs/<project-name>.db # 跨会话持久化
基本工作流
# 1. 连接
PROJECT=$(basename $(git rev-parse --show-toplevel 2>/dev/null || pwd))
sqlite3 ~/.claude-logs/$PROJECT.db
# 2. 创建表(首次)
CREATE TABLE results (
id INTEGER PRIMARY KEY,
name TEXT,
status TEXT,
duration_ms INTEGER
);
# 3. 载入数据
INSERT INTO results (name, status, duration_ms)
SELECT json_extract(value, '$.name'),
json_extract(value, '$.status'),
json_extract(value, '$.duration_ms')
FROM json_each(readfile('data.json'));
# 4. 查询(SQL 完成工作)
SELECT status, COUNT(*), AVG(duration_ms)
FROM results
GROUP BY status;
关键思维转变
从:“处理一次数据就结束” 到:“让数据可查询”
好处:
- 后续问题无需重新处理——数据已载入
- 不同分析可即时针对同一数据集运行
- 状态跨会话持久化
- SQL 处理复杂性——减少自定义代码
附加资源
- ./references/patterns.md——Python 与 SQL 的并排对比及真实示例(测试分析、错误关联、文件处理状态)
限制
资料未提供该技能的具体安装方式、支持的平台范围、收费或价格信息,也未说明除 sqlite3 与 sqlite-utils 之外的其他依赖或限制。