55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/profiler/mcp/tools/analyze_queries.rb', line 55
def self.analyze_and_format(queries, summary_only: false)
lines = []
lines << "# SQL Query Analysis\n"
slow_threshold = Profiler.configuration.slow_query_threshold
slow_queries = queries.select { |q| q["duration"] > slow_threshold }
query_counts = queries.group_by { |q| normalize_sql(q["sql"]) }
.transform_values { |qs| { count: qs.size, backtrace: qs.first["backtrace"] || [] } }
.select { |_, v| v[:count] >= 3 }
unless summary_only
if slow_queries.any?
lines << "## ⚠️ Slow Queries (> #{slow_threshold}ms)"
lines << "Found #{slow_queries.size} slow queries:\n"
slow_queries.first(5).each_with_index do |query, index|
lines << "### Query #{index + 1} - #{query['duration'].round(2)}ms"
lines << "```sql"
lines << query["sql"]
lines << "```\n"
end
lines << "_... and #{slow_queries.size - 5} more slow queries_\n" if slow_queries.size > 5
else
lines << "## ✅ No Slow Queries"
lines << "All queries executed in less than #{slow_threshold}ms\n"
end
if query_counts.any?
lines << "## ⚠️ Duplicate Queries (Potential N+1)"
lines << "Found #{query_counts.size} query pattern(s) repeated 3+ times:\n"
query_counts.sort_by { |_, v| -v[:count] }.first(5).each do |sql, v|
lines << "### Executed #{v[:count]} times:"
lines << "```sql"
lines << sql
lines << "```"
if v[:backtrace].any?
lines << "#### Called from:"
v[:backtrace].first(3).each { |frame| lines << " #{frame}" }
end
lines << ""
end
lines << "_... and #{query_counts.size - 5} more duplicate patterns_\n" if query_counts.size > 5
else
lines << "## ✅ No Duplicate Queries"
lines << "No query pattern repeated 3+ times\n"
end
end
lines << "## Summary Statistics"
lines << "- **Total Queries:** #{queries.size}"
lines << "- **Total Duration:** #{queries.sum { |q| q['duration'] }.round(2)}ms"
lines << "- **Average Duration:** #{(queries.sum { |q| q['duration'] } / queries.size).round(2)}ms"
lines << "- **Slow Queries:** #{slow_queries.size}"
lines << "- **N+1 Patterns (≥3×):** #{query_counts.size}"
lines << "- **Cached Queries:** #{queries.count { |q| q['cached'] }}"
lines.join("\n")
end
|