SQL优化器 logo

SQL优化器

Organization
microwind
SQL优化器

当优化SQL查询时,分析执行计划,检查索引使用,优化查询性能。验证SQL语法,分析查询复杂度,和最佳实践。

Overview

Publishermicrowind
Repositoryai-skills
Skill nameSQL优化器
Stars
93
Forks
25
Bundled files
4
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 4 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by microwind on GitHub. Read the source before you install it.

Installation

Install the SQL优化器 AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/microwind/ai-skills/tree/main/database/sql-optimizer
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/microwind/ai-skills.git /tmp/ai-skills
mkdir -p .claude/skills
cp -r /tmp/ai-skills/database/sql-optimizer .claude/skills/microwind-sql-2
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable SQL优化器 in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads SQL优化器 on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so SQL优化器 is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

SQL优化器技能

概述

慢SQL查询会复合影响。一个慢查询会影响100个事务。在扩展之前先优化。需要建立完善的SQL查询分析和优化机制。

核心原则: 慢SQL查询会复合影响。一个慢查询会影响100个事务。在扩展之前先优化。

何时使用

始终:

  • 优化慢查询
  • 数据库性能问题
  • 扩展数据库之前
  • 性能分析后的查询调优
  • 索引设计优化
  • 查询性能监控

触发短语:

  • "优化这个SQL查询"
  • "查询太慢了"
  • "如何优化数据库性能?"
  • "检查SQL执行计划"
  • "索引怎么设计?"
  • "SQL性能分析"

SQL优化功能

查询分析

  • 执行计划分析
  • 查询复杂度评估
  • 索引使用检查
  • 统计信息分析
  • 性能瓶颈识别

索引优化

  • 索引设计建议
  • 索引使用效率分析
  • 冗余索引检测
  • 索引优化方案
  • 覆盖索引设计

性能调优

  • 查询重写建议
  • 表结构优化
  • 分区策略分析
  • 缓存优化建议
  • 参数调优

常见SQL性能问题

缺少索引

问题:
查询条件没有合适的索引支持

后果:
- 全表扫描
- 查询速度慢
- CPU占用高
- 锁竞争严重

解决方案:
- 创建合适的索引
- 复合索引优化
- 覆盖索引设计
- 索引选择性分析

查询设计不当

问题:
SQL查询语句设计不合理

后果:
- 执行计划不优
- 资源浪费
- 性能下降
- 扩展性差

解决方案:
- 重写查询语句
- 避免子查询
- 优化JOIN操作
- 减少数据传输

统计信息过时

问题:
数据库统计信息不准确

后果:
- 执行计划错误
- 索引选择不当
- 查询性能下降
- 资源分配不合理

解决方案:
- 更新统计信息
- 定期维护
- 自动统计收集
- 手动统计更新

SQL优化策略

查询重写技巧

避免子查询:
- 使用JOIN替代子查询
- 使用EXISTS替代IN
- 优化相关子查询
- 减少嵌套层次

优化JOIN:
- 选择合适的JOIN类型
- 确保连接字段有索引
- 减少JOIN的数据量
- 优化JOIN顺序

索引设计原则

单列索引:
- 高选择性字段
- 频繁查询条件
- 排序字段
- 外键字段

复合索引:
- 多条件查询
- 字段顺序重要
- 覆盖查询需求
- 减少回表查询

代码实现示例

SQL查询优化器

python
import re
import sqlparse
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass
from enum import Enum

class QueryType(Enum):
    SELECT = "SELECT"
    INSERT = "INSERT"
    UPDATE = "UPDATE"
    DELETE = "DELETE"
    CREATE = "CREATE"
    DROP = "DROP"
    ALTER = "ALTER"

@dataclass
class QueryAnalysis:
    """查询分析结果"""
    query_type: QueryType
    complexity_score: int
    tables: List[str]
    columns: List[str]
    joins: List[Dict[str, str]]
    where_conditions: List[str]
    group_by: List[str]
    order_by: List[str]
    issues: List[str]
    recommendations: List[str]
    execution_plan: Optional[Dict[str, Any]] = None

