sparksql-error-analyzer
SKILL.md
Spark SQL Error Analyzer
分析 Spark SQL 报错日志,识别错误原因并提供解决方案代码。
使用场景
- 分析 Spark SQL 执行异常
- 解析报错日志并提供修复方案
- 优化 SQL 语句解决性能问题
- 处理语法错误和逻辑错误
输入格式
用户提供以下信息:
- 错误日志 (error_log): Spark SQL 的报错日志或异常堆栈
- SQL 语句 (sql_statement): 出错的 SQL 语句
分析流程
步骤 1: 解析错误日志(使用脚本)
使用 scripts/parse_sparksql_error.py 脚本自动解析错误日志:
# 方式 1: 从文件读取
python scripts/parse_sparksql_error.py error.log sql_query.sql
# 方式 2: 从标准输入读取
echo '<错误日志内容>' | python scripts/parse_sparksql_error.py -
脚本输出 JSON 格式的解析结果,包含:
error_type: 错误类型error_code: 错误代码error_message: 错误描述root_cause: 根本原因affected_objects: 涉及的表、列等suggestions: 修复建议列表sql_analysis: SQL 结构分析(如果提供了 SQL 文件)
手动解析要点:
-
识别错误类型和关键信息:
- 异常类型(如
AnalysisException,ParseException,SparkException) - 错误代码(如
TABLE_OR_VIEW_NOT_FOUND,COLUMN_NOT_FOUND) - 错误位置(行号、列名、表名等)
- 根本原因(Root Cause)
- 异常类型(如
-
常见错误类型分类:
错误类型 典型特征 常见原因 语法错误 ParseExceptionSQL 语法不正确、关键字拼写错误 分析错误 AnalysisException表/列不存在、类型不匹配 运行时错误 SparkException数据问题、内存不足、执行超时 资源错误 OutOfMemoryError数据倾斜、分区不当
步骤 2: 分析 SQL 语句
使用脚本分析:
# 在 Python 中调用分析函数
from scripts.parse_sparksql_error import analyze_sql_structure
sql_info = analyze_sql_structure("SELECT * FROM users WHERE age > 18")
print(sql_info)
# 输出: {
# 'sql_type': 'SELECT',
# 'tables': ['users'],
# 'joins': [],
# 'aggregations': [],
# 'potential_issues': ['建议添加 LIMIT 限制返回行数']
# }
手动分析要点:
-
检查 SQL 结构:
- SELECT / JOIN / WHERE / GROUP BY / ORDER BY 等子句
- 子查询和嵌套查询
- 窗口函数和聚合函数
- UDF 使用
-
识别潜在问题:
- 隐式类型转换
- 笛卡尔积风险
- 数据倾斜迹象
- 性能瓶颈
步骤 3: 生成分析报告
输出结构化的分析结果:
## 错误分析
### 错误类型
[具体错误类型]
### 错误原因
[详细解释错误产生的根本原因]
### 涉及对象
- 表: [表名列表]
- 列: [列名列表]
- 函数: [函数名列表]
## 解决方案
### 方案 1: [方案标题]
**适用场景**: [说明适用情况]
**修复代码**:
```sql
[修复后的 SQL 代码]
说明: [详细解释修复原理]
方案 2: [备选方案,如有]
...
预防措施
- [建议 1]
- [建议 2]
- [建议 3]
## 常见错误模式与解决方案
### 1. 表或视图不存在 (TABLE_OR_VIEW_NOT_FOUND)
**错误特征**:
AnalysisException: [TABLE_OR_VIEW_NOT_FOUND] The table or view xxx cannot be found
**解决方案**:
- 检查表名拼写
- 确认数据库/Schema 正确
- 使用 `SHOW TABLES` 验证表存在
- 添加数据库前缀: `database.table`
### 2. 列不存在 (COLUMN_NOT_FOUND)
**错误特征**:
AnalysisException: [COLUMN_NOT_FOUND] Column 'xxx' does not exist
**解决方案**:
- 检查列名拼写
- 使用 `DESCRIBE table_name` 查看可用列
- 检查是否使用了别名后引用原列名
### 3. 类型不匹配 (DATATYPE_MISMATCH)
**错误特征**:
AnalysisException: [DATATYPE_MISMATCH] Cannot resolve column due to data type mismatch
**解决方案**:
- 使用 `CAST(column AS type)` 进行显式转换
- 检查 JOIN 条件的类型一致性
- 处理 NULL 值
### 4. 内存不足 (OutOfMemoryError)
**错误特征**:
java.lang.OutOfMemoryError: Java heap space
**解决方案**:
- 增加 executor 内存
- 优化数据分区
- 使用 `spark.sql.adaptive.enabled=true`
- 减少数据倾斜
### 5. 数据倾斜
**错误特征**:
Task xxx failed due to data skew
或执行极慢,某些 task 耗时过长
**解决方案**:
- 添加盐值 (salt) 打散热点 key
- 使用两阶段聚合
- 调整分区数
## 最佳实践
### SQL 编写建议
1. 使用显式 JOIN 语法,避免隐式 JOIN
2. 尽早过滤数据(谓词下推)
3. 避免 SELECT *,只选择需要的列
4. 合理使用分区裁剪
### 性能优化建议
1. 大表 JOIN 时确保分区/桶策略合理
2. 使用广播 JOIN 处理小表
3. 避免在 WHERE 中对列进行函数操作
4. 合理使用缓存 `CACHE TABLE`
### 调试技巧
1. 使用 `EXPLAIN` 查看执行计划
2. 使用 `EXPLAIN EXTENDED` 查看详细计划
3. 开启 `spark.sql.adaptive.enabled` 自动优化
4. 查看 Spark UI 分析 task 分布
## 示例
### 示例 1: 列不存在错误
**输入**:
- 错误日志: `AnalysisException: [COLUMN_NOT_FOUND] Column 'user_id' does not exist`
- SQL: `SELECT user_id, name FROM users`
**分析输出**:
```markdown
## 错误分析
### 错误类型
AnalysisException - COLUMN_NOT_FOUND
### 错误原因
SQL 中引用的列 `user_id` 在表 `users` 中不存在
### 涉及对象
- 表: users
- 列: user_id (不存在的列)
## 解决方案
### 方案 1: 修正列名
**适用场景**: 列名拼写错误
**修复代码**:
```sql
-- 先查看表结构
DESCRIBE users;
-- 假设正确的列名是 id
SELECT id, name FROM users;
说明: 使用 DESCRIBE 命令确认表的实际列名,然后修正 SQL 中的列引用。
预防措施
- 编写 SQL 前先查看表结构
- 使用 IDE 的自动补全功能
- 建立数据字典文档
### 示例 2: 类型不匹配错误
**输入**:
- 错误日志: `AnalysisException: [DATATYPE_MISMATCH] Cannot resolve 'date_col' due to data type mismatch`
- SQL: `SELECT * FROM logs WHERE date_col > '2024-01-01'`
**分析输出**:
```markdown
## 错误分析
### 错误类型
AnalysisException - DATATYPE_MISMATCH
### 错误原因
`date_col` 列的类型与字符串 '2024-01-01' 不匹配,可能是数值类型或日期类型不匹配
### 涉及对象
- 表: logs
- 列: date_col
## 解决方案
### 方案 1: 显式类型转换
**适用场景**: date_col 是 DATE/TIMESTAMP 类型
**修复代码**:
```sql
SELECT * FROM logs WHERE date_col > DATE '2024-01-01';
-- 或
SELECT * FROM logs WHERE date_col > CAST('2024-01-01' AS DATE);
方案 2: 转换为字符串比较
适用场景: date_col 是字符串类型,存储格式为 'yyyy-MM-dd'
修复代码:
SELECT * FROM logs WHERE date_col > '2024-01-01';
-- 确保格式一致
预防措施
- 定义表时使用合适的类型
- 比较时确保类型一致
- 避免隐式类型转换
## 脚本使用指南
### parse_sparksql_error.py 完整用法
```bash
# 基本用法 - 只分析错误日志
python scripts/parse_sparksql_error.py error.log
# 完整用法 - 同时分析错误日志和 SQL
python scripts/parse_sparksql_error.py error.log query.sql
# 从管道输入错误日志
cat error.log | python scripts/parse_sparksql_error.py -
# 直接在命令行传入错误日志
echo "AnalysisException: [COLUMN_NOT_FOUND] Column 'xxx' does not exist" | python scripts/parse_sparksql_error.py -
脚本功能
-
错误解析 (
SparkSQLErrorParser类):- 自动识别 10+ 种常见 Spark SQL 错误
- 提取错误代码、类型、涉及对象
- 生成针对性的修复建议
-
SQL 分析 (
analyze_sql_structure函数):- 识别 SQL 类型 (SELECT/INSERT/UPDATE/DELETE 等)
- 提取涉及的表名、JOIN 类型、聚合函数
- 检测潜在问题 (SELECT *、隐式 JOIN 等)
-
输出格式:
{ "error_analysis": { "error_type": "AnalysisException", "error_code": "COLUMN_NOT_FOUND", "error_message": "列不存在", "root_cause": "...", "affected_objects": { "tables": [], "columns": ["xxx"] }, "suggestions": [...] }, "sql_analysis": { "sql_type": "SELECT", "tables": ["users"], "potential_issues": [...] } }
注意事项
- 隐私保护: 分析时注意隐藏敏感数据(如用户 ID、手机号等)
- 上下文理解: 结合业务逻辑理解 SQL 意图
- 多方案提供: 复杂问题提供多个解决方案供选择
- 验证建议: 建议用户在小数据集上验证修复方案
- 脚本依赖: 脚本使用 Python 3 标准库,无需额外安装依赖