SQL优化器技能
概述
慢SQL查询会复合影响。一个慢查询会影响100个事务。在扩展之前先优化。需要建立完善的SQL查询分析和优化机制。
核心原则: 慢SQL查询会复合影响。一个慢查询会影响100个事务。在扩展之前先优化。
何时使用
始终:
- 优化慢查询
- 数据库性能问题
- 扩展数据库之前
- 性能分析后的查询调优
- 索引设计优化
- 查询性能监控
触发短语:
- "优化这个SQL查询"
- "查询太慢了"
- "如何优化数据库性能?"
- "检查SQL执行计划"
- "索引怎么设计?"
- "SQL性能分析"
SQL优化功能
查询分析
- 执行计划分析
- 查询复杂度评估
- 索引使用检查
- 统计信息分析
- 性能瓶颈识别
索引优化
- 索引设计建议
- 索引使用效率分析
- 冗余索引检测
- 索引优化方案
- 覆盖索引设计
性能调优
- 查询重写建议
- 表结构优化
- 分区策略分析
- 缓存优化建议
- 参数调优
常见SQL性能问题
缺少索引
问题: 查询条件没有合适的索引支持 后果: - 全表扫描 - 查询速度慢 - CPU占用高 - 锁竞争严重 解决方案: - 创建合适的索引 - 复合索引优化 - 覆盖索引设计 - 索引选择性分析
查询设计不当
问题: SQL查询语句设计不合理 后果: - 执行计划不优 - 资源浪费 - 性能下降 - 扩展性差 解决方案: - 重写查询语句 - 避免子查询 - 优化JOIN操作 - 减少数据传输
统计信息过时
问题: 数据库统计信息不准确 后果: - 执行计划错误 - 索引选择不当 - 查询性能下降 - 资源分配不合理 解决方案: - 更新统计信息 - 定期维护 - 自动统计收集 - 手动统计更新
SQL优化策略
查询重写技巧
避免子查询: - 使用JOIN替代子查询 - 使用EXISTS替代IN - 优化相关子查询 - 减少嵌套层次 优化JOIN: - 选择合适的JOIN类型 - 确保连接字段有索引 - 减少JOIN的数据量 - 优化JOIN顺序
索引设计原则
单列索引: - 高选择性字段 - 频繁查询条件 - 排序字段 - 外键字段 复合索引: - 多条件查询 - 字段顺序重要 - 覆盖查询需求 - 减少回表查询
代码实现示例
SQL查询优化器
pythonimport 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()
数据库性能监控
pythonimport 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优化最佳实践
查询设计原则
- **避免SELECT ***: 只查询需要的列
- 合理使用WHERE: 限制数据范围
- 优化JOIN: 选择合适的JOIN类型和顺序
- 使用索引: 为查询条件创建合适的索引
索引设计原则
- 高选择性: 选择性高的字段适合建索引
- 复合索引: 多条件查询使用复合索引
- 覆盖索引: 包含查询所有字段的索引
- 定期维护: 定期分析和重建索引
性能监控
- 慢查询日志: 记录和分析慢查询
- 执行计划: 分析查询执行计划
- 性能指标: 监控关键性能指标
- 趋势分析: 分析性能变化趋势
相关技能
- database-query-analyzer - 数据库查询分析
- api-validator - API接口验证和设计
- performance-profiler - 性能分析和监控
- database-design - 数据库设计优化