class SQLOptimizer:
    """SQL查询优化器"""
    
    def __init__(self):
        self.optimization_rules = self._setup_optimization_rules()
        self.index_suggestions = []
        self.performance_metrics = {}
    
    def analyze_query(self, query: str) -> QueryAnalysis:
        """分析SQL查询"""
        # 格式化SQL
        formatted_query = sqlparse.format(query, reindent=True, keyword_case='upper')
        
        # 解析查询类型
        query_type = self._detect_query_type(formatted_query)
        
        # 提取查询组件
        tables = self._extract_tables(formatted_query)
        columns = self._extract_columns(formatted_query)
        joins = self._extract_joins(formatted_query)
        where_conditions = self._extract_where_conditions(formatted_query)
        group_by = self._extract_group_by(formatted_query)
        order_by = self._extract_order_by(formatted_query)
        
        # 计算复杂度
        complexity_score = self._calculate_complexity(
            tables, columns, joins, where_conditions, group_by, order_by
        )
        
        # 分析问题和建议
        issues = []
        recommendations = []
        
        self._analyze_performance_issues(
            query_type, tables, columns, joins, where_conditions, 
            group_by, order_by, issues, recommendations
        )
        
        return QueryAnalysis(
            query_type=query_type,
            complexity_score=complexity_score,
            tables=tables,
            columns=columns,
            joins=joins,
            where_conditions=where_conditions,
            group_by=group_by,
            order_by=order_by,
            issues=issues,
            recommendations=recommendations
        )
    
    def optimize_query(self, query: str) -> Dict[str, Any]:
        """优化SQL查询"""
        analysis = self.analyze_query(query)
        
        optimized_query = query
        optimizations_applied = []
        
        # 应用优化规则
        for rule in self.optimization_rules:
            result = rule.apply(optimized_query, analysis)
            if result.modified:
                optimized_query = result.query
                optimizations_applied.append(rule.name)
        
        # 生成索引建议
        index_suggestions = self._generate_index_suggestions(analysis)
        
        # 生成执行计划建议
        execution_plan_hints = self._generate_execution_plan_hints(analysis)
        
        return {
            'original_query': query,
            'optimized_query': optimized_query,
            'analysis': analysis,
            'optimizations_applied': optimizations_applied,
            'index_suggestions': index_suggestions,
            'execution_plan_hints': execution_plan_hints,
            'performance_improvement_estimate': self._estimate_improvement(analysis)
        }
    
    def _detect_query_type(self, query: str) -> QueryType:
        """检测查询类型"""
        query_upper = query.strip().upper()
        
        if query_upper.startswith('SELECT'):
            return QueryType.SELECT
        elif query_upper.startswith('INSERT'):
            return QueryType.INSERT
        elif query_upper.startswith('UPDATE'):
            return QueryType.UPDATE
        elif query_upper.startswith('DELETE'):
            return QueryType.DELETE
        elif query_upper.startswith('CREATE'):
            return QueryType.CREATE
        elif query_upper.startswith('DROP'):
            return QueryType.DROP
        elif query_upper.startswith('ALTER'):
            return QueryType.ALTER
        else:
            return QueryType.SELECT  # 默认
    
    def _extract_tables(self, query: str) -> List[str]:
        """提取表名"""
        tables = []
        
        # 使用正则表达式提取表名
        # FROM子句
        from_pattern = r'FROM\s+([a-zA-Z_][a-zA-Z0-9_]*)'
        from_matches = re.findall(from_pattern, query, re.IGNORECASE)
        tables.extend(from_matches)
        
        # JOIN子句
        join_pattern = r'JOIN\s+([a-zA-Z_][a-zA-Z0-9_]*)'
        join_matches = re.findall(join_pattern, query, re.IGNORECASE)
        tables.extend(join_matches)
        
        # INSERT INTO子句
        insert_pattern = r'INSERT\s+INTO\s+([a-zA-Z_][a-zA-Z0-9_]*)'
        insert_matches = re.findall(insert_pattern, query, re.IGNORECASE)
        tables.extend(insert_matches)
        
        # UPDATE子句
        update_pattern = r'UPDATE\s+([a-zA-Z_][a-zA-Z0-9_]*)'
        update_matches = re.findall(update_pattern, query, re.IGNORECASE)
        tables.extend(update_matches)
        
        return list(set(tables))  # 去重
    
    def _extract_columns(self, query: str) -> List[str]:
        """提取列名"""
        columns = []
        
        # SELECT子句中的列
        select_pattern = r'SELECT\s+(.*?)\s+FROM'
        select_match = re.search(select_pattern, query, re.IGNORECASE | re.DOTALL)
        if select_match:
            select_clause = select_match.group(1)
            
            # 排除函数和聚合
            if select_clause != '*':
                # 简单的列名提取
                column_pattern = r'([a-zA-Z_][a-zA-Z0-9_]*)\s*(?:,|$|\s+FROM)'
                column_matches = re.findall(column_pattern, select_clause)
                columns.extend(column_matches)
        
        return list(set(columns))
    
    def _extract_joins(self, query: str) -> List[Dict[str, str]]:
        """提取JOIN信息"""
        joins = []
        
        # JOIN模式
        join_pattern = r'(INNER|LEFT|RIGHT|FULL|CROSS)\s+JOIN\s+([a-zA-Z_][a-zA-Z0-9_]*)\s+ON\s+([^JOIN]+)'
        join_matches = re.findall(join_pattern, query, re.IGNORECASE)
        
        for join_type, table, condition in join_matches:
            joins.append({
                'type': join_type.upper(),
                'table': table,
                'condition': condition.strip()
            })
        
        return joins
    
    def _extract_where_conditions(self, query: str) -> List[str]:
        """提取WHERE条件"""
        conditions = []
        
        where_pattern = r'WHERE\s+(.*?)(?:\s+GROUP\s+BY|\s+ORDER\s+BY|\s+LIMIT|$)'
        where_match = re.search(where_pattern, query, re.IGNORECASE | re.DOTALL)
        
        if where_match:
            where_clause = where_match.group(1)
            # 分割AND和OR条件
            and_conditions = re.split(r'\s+AND\s+', where_clause, flags=re.IGNORECASE)
            for condition in and_conditions:
                or_conditions = re.split(r'\s+OR\s+', condition, flags=re.IGNORECASE)
                conditions.extend([c.strip() for c in or_conditions])
        
        return conditions
    
    def _extract_group_by(self, query: str) -> List[str]:
        """提取GROUP BY字段"""
        group_by = []
        
        group_pattern = r'GROUP\s+BY\s+(.*?)(?:\s+ORDER\s+BY|\s+LIMIT|$)'
        group_match = re.search(group_pattern, query, re.IGNORECASE)
        
        if group_match:
            group_clause = group_match.group(1)
            group_by = [col.strip() for col in group_clause.split(',')]
        
        return group_by
    
    def _extract_order_by(self, query: str) -> List[str]:
        """提取ORDER BY字段"""
        order_by = []
        
        order_pattern = r'ORDER\s+BY\s+(.*?)(?:\s+LIMIT|$)'
        order_match = re.search(order_pattern, query, re.IGNORECASE)
        
        if order_match:
            order_clause = order_match.group(1)
            order_by = [col.strip() for col in order_clause.split(',')]
        
        return order_by
    
    def _calculate_complexity(self, tables: List[str], columns: List[str], 
                            joins: List[Dict], where_conditions: List[str],
                            group_by: List[str], order_by: List[str]) -> int:
        """计算查询复杂度"""
        score = 0
        
        # 表数量影响
        score += len(tables) * 10
        
        # 列数量影响
        score += len(columns) * 2
        
        # JOIN影响
        score += len(joins) * 15
        
        # WHERE条件影响
        score += len(where_conditions) * 5
        
        # GROUP BY影响
        score += len(group_by) * 8
        
        # ORDER BY影响
        score += len(order_by) * 3
        
        # 子查询影响
        # 这里简化处理,实际应该解析嵌套层次
        
        return score
    
    def _analyze_performance_issues(self, query_type: QueryType, tables: List[str],
                                  columns: List[str], joins: List[Dict],
                                  where_conditions: List[str], group_by: List[str],
                                  order_by: List[str], issues: List[str],
                                  recommendations: List[str]):
        """分析性能问题"""
        
        # 检查SELECT *
        if query_type == QueryType.SELECT and '*' in columns:
            issues.append("查询使用了SELECT *,可能返回不必要的数据")
            recommendations.append("只查询需要的列,避免使用SELECT *")
        
        # 检查JOIN数量
        if len(joins) > 5:
            issues.append(f"查询包含过多JOIN操作({len(joins)}个)")
            recommendations.append("考虑分解复杂查询或优化表结构")
        
        # 检查WHERE条件
        if not where_conditions and query_type == QueryType.SELECT:
            issues.append("查询缺少WHERE条件,可能扫描全表")
            recommendations.append("添加适当的WHERE条件限制数据范围")
        
        # 检查GROUP BY和ORDER BY
        if group_by and order_by:
            if set(group_by) & set(order_by):
                recommendations.append("GROUP BY和ORDER BY使用相同字段,可以利用索引")
        
        # 检查表数量
        if len(tables) > 10:
            issues.append(f"查询涉及过多表({len(tables)}个)")
            recommendations.append("考虑使用视图或分解查询")
    
    def _generate_index_suggestions(self, analysis: QueryAnalysis) -> List[Dict[str, Any]]:
        """生成索引建议"""
        suggestions = []
        
        # 基于WHERE条件建议索引
        for condition in analysis.where_conditions:
            # 简单的字段提取
            field_pattern = r'([a-zA-Z_][a-zA-Z0-9_]*)\s*[=<>!]'
            field_matches = re.findall(field_pattern, condition)
            
            for field in field_matches:
                suggestions.append({
                    'type': 'single_column',
                    'table': analysis.tables[0] if analysis.tables else 'unknown',
                    'column': field,
                    'reason': f'WHERE条件中使用: {condition}',
                    'priority': 'high'
                })
        
        # 基于JOIN条件建议索引
        for join in analysis.joins:
            # 提取JOIN字段
            condition = join['condition']
            field_pattern = r'([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_][a-zA-Z0-9_]*)'
            field_matches = re.findall(field_pattern, condition)
            
            for table1, table2, field in field_matches:
                suggestions.append({
                    'type': 'foreign_key',
                    'table': table1,
                    'column': field,
                    'reason': f'JOIN条件: {condition}',
                    'priority': 'high'
                })
        
        # 基于ORDER BY建议索引
        if analysis.order_by:
            for field in analysis.order_by:
                clean_field = field.split()[0]  # 移除ASC/DESC
                suggestions.append({
                    'type': 'order_by',
                    'table': analysis.tables[0] if analysis.tables else 'unknown',
                    'column': clean_field,
                    'reason': f'ORDER BY使用: {field}',
                    'priority': 'medium'
                })
        
        return suggestions
    
    def _generate_execution_plan_hints(self, analysis: QueryAnalysis) -> List[str]:
        """生成执行计划提示"""
        hints = []
        
        if analysis.complexity_score > 100:
            hints.append("查询复杂度较高,建议分解为多个简单查询")
        
        if len(analysis.joins) > 3:
            hints.append("考虑使用EXISTS替代部分JOIN操作")
        
        if analysis.group_by and len(analysis.group_by) > 3:
            hints.append("GROUP BY字段较多,考虑使用覆盖索引")
        
        return hints
    
    def _estimate_improvement(self, analysis: QueryAnalysis) -> Dict[str, float]:
        """估算性能提升"""
        improvement = {
            'query_speed': 0.0,
            'resource_usage': 0.0,
            'scalability': 0.0
        }
        
        # 基于问题数量估算
        issue_count = len(analysis.issues)
        if issue_count > 0:
            improvement['query_speed'] = min(0.8, issue_count * 0.15)
            improvement['resource_usage'] = min(0.6, issue_count * 0.12)
            improvement['scalability'] = min(0.4, issue_count * 0.08)
        
        return improvement
    
    def _setup_optimization_rules(self) -> List['OptimizationRule']:
        """设置优化规则"""
        return [
            SelectStarOptimization(),
            SubqueryOptimization(),
            JoinOptimization(),
            WhereOptimization(),
            IndexHintOptimization()
        ]

