
ecto-query-analysis
by layeddie
SKILL.md
name: ecto-query-analysis description: Analyzes Ecto queries for N+1 problems, missing preloads, and performance issues.
Ecto Query Analysis Skill
Use this skill to analyze Ecto queries for performance issues and optimization opportunities.
When to Use
- Reviewing Ecto query code
- Investigating slow database queries
- Optimizing database access patterns
- Designing database schemas for performance
Common Issues
N+1 Query Problem
Symptom: Multiple database queries executed in a loop to fetch associated data.
Example:
# ❌ Bad - N+1 query problem
def get_users_with_posts do
users = Repo.all(User)
Enum.map(users, fn user ->
posts = Repo.all(from p in Post, where: p.user_id == ^user.id)
%{user: user, posts: posts}
end)
end
# ✅ Good - Preload associations
def get_users_with_posts do
User
|> preload([:posts])
|> Repo.all()
end
Missing Indexes
Symptom: Frequent queries on non-indexed columns are slow.
Example:
# ❌ Bad - No index on frequently queried column
# Query: WHERE email = '...' on large table
# Result: Slow sequential scan
# ✅ Good - Add index
# CREATE INDEX users_email_idx ON users(email)
# Query becomes fast index scan
Large Result Sets
Symptom: Loading all records into memory unnecessarily.
Example:
# ❌ Bad - Loading all records
def list_users, do: Repo.all(User)
# ✅ Good - Pagination
def list_users(page, per_page \\ 20) do
User
|> limit(^per_page)
|> offset((page - 1) * ^per_page)
|> Repo.all()
end
Optimization Strategies
Preloading
Associations: Always preload associations to prevent N+1 queries.
# Single association
User |> preload([:posts]) |> Repo.one()
# Multiple associations
User |> preload([:posts, :profile, :settings]) |> Repo.one()
# Nested associations
User |> preload([profile: [:avatar, [:background]]) |> Repo.one()
Selective Preloading
Only Load Needed Fields:
# Instead of preload(:posts) which loads all fields
User
|> Ash.Query.for_read()
|> Ash.Query.load([:posts, published_posts: [:author]])
|> Ash.Query.filter(posts[:published] == true)
|> Ash.read!()
Query Optimization
Use Ash Aggregates:
# Instead of loading all posts then counting
def count_published_posts(user_id) do
Post
|> Ash.Query.aggregate([:count], :first)
|> Ash.Query.filter(author_id == ^user_id)
|> Ash.Query.filter(status == :published)
|> Ash.read_one!()
end
Use Window Functions:
# Calculate stats efficiently
def get_user_stats(user_id) do
stats = User
|> Ash.Query.aggregate([:count, :max_age], :first)
|> Ash.Query.filter(id == ^user_id)
|> Ash.read_one!()
stats
end
Indexing Strategy
Composite Index: Index multiple columns often queried together.
# For queries filtering by user_id and status
CREATE INDEX posts_user_id_status_idx ON posts(user_id, status)
Partial Index: Index on prefix for range queries.
# For queries filtering by email LIKE 'user%'
CREATE INDEX users_email_prefix_idx ON users(email text_pattern_ops)
Commands to Run
# Enable query logging
# In config/dev.exs:
config :my_app, MyApp.Repo,
loggers: [{Ecto.LogEntry, :log, :info}],
log_sql_queries: true
# Analyze query plans
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
# Check for missing indexes
# In IEx:
Ecto.Adapters.SQL.explain(MyApp.Repo, "EXPLAIN SELECT * FROM users")
Best Practices
Do
- Always preload associations
- Use selective preloading
- Use aggregates for efficient calculations
- Add indexes on frequently queried columns
- Use pagination for large result sets
- Filter at database level, not in Elixir
Don't
- Enumerate over associations (N+1 problem)
- Load entire result sets into memory
- Use SELECT * when you only need specific columns
- Ignore query performance warnings
- Skip adding indexes on slow queries
Tools
- mgrep: Search for N+1 patterns:
mgrep "N+1 query problems in codebase" - Serena: Analyze codebase for query optimization opportunities
- Credo: Check for code smells in database access code
Use this skill to identify and fix Ecto performance issues.
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です