ハイブリッドモード、段階的コンポーネント書き換え、依存性注入更新を使用してAngularJSからAngularへ移行します。AngularJSアプリケーションのアップグレード、フレームワーク移行の計画、またはレガシーAngularコードのモダナイゼーション時に使用します。
中文简介正在准备中。当前显示原文说明。
SQLクエリ最適化、インデックス戦略、EXPLAIN分析をマスターし、データベースパフォーマンスを劇的に向上させ、遅いクエリを排除。遅いクエリのデバッグ、データベーススキーマの設計、アプリケーションパフォーマンスの最適化時に使用。
中文简介正在准备中。当前显示原文说明。
查看安装方法安装前可以查看交给 AI 代理的指令内容。
English | 日本語
体系的な最適化、適切なインデックス作成、クエリプラン分析を通じて、遅いデータベースクエリを超高速操作に変革します。
EXPLAIN出力の理解は最適化の基本です。
PostgreSQL EXPLAIN:
-- 基本的なexplain
EXPLAIN SELECT * FROM users WHERE email = 'user@example.com';
-- 実際の実行統計付き
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'user@example.com';
-- より詳細な冗長出力
EXPLAIN (ANALYZE, BUFFERS, VERBOSE)
SELECT u.*, o.order_total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > NOW() - INTERVAL '30 days';
注視すべき主要メトリクス:
インデックスは最も強力な最適化ツールです。
インデックスタイプ:
-- 標準B-Treeインデックス
CREATE INDEX idx_users_email ON users(email);
-- 複合インデックス(順序が重要!)
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
-- 部分インデックス(行のサブセットをインデックス化)
CREATE INDEX idx_active_users ON users(email)
WHERE status = 'active';
-- 式インデックス
CREATE INDEX idx_users_lower_email ON users(LOWER(email));
-- カバリングインデックス(追加カラムを含む)
CREATE INDEX idx_users_email_covering ON users(email)
INCLUDE (name, created_at);
-- 全文検索インデックス
CREATE INDEX idx_posts_search ON posts
USING GIN(to_tsvector('english', title || ' ' || body));
-- JSONBインデックス
CREATE INDEX idx_metadata ON events USING GIN(metadata);
SELECT * を避ける:
-- 悪い例:不要なカラムを取得
SELECT * FROM users WHERE id = 123;
-- 良い例:必要なものだけを取得
SELECT id, email, name FROM users WHERE id = 123;
WHERE句を効率的に使用:
-- 悪い例:関数がインデックス使用を妨げる
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
-- 良い例:関数インデックスを作成するか正確な一致を使用
CREATE INDEX idx_users_email_lower ON users(LOWER(email));
-- その後:
SELECT * FROM users WHERE LOWER(email) = 'user@example.com';
-- または正規化されたデータを保存
SELECT * FROM users WHERE email = 'user@example.com';
JOINを最適化:
-- 悪い例:デカルト積の後にフィルター
SELECT u.name, o.total
FROM users u, orders o
WHERE u.id = o.user_id AND u.created_at > '2024-01-01';
-- 良い例:結合前にフィルター
SELECT u.name, o.total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01';
-- より良い例:両方のテーブルをフィルター
SELECT u.name, o.total
FROM (SELECT * FROM users WHERE created_at > '2024-01-01') u
JOIN orders o ON u.id = o.user_id;
問題:N+1クエリアンチパターン
# 悪い例:N+1クエリを実行
users = db.query(\"SELECT * FROM users LIMIT 10\")
for user in users:
orders = db.query(\"SELECT * FROM orders WHERE user_id = ?\", user.id)
# 注文を処理
解決策:JOINまたはバッチロードを使用
-- 解決策1:JOIN
SELECT
u.id, u.name,
o.id as order_id, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id IN (1, 2, 3, 4, 5);
-- 解決策2:バッチクエリ
SELECT * FROM orders
WHERE user_id IN (1, 2, 3, 4, 5);
# 良い例:JOINまたはバッチロードで単一クエリ
# JOINを使用
results = db.query(\"\"\"
SELECT u.id, u.name, o.id as order_id, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id IN (1, 2, 3, 4, 5)
\"\"\")
# またはバッチロード
users = db.query(\"SELECT * FROM users LIMIT 10\")
user_ids = [u.id for u in users]
orders = db.query(
\"SELECT * FROM orders WHERE user_id IN (?)\",
user_ids
)
# user_idで注文をグループ化
orders_by_user = {}
for order in orders:
orders_by_user.setdefault(order.user_id, []).append(order)
悪い例:大きなテーブルでのOFFSET
-- 大きなオフセットでは遅い
SELECT * FROM users
ORDER BY created_at DESC
LIMIT 20 OFFSET 100000; -- 非常に遅い!
良い例:カーソルベースのページネーション
-- はるかに高速:カーソル(最後に見たID)を使用
SELECT * FROM users
WHERE created_at < '2024-01-15 10:30:00' -- 最後のカーソル
ORDER BY created_at DESC
LIMIT 20;
-- 複合ソートで
SELECT * FROM users
WHERE (created_at, id) < ('2024-01-15 10:30:00', 12345)
ORDER BY created_at DESC, id DESC
LIMIT 20;
-- インデックスが必要
CREATE INDEX idx_users_cursor ON users(created_at DESC, id DESC);
COUNTクエリの最適化:
-- 悪い例:すべての行をカウント
SELECT COUNT(*) FROM orders; -- 大きなテーブルでは遅い
-- 良い例:概算カウントに推定値を使用
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE relname = 'orders';
-- 良い例:カウント前にフィルター
SELECT COUNT(*) FROM orders
WHERE created_at > NOW() - INTERVAL '7 days';
-- より良い例:インデックスのみスキャンを使用
CREATE INDEX idx_orders_created ON orders(created_at);
SELECT COUNT(*) FROM orders
WHERE created_at > NOW() - INTERVAL '7 days';
GROUP BYの最適化:
-- 悪い例:グループ化してからフィルター
SELECT user_id, COUNT(*) as order_count
FROM orders
GROUP BY user_id
HAVING COUNT(*) > 10;
-- より良い例:まずフィルター、その後グループ化(可能な場合)
SELECT user_id, COUNT(*) as order_count
FROM orders
WHERE status = 'completed'
GROUP BY user_id
HAVING COUNT(*) > 10;
-- 最良の例:カバリングインデックスを使用
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
相関サブクエリの変換:
-- 悪い例:相関サブクエリ(各行で実行)
SELECT u.name, u.email,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) as order_count
FROM users u;
-- 良い例:集約付きJOIN
SELECT u.name, u.email, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.name, u.email;
-- より良い例:ウィンドウ関数を使用
SELECT DISTINCT ON (u.id)
u.name, u.email,
COUNT(o.id) OVER (PARTITION BY u.id) as order_count
FROM users u
LEFT JOIN orders o ON o.user_id = u.id;
明確性のためのCTE使用:
-- 共通テーブル式の使用
WITH recent_users AS (
SELECT id, name, email
FROM users
WHERE created_at > NOW() - INTERVAL '30 days'
),
user_order_counts AS (
SELECT user_id, COUNT(*) as order_count
FROM orders
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY user_id
)
SELECT ru.name, ru.email, COALESCE(uoc.order_count, 0) as orders
FROM recent_users ru
LEFT JOIN user_order_counts uoc ON ru.id = uoc.user_id;
バッチINSERT:
-- 悪い例:複数の個別insert
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com');
INSERT INTO users (name, email) VALUES ('Carol', 'carol@example.com');
-- 良い例:バッチinsert
INSERT INTO users (name, email) VALUES
('Alice', 'alice@example.com'),
('Bob', 'bob@example.com'),
('Carol', 'carol@example.com');
-- より良い例:一括insertにCOPYを使用(PostgreSQL)
COPY users (name, email) FROM '/tmp/users.csv' CSV HEADER;
バッチUPDATE:
-- 悪い例:ループでupdate
UPDATE users SET status = 'active' WHERE id = 1;
UPDATE users SET status = 'active' WHERE id = 2;
-- ... 多数のIDで繰り返し
-- 良い例:IN句で単一UPDATE
UPDATE users
SET status = 'active'
WHERE id IN (1, 2, 3, 4, 5, ...);
-- より良い例:大きなバッチには一時テーブルを使用
CREATE TEMP TABLE temp_user_updates (id INT, new_status VARCHAR);
INSERT INTO temp_user_updates VALUES (1, 'active'), (2, 'active'), ...;
UPDATE users u
SET status = t.new_status
FROM temp_user_updates t
WHERE u.id = t.id;
高コストなクエリを事前計算。
-- マテリアライズドビューを作成
CREATE MATERIALIZED VIEW user_order_summary AS
SELECT
u.id,
u.name,
COUNT(o.id) as total_orders,
SUM(o.total) as total_spent,
MAX(o.created_at) as last_order_date
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;
-- マテリアライズドビューにインデックスを追加
CREATE INDEX idx_user_summary_spent ON user_order_summary(total_spent DESC);
-- マテリアライズドビューを更新
REFRESH MATERIALIZED VIEW user_order_summary;
-- 並行更新(PostgreSQL)
REFRESH MATERIALIZED VIEW CONCURRENTLY user_order_summary;
-- マテリアライズドビューをクエリ(非常に高速)
SELECT * FROM user_order_summary
WHERE total_spent > 1000
ORDER BY total_spent DESC;
パフォーマンス向上のために大きなテーブルを分割。
-- 日付による範囲パーティショニング(PostgreSQL)
CREATE TABLE orders (
id SERIAL,
user_id INT,
total DECIMAL,
created_at TIMESTAMP
) PARTITION BY RANGE (created_at);
-- パーティションを作成
CREATE TABLE orders_2024_q1 PARTITION OF orders
FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');
CREATE TABLE orders_2024_q2 PARTITION OF orders
FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');
-- クエリは自動的に適切なパーティションを使用
SELECT * FROM orders
WHERE created_at BETWEEN '2024-02-01' AND '2024-02-28';
-- orders_2024_q1パーティションのみスキャン
-- インデックス使用を強制(MySQL)
SELECT * FROM users
USE INDEX (idx_users_email)
WHERE email = 'user@example.com';
-- 並列クエリ(PostgreSQL)
SET max_parallel_workers_per_gather = 4;
SELECT * FROM large_table WHERE condition;
-- 結合ヒント(PostgreSQL)
SET enable_nestloop = OFF; -- ハッシュまたはマージ結合を強制
-- 統計を更新
ANALYZE users;
ANALYZE VERBOSE orders;
-- Vacuum(PostgreSQL)
VACUUM ANALYZE users;
VACUUM FULL users; -- スペースを回収(テーブルをロック)
-- 再インデックス
REINDEX INDEX idx_users_email;
REINDEX TABLE users;
LIKE '%abc'はインデックスを使用できない-- 遅いクエリを見つける(PostgreSQL)
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
-- 欠落しているインデックスを見つける(PostgreSQL)
SELECT
schemaname,
tablename,
seq_scan,
seq_tup_read,
idx_scan,
seq_tup_read / seq_scan AS avg_seq_tup_read
FROM pg_stat_user_tables
WHERE seq_scan > 0
ORDER BY seq_tup_read DESC
LIMIT 10;
-- 未使用のインデックスを見つける(PostgreSQL)
SELECT
schemaname,
tablename,
indexname,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
还没有评价。欢迎分享你的使用感受。
无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。
还没有评论。来写第一条吧。
ハイブリッドモード、段階的コンポーネント書き換え、依存性注入更新を使用してAngularJSからAngularへ移行します。AngularJSアプリケーションのアップグレード、フレームワーク移行の計画、またはレガシーAngularコードのモダナイゼーション時に使用します。
中文简介正在准备中。当前显示原文说明。
Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.
中文简介正在准备中。当前显示原文说明。
Master REST and GraphQL API design principles to build intuitive, scalable, and maintainable APIs that delight developers. Use when designing new APIs, reviewing API specifications, or establishing API design standards.
中文简介正在准备中。当前显示原文说明。
開発者を喜ばせる直感的でスケーラブルで保守可能なAPIを構築するために、RESTとGraphQL APIの設計原則をマスターします。新しいAPIの設計、API仕様のレビュー、またはAPI設計標準の確立時に使用してください。
中文简介正在准备中。当前显示原文说明。
クリーンアーキテクチャ、ヘキサゴナルアーキテクチャ、ドメイン駆動設計を含む実証済みのバックエンドアーキテクチャパターンを実装します。複雑なバックエンドシステムの設計や、保守性向上のための既存アプリケーションのリファクタリング時に使用します。
中文简介正在准备中。当前显示原文说明。
Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.
中文简介正在准备中。当前显示原文说明。