class OptimizationRule:
    """优化规则基类"""
    
    def __init__(self, name: str):
        self.name = name
    
    def apply(self, query: str, analysis: QueryAnalysis) -> 'OptimizationResult':
        """应用优化规则"""
        raise NotImplementedError

@dataclass
class OptimizationResult:
    """优化结果"""
    query: str
    modified: bool
    reason: str

class SelectStarOptimization(OptimizationRule):
    """SELECT *优化"""
    
    def __init__(self):
        super().__init__("SELECT *优化")
    
    def apply(self, query: str, analysis: QueryAnalysis) -> OptimizationResult:
        if '*' in analysis.columns:
            # 这里应该根据实际表结构替换*
            # 简化处理,提示用户手动优化
            return OptimizationResult(
                query=query,
                modified=False,
                reason="需要手动指定具体列名替代SELECT *"
            )
        
        return OptimizationResult(query=query, modified=False, reason="无需优化")

class SubqueryOptimization(OptimizationRule):
    """子查询优化"""
    
    def __init__(self):
        super().__init__("子查询优化")
    
    def apply(self, query: str, analysis: QueryAnalysis) -> OptimizationResult:
        # 检查是否可以转换为JOIN
        # 简化处理
        optimized_query = query
        
        # 检查IN子查询
        in_pattern = r'IN\s*\(\s*SELECT\s+.*?\)'
        if re.search(in_pattern, optimized_query, re.IGNORECASE | re.DOTALL):
            # 可以建议使用EXISTS或JOIN替代
            return OptimizationResult(
                query=optimized_query,
                modified=False,
                reason="建议使用EXISTS或JOIN替代IN子查询"
            )
        
        return OptimizationResult(query=optimized_query, modified=False, reason="无需优化")

