ワンクリックで
database
查询优化、索引策略和数据库性能调优,覆盖 PostgreSQL 和 MySQL
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
查询优化、索引策略和数据库性能调优,覆盖 PostgreSQL 和 MySQL
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
单文件代码审查,6个维度逐项检查。覆盖正确性、安全性、性能、可维护性、测试、无障碍
CI/CD 流水线和容器化部署,覆盖 GitHub Actions、GitLab CI、Docker、测试策略和部署自动化
微服务设计模式,涵盖服务网格、事件驱动架构、Saga 模式和 API 网关
Web 性能优化,涵盖包分析、懒加载、缓存策略和 Core Web Vitals
TypeScript 进阶模式,涵盖泛型、条件类型、映射类型、模板字面量和类型守卫
UI 原型产出技能,根据选定风格生成静态 HTML 原型,作为 Builder 的设计契约
| name | database |
| description | 查询优化、索引策略和数据库性能调优,覆盖 PostgreSQL 和 MySQL |
Always run EXPLAIN ANALYZE before optimizing. Read the output bottom-up.
-- PostgreSQL
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) SELECT ...;
-- MySQL
EXPLAIN ANALYZE SELECT ...;
Key metrics to watch:
ANALYZECREATE INDEX idx_users_email ON users (email);
CREATE INDEX idx_orders_user_date ON orders (user_id, created_at DESC);
Use for: equality, range queries, sorting. Column order matters in composite indexes: put equality columns first, then range/sort columns.
CREATE INDEX idx_orders_pending ON orders (created_at)
WHERE status = 'pending';
Use when queries always filter on a specific condition. Dramatically smaller than full indexes.
CREATE INDEX idx_products_tags ON products USING GIN (tags);
CREATE INDEX idx_docs_search ON documents USING GIN (to_tsvector('english', content));
CREATE INDEX idx_locations_point ON locations USING GiST (coordinates);
CREATE INDEX idx_events_period ON events USING GiST (tsrange(start_at, end_at));
-- PostgreSQL
CREATE INDEX idx_users_email_name ON users (email) INCLUDE (name);
-- MySQL
CREATE INDEX idx_users_email_name ON users (email, name);
Symptom: 1 query to fetch parent + N queries for each child.
// BAD: N+1
const users = await db.select().from(users);
for (const user of users) {
const orders = await db.select().from(orders).where(eq(orders.userId, user.id));
}
// GOOD: eager load (Prisma)
const users = await prisma.user.findMany({ include: { orders: true } });
// GOOD: join query (Drizzle)
const users = await db.query.users.findMany({
with: { orders: true },
});
Detection: enable query logging, count queries per request. More than 10 queries for a single endpoint is a red flag.
Rule of thumb: pool_size = (core_count * 2) + disk_count
Typical web app: 10-20 connections per app instance
PostgreSQL:
idle_in_transaction_session_timeout = '30s'pg_stat_activityMySQL:
max_connections based on available RAM (each connection uses ~10MB)SHOW PROCESSLISTSELECT queries to replicas// Read replica routing (Kysely)
function getDatabase(write: boolean) {
return write ? primaryDb : replicaDb;
}
// Usage
const users = await getDatabase(false).selectFrom('users').selectAll().execute();
await getDatabase(true).insertInto('users').values({ name: 'Alice' }).execute();
-- PostgreSQL
CREATE TABLE events (
id bigint GENERATED ALWAYS AS IDENTITY,
created_at timestamptz NOT NULL,
data jsonb
) PARTITION BY RANGE (created_at);
CREATE TABLE events_2025_q1 PARTITION OF events
FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');
CREATE TABLE events_2025_q2 PARTITION OF events
FOR VALUES FROM ('2025-04-01') TO ('2025-07-01');
CREATE TABLE sessions (
id uuid PRIMARY KEY,
user_id bigint NOT NULL
) PARTITION BY HASH (user_id);
CREATE TABLE sessions_0 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE sessions_1 PARTITION OF sessions FOR VALUES WITH (MODULUS 4, REMAINDER 1);
Partition when tables exceed 50-100GB or when you need to drop old data quickly.
EXPLAIN ANALYZE and read the planidx_scan in pg_stat_user_indexes)SELECT * with specific columnsLIMIT to queries that only need a subsetEXISTS instead of COUNT(*) > 0INSERT/UPDATE operations (500-1000 rows per batch)WHERE clauseslog_min_duration_statement = 100)LIKE '%term%' on unindexed columns (use full-text search instead)ORDER BY RANDOM() (use TABLESAMPLE or application-level randomization)SELECT DISTINCT masking a join problemWHERE on UPDATE/DELETE (always verify with SELECT first)OFFSET for deep pagination (use keyset/cursor pagination instead)