class JoinOptimization(OptimizationRule):
    """JOIN优化"""
    
    def __init__(self):
        super().__init__("JOIN优化")
    
    def apply(self, query: str, analysis: QueryAnalysis) -> OptimizationResult:
        optimized_query = query
        
        # 检查JOIN顺序
        if len(analysis.joins) > 2:
            return OptimizationResult(
                query=optimized_query,
                modified=False,
                reason="建议优化JOIN顺序,小表在前"
            )
        
        return OptimizationResult(query=optimized_query, modified=False, reason="无需优化")

class WhereOptimization(OptimizationRule):
    """WHERE条件优化"""
    
    def __init__(self):
        super().__init__("WHERE条件优化")
    
    def apply(self, query: str, analysis: QueryAnalysis) -> OptimizationResult:
        optimized_query = query
        
        # 检查函数使用
        for condition in analysis.where_conditions:
            if re.search(r'[A-Z_]+\(', condition, re.IGNORECASE):
                return OptimizationResult(
                    query=optimized_query,
                    modified=False,
                    reason="WHERE条件中使用了函数,可能影响索引使用"
                )
        
        return OptimizationResult(query=optimized_query, modified=False, reason="无需优化")

class IndexHintOptimization(OptimizationRule):
    """索引提示优化"""
    
    def __init__(self):
        super().__init__("索引提示优化")
    
    def apply(self, query: str, analysis: QueryAnalysis) -> OptimizationResult:
        # 可以添加索引提示
        # 简化处理
        return OptimizationResult(
            query=query,
            modified=False,
            reason="可以考虑添加索引提示"
        )

# 使用示例
def main():
    optimizer = SQLOptimizer()
    
    # 示例查询
    sample_queries = [
        """
        SELECT u.name, o.order_date, p.product_name
        FROM users u
        INNER JOIN orders o ON u.id = o.user_id
        INNER JOIN order_items oi ON o.id = oi.order_id
        INNER JOIN products p ON oi.product_id = p.id
        WHERE u.status = 'active' AND o.order_date > '2023-01-01'
        ORDER BY o.order_date DESC
        """,
        
        """
        SELECT * FROM products WHERE price > 100
        """,
        
        """
        SELECT COUNT(*) FROM orders WHERE user_id IN (SELECT id FROM users WHERE status = 'active')
        """
    ]
    
    for i, query in enumerate(sample_queries, 1):
        print(f"\n=== 查询 {i} ===")
        print(f"原始查询: {query.strip()}")
        
        # 分析查询
        analysis = optimizer.analyze_query(query)
        print(f"查询类型: {analysis.query_type.value}")
        print(f"复杂度分数: {analysis.complexity_score}")
        print(f"涉及表: {analysis.tables}")
        print(f"涉及列: {analysis.columns}")
        
        if analysis.issues:
            print("发现的问题:")
            for issue in analysis.issues:
                print(f"  - {issue}")
        
        if analysis.recommendations:
            print("优化建议:")
            for rec in analysis.recommendations:
                print(f"  - {rec}")
        
        # 优化查询
        optimization = optimizer.optimize_query(query)
        print(f"优化后查询: {optimization['optimized_query'].strip()}")
        
        if optimization['index_suggestions']:
            print("索引建议:")
            for suggestion in optimization['index_suggestions']:
                print(f"  - {suggestion['table']}.{suggestion['column']} ({suggestion['type']}) - {suggestion['reason']}")
        
        improvement = optimization['performance_improvement_estimate']
        print(f"预计性能提升: 查询速度{improvement['query_speed']:.1%}, 资源使用{improvement['resource_usage']:.1%}")

if __name__ == "__main__":
    main()

数据库性能监控

python
import time
import psycopg2
from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from datetime import datetime, timedelta
import statistics

@dataclass
class PerformanceMetrics:
    """性能指标"""
    query_time: float
    rows_examined: int
    rows_returned: int
    index_usage: Dict[str, int]
    buffer_usage: Dict[str, int]
    cpu_usage: float
    memory_usage: float

class DatabasePerformanceMonitor:
    """数据库性能监控"""
    
    def __init__(self, connection_string: str):
        self.connection_string = connection_string
        self.metrics_history = []
        self.slow_queries = []
    
    def monitor_query_performance(self, query: str, params: tuple = None) -> PerformanceMetrics:
        """监控查询性能"""
        start_time = time.time()
        
        with psycopg2.connect(self.connection_string) as conn:
            with conn.cursor() as cursor:
                # 执行EXPLAIN ANALYZE
                explain_query = f"EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) {query}"
                cursor.execute(explain_query, params)
                explain_result = cursor.fetchone()[0]
                
                # 执行实际查询
                cursor.execute(query, params)
                rows = cursor.fetchall()
        
        end_time = time.time()
        
        # 解析执行计划
        plan = explain_result[0]
        
        metrics = PerformanceMetrics(
            query_time=end_time - start_time,
            rows_examined=plan.get('Actual Rows', 0),
            rows_returned=len(rows),
            index_usage=self._extract_index_usage(plan),
            buffer_usage=self._extract_buffer_usage(plan),
            cpu_usage=self._get_cpu_usage(),
            memory_usage=self._get_memory_usage()
        )
        
        self.metrics_history.append(metrics)
        
        # 检查是否为慢查询
        if metrics.query_time > 1.0:  # 超过1秒
            self.slow_queries.append({
                'query': query,
                'params': params,
                'metrics': metrics,
                'timestamp': datetime.now()
            })
        
        return metrics
    
    def _extract_index_usage(self, plan: Dict[str, Any]) -> Dict[str, int]:
        """提取索引使用情况"""
        index_usage = {}
        
        def traverse_plan(node):
            if 'Node Type' in node:
                node_type = node['Node Type']
                
                if 'Index Name' in node:
                    index_name = node['Index Name']
                    index_usage[index_name] = index_usage.get(index_name, 0) + 1
                
                if 'Plans' in node:
                    for sub_plan in node['Plans']:
                        traverse_plan(sub_plan)
        
        traverse_plan(plan)
        return index_usage
    
    def _extract_buffer_usage(self, plan: Dict[str, Any]) -> Dict[str, int]:
        """提取缓冲区使用情况"""
        buffers = plan.get('Buffers', {})
        
        return {
            'shared_hit': buffers.get('shared hit', 0),
            'shared_read': buffers.get('shared read', 0),
            'shared_dirtied': buffers.get('shared dirtied', 0),
            'shared_written': buffers.get('shared written', 0),
            'local_hit': buffers.get('local hit', 0),
            'local_read': buffers.get('local read', 0),
            'local_dirtied': buffers.get('local dirtied', 0),
            'local_written': buffers.get('local written', 0),
            'temp_read': buffers.get('temp read', 0),
            'temp_written': buffers.get('temp written', 0)
        }
    
    def _get_cpu_usage(self) -> float:
        """获取CPU使用率"""
        import psutil
        return psutil.cpu_percent()
    
    def _get_memory_usage(self) -> float:
        """获取内存使用率"""
        import psutil
        return psutil.virtual_memory().percent
    
    def analyze_performance_trends(self, hours: int = 24) -> Dict[str, Any]:
        """分析性能趋势"""
        cutoff_time = datetime.now() - timedelta(hours=hours)
        recent_metrics = [
            m for m in self.metrics_history 
            if datetime.now() - timedelta(hours=hours) <= datetime.now()
        ]
        
        if not recent_metrics:
            return {'message': '没有足够的数据进行分析'}
        
        query_times = [m.query_time for m in recent_metrics]
        cpu_usage = [m.cpu_usage for m in recent_metrics]
        memory_usage = [m.memory_usage for m in recent_metrics]
        
        analysis = {
            'period_hours': hours,
            'total_queries': len(recent_metrics),
            'avg_query_time': statistics.mean(query_times),
            'max_query_time': max(query_times),
            'min_query_time': min(query_times),
            'avg_cpu_usage': statistics.mean(cpu_usage),
            'avg_memory_usage': statistics.mean(memory_usage),
            'slow_query_count': len([m for m in recent_metrics if m.query_time > 1.0]),
            'trend': self._calculate_trend(query_times)
        }
        
        return analysis
    
    def _calculate_trend(self, values: List[float]) -> str:
        """计算趋势"""
        if len(values) < 2:
            return 'insufficient_data'
        
        # 简单的线性趋势计算
        x = list(range(len(values)))
        n = len(values)
        
        sum_x = sum(x)
        sum_y = sum(values)
        sum_xy = sum(x[i] * values[i] for i in range(n))
        sum_x2 = sum(x[i] ** 2 for i in range(n))
        
        # 计算斜率
        slope = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)
        
        if slope > 0.01:
            return 'increasing'
        elif slope < -0.01:
            return 'decreasing'
        else:
            return 'stable'
    
    def generate_optimization_report(self) -> Dict[str, Any]:
        """生成优化报告"""
        if not self.metrics_history:
            return {'message': '没有性能数据'}
        
        # 分析慢查询
        slow_query_analysis = self._analyze_slow_queries()
        
        # 分析索引使用
        index_analysis = self._analyze_index_usage()
        
        # 分析缓冲区使用
        buffer_analysis = self._analyze_buffer_usage()
        
        # 生成建议
        recommendations = self._generate_recommendations(
            slow_query_analysis, index_analysis, buffer_analysis
        )
        
        return {
            'summary': {
                'total_queries': len(self.metrics_history),
                'slow_queries': len(self.slow_queries),
                'avg_query_time': statistics.mean([m.query_time for m in self.metrics_history])
            },
            'slow_queries': slow_query_analysis,
            'index_usage': index_analysis,
            'buffer_usage': buffer_analysis,
            'recommendations': recommendations
        }
    
    def _analyze_slow_queries(self) -> Dict[str, Any]:
        """分析慢查询"""
        if not self.slow_queries:
            return {'message': '没有慢查询'}
        
        slow_times = [sq['metrics'].query_time for sq in self.slow_queries]
        
        return {
            'count': len(self.slow_queries),
            'avg_time': statistics.mean(slow_times),
            'max_time': max(slow_times),
            'min_time': min(slow_times),
            'queries': [
                {
                    'query': sq['query'][:100] + '...',
                    'time': sq['metrics'].query_time,
                    'rows_examined': sq['metrics'].rows_examined,
                    'timestamp': sq['timestamp'].isoformat()
                }
                for sq in self.slow_queries[-5:]  # 最近5个慢查询
            ]
        }
    
    def _analyze_index_usage(self) -> Dict[str, Any]:
        """分析索引使用"""
        all_index_usage = {}
        
        for metrics in self.metrics_history:
            for index, count in metrics.index_usage.items():
                all_index_usage[index] = all_index_usage.get(index, 0) + count
        
        # 排序
        sorted_indexes = sorted(all_index_usage.items(), key=lambda x: x[1], reverse=True)
        
        return {
            'total_index_usage': sum(all_index_usage.values()),
            'unique_indexes': len(all_index_usage),
            'top_indexes': sorted_indexes[:10],
            'unused_indexes': []  # 需要与数据库中的索引列表比较
        }
    
    def _analyze_buffer_usage(self) -> Dict[str, Any]:
        """分析缓冲区使用"""
        total_shared_hit = sum(m.buffer_usage.get('shared_hit', 0) for m in self.metrics_history)
        total_shared_read = sum(m.buffer_usage.get('shared_read', 0) for m in self.metrics_history)
        
        hit_ratio = total_shared_hit / (total_shared_hit + total_shared_read) if (total_shared_hit + total_shared_read) > 0 else 0
        
        return {
            'shared_buffer_hit_ratio': hit_ratio,
            'total_shared_hit': total_shared_hit,
            'total_shared_read': total_shared_read,
            'cache_efficiency': 'good' if hit_ratio > 0.95 else 'poor'
        }
    
    def _generate_recommendations(self, slow_query_analysis: Dict, 
                                index_analysis: Dict, buffer_analysis: Dict) -> List[str]:
        """生成优化建议"""
        recommendations = []
        
        # 慢查询建议
        if slow_query_analysis.get('count', 0) > 0:
            recommendations.append(
                f"发现{slow_query_analysis['count']}个慢查询,平均执行时间{slow_query_analysis['avg_time']:.3f}秒"
            )
            recommendations.append("建议分析慢查询的执行计划并优化索引")
        
        # 缓冲区建议
        hit_ratio = buffer_analysis.get('shared_buffer_hit_ratio', 0)
        if hit_ratio < 0.95:
            recommendations.append(
                f"共享缓冲区命中率{hit_ratio:.1%}较低,建议增加shared_buffers配置"
            )
        
        # 索引建议
        if index_analysis.get('unique_indexes', 0) > 20:
            recommendations.append("索引数量较多,建议清理未使用的索引")
        
        return recommendations

# 使用示例
def main():
    monitor = DatabasePerformanceMonitor("postgresql://user:password@localhost/dbname")
    
    # 监控一些查询
    queries = [
        "SELECT * FROM users WHERE status = 'active'",
        "SELECT COUNT(*) FROM orders WHERE created_at > '2023-01-01'",
        "SELECT u.name, COUNT(o.id) FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.name"
    ]
    
    for query in queries:
        print(f"执行查询: {query}")
        metrics = monitor.monitor_query_performance(query)
        print(f"执行时间: {metrics.query_time:.3f}秒")
        print(f"检查行数: {metrics.rows_examined}")
        print(f"返回行数: {metrics.rows_returned}")
        print()
    
    # 生成报告
    report = monitor.generate_optimization_report()
    print("=== 性能优化报告 ===")
    print(f"总查询数: {report['summary']['total_queries']}")
    print(f"慢查询数: {report['summary']['slow_queries']}")
    print(f"平均执行时间: {report['summary']['avg_query_time']:.3f}秒")
    
    if report['recommendations']:
        print("\n优化建议:")
        for rec in report['recommendations']:
            print(f"- {rec}")

if __name__ == "__main__":
    main()

SQL优化最佳实践

查询设计原则

  1. **避免SELECT ***: 只查询需要的列
  2. 合理使用WHERE: 限制数据范围
  3. 优化JOIN: 选择合适的JOIN类型和顺序
  4. 使用索引: 为查询条件创建合适的索引

索引设计原则

  1. 高选择性: 选择性高的字段适合建索引
  2. 复合索引: 多条件查询使用复合索引
  3. 覆盖索引: 包含查询所有字段的索引
  4. 定期维护: 定期分析和重建索引

性能监控

  1. 慢查询日志: 记录和分析慢查询
  2. 执行计划: 分析查询执行计划
  3. 性能指标: 监控关键性能指标
  4. 趋势分析: 分析性能变化趋势

相关技能

  • database-query-analyzer - 数据库查询分析
  • api-validator - API接口验证和设计
  • performance-profiler - 性能分析和监控
  • database-design - 数据库设计优化

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the SQL优化器 AI skill do?

当优化SQL查询时,分析执行计划,检查索引使用,优化查询性能。验证SQL语法,分析查询复杂度,和最佳实践。

Why use SQL优化器 on TypingMind?

Because you install it once and use it with any model. SQL优化器 is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install SQL优化器 in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/microwind/ai-skills/tree/main/database/sql-optimizer. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use SQL优化器?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with SQL优化器?

As many as you like. As long as a model supports skills, you can use SQL优化器 with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the SQL优化器 AI skill free?

Yes. It is published on GitHub by microwind under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