sql-insight について
sql-insight は、SQL の作成と分析に使うコマンドラインツールです。データベース構造の把握やクエリ確認を行う開発者向けに、自然言語からの SQL 作成支援、ルールベースの改善提案、EXPLAIN プランの解釈を備えています。読み取り専用接続と SQL 制限もあります。
主な機能
- 01テーブル、インデックス、サンプルデータの抽出
- 02スキーマ情報を使った SQL 作成支援
- 0313 のルールによるクエリ検査
- 04EXPLAIN プランの実行と解釈
- 05読み取り専用接続と SQL 制限
活用シーン
- 01自然言語の依頼から SQL を作成
- 02SQL クエリの改善点を確認
- 03全表スキャンやインデックス不足の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ zebbern/ claude-code-guide --skill sql-insightインストール後、Claude Code で/sql-insightを入力して読み込まれたか確認します。
同梱ファイルLICENSEscripts/sql_query_helper.py
詳細
sql-insight
SQL クエリアシスタント — 自然言語から SQL への変換、クエリ最適化の分析、EXPLAIN プランの解釈を行います。
機能
| 機能 | 説明 |
|---|---|
| スキーマ抽出 | データベースのテーブル構造(カラム、型、インデックス、外部キー、サンプルデータ)を抽出し、自然言語から SQL への変換に必要なコンテキストを提供します |
| 自然言語 → SQL | スキーマのコンテキストを使用して、自然言語の説明を SQL クエリに変換します |
| クエリ最適化の分析 | 13 個のルールに基づいて SQL のアンチパターンを検出し、最適化の提案を提示します |
| EXPLAIN の解釈 | EXPLAIN を実行してクエリプランを解釈し、フルテーブルスキャンや不足しているインデックスなどを特定します |
ワークフロー
自然言語 → SQL
schemaコマンドを使用してデータベースのテーブル構造を抽出します- スキーマをコンテキストとして使用し、ユーザーの自然言語によるリクエストを SQL に変換します
optimizeコマンドを使用して、生成された SQL を改善できるか確認しますexplainコマンドを使用してクエリの実行プランを検証します
# Step 1: Extract schema (compact mode, suitable for LLM context)
python3 scripts/sql_query_helper.py --db-path data.db schema --compact
# Step 2: Analyze SQL optimization suggestions
python3 scripts/sql_query_helper.py optimize "SELECT * FROM orders WHERE user_id = 100"
# Step 3: View EXPLAIN execution plan
python3 scripts/sql_query_helper.py --db-path data.db explain "SELECT * FROM orders WHERE user_id = 100"
クイックスタート
スキーマ抽出
# Extract full schema (JSON format, with sample data)
python3 scripts/sql_query_helper.py --db-path data.db schema
# Compact mode (plain text, suitable for embedding in prompts)
python3 scripts/sql_query_helper.py --db-path data.db schema --compact
# Skip data sampling
python3 scripts/sql_query_helper.py --db-path data.db schema --sample-rows 0
# PostgreSQL
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb user=reader" schema --compact
クエリ最適化の分析
# Analyze SQL query (no database connection required, pure rule-based detection)
python3 scripts/sql_query_helper.py optimize "SELECT * FROM orders o, users u WHERE o.user_id = u.id"
python3 scripts/sql_query_helper.py optimize "SELECT name FROM users WHERE UPPER(email) LIKE '%@GMAIL.COM'"
python3 scripts/sql_query_helper.py optimize "SELECT id, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count FROM users u"
EXPLAIN の解釈
# SQLite EXPLAIN
python3 scripts/sql_query_helper.py --db-path data.db explain "SELECT * FROM orders WHERE user_id = 100"
# PostgreSQL EXPLAIN
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb" explain "SELECT * FROM orders WHERE user_id = 100"
# PostgreSQL EXPLAIN ANALYZE (actually executes the query for real-world data)
python3 scripts/sql_query_helper.py --db-type postgres --dsn "host=localhost dbname=mydb" explain --analyze "SELECT * FROM orders WHERE user_id = 100"
詳細な使用方法
グローバルパラメーター
| パラメーター | 必須 | デフォルト | 説明 |
|---|---|---|---|
--db-type | いいえ | sqlite | データベースの種類:sqlite または postgres |
--db-path | schema/explain(SQLite)で必須 | — | SQLite データベースファイルのパス |
--dsn | schema/explain(PostgreSQL)で必須 | — | PostgreSQL 接続文字列 |
サブコマンド
| コマンド | データベースが必要 | 説明 |
|---|---|---|
schema | はい | データベースのテーブル構造を抽出します |
optimize <sql> | いいえ | SQL クエリ最適化の分析(ルールベースの検出のみ) |
explain <sql> | はい | EXPLAIN を実行してプランを解釈します |
schema パラメーター
| パラメーター | デフォルト | 説明 |
|---|---|---|
--sample-rows, -n | 3 | テーブルごとのサンプル行数(サンプリングを省略する場合は 0) |
--compact | false | コンパクトなテキスト出力(プロンプトへの埋め込みに適しています) |
explain パラメーター
| パラメーター | デフォルト | 説明 |
|---|---|---|
--analyze | false | EXPLAIN ANALYZE を使用します(PostgreSQL のみ。クエリを実際に実行します) |
最適化ルール
optimize コマンドは、以下の 13 個の SQL アンチパターンを検出します。
| ルール | 深刻度 | 説明 |
|---|---|---|
| avoid-select-star | warning | SELECT * を避け、カラム名を明示的に列挙します |
| unbounded-query | info | WHERE 句と LIMIT 句がありません |
| leading-wildcard-like | warning | LIKE '%...' はインデックスを使用できなくなります |
| or-condition | info | OR 条件によりインデックスが使用されない場合があります |
| not-in-subquery | warning | NOT IN(サブクエリ)はパフォーマンスが低下します |
| scalar-subquery | warning | SELECT 内のスカラーサブクエリは行ごとに実行されます |
| function-on-column | warning | WHERE 内でカラムに関数を適用すると、インデックスを使用できなくなります |
| implicit-join | info | 暗黙的な結合(カンマ区切りのテーブル)は可読性が低くなります |
| distinct-usage | info | DISTINCT により、JOIN の重複の問題が隠れる場合があります |
| order-without-limit | info | LIMIT のない ORDER BY です |
| deep-nesting | warning | サブクエリが深くネストされています |
| having-without-group | warning | GROUP BY のない HAVING です |
| not-equal-filter | info | != 条件ではインデックスを効果的に使用できません |
EXPLAIN の解釈項目
| 確認項目 | 対応データベース | 説明 |
|---|---|---|
| 全表スキャン | SQLite / PostgreSQL | Seq Scan / SCAN TABLE を検出します |
| 自動一時インデックス | SQLite | SQLite が一時インデックスを自動作成します。これは永続インデックスが不足していることを示します |
| カバリングインデックス | SQLite / PostgreSQL | インデックスにクエリ対象のすべての列が含まれているため、テーブルを検索する必要はありません |
| ディスクソート | PostgreSQL | ソート処理がディスクに書き出されます |
| ネステッドループ結合 | PostgreSQL | 大きなテーブルでのネステッドループ結合はパフォーマンスが低下します |
| 行数推定の乖離 | PostgreSQL (ANALYZE) | 推定行数と実際の行数の差が 10 倍を超えています |
出力例
schema --compact
-- Database: sqlite
-- users (1500 rows): id INTEGER PK, name TEXT, email TEXT, age INTEGER, created_at TEXT
-- IDX(unique): idx_users_email on (email)
-- orders (8200 rows): id INTEGER PK, user_id INTEGER, amount REAL, status TEXT, created_at TEXT
-- FK: user_id -> users.id
-- IDX: idx_orders_user_id on (user_id)
optimize
{
"sql": "SELECT * FROM orders o, users u WHERE o.user_id = u.id",
"issues": [
{
"severity": "warning",
"rule": "avoid-select-star",
"message": "Avoid SELECT *: only select the columns you need to reduce I/O and network transfer",
"suggestion": "Replace SELECT * with an explicit list of required column names"
},
{
"severity": "info",
"rule": "implicit-join",
"message": "Uses implicit join (comma-separated tables), which is less readable and error-prone",
"suggestion": "Use explicit JOIN ... ON syntax for better readability and maintainability"
}
]
}
explain (SQLite)
{
"db_type": "sqlite",
"query": "SELECT * FROM orders WHERE user_id = 100",
"plan": [
{"id": 2, "parent": 0, "detail": "SEARCH orders USING INDEX idx_orders_user_id (user_id=?)"}
],
"interpretation": [
{
"severity": "ok",
"type": "index-search",
"detail": "Index lookup: idx_orders_user_id",
"suggestion": "Index lookup is efficient"
}
]
}
安全対策
- 読み取り専用接続:SQLite では
?mode=roを使用し、PostgreSQL ではSET SESSION READ ONLYを使用します - SQL の許可リスト:SELECT / WITH / EXPLAIN で始まるステートメントのみを許可します
- 危険なキーワードのブロック:INSERT、UPDATE、DELETE、DROP およびその他 30 以上のキーワードをブロックします
- 複数ステートメントのブロック:セミコロンで区切られた複数の SQL ステートメントは拒否されます
- 識別子のエスケープ:SQL インジェクションを防ぐため、テーブル名を二重引用符でエスケープします
依存関係
- Python 3.8+(
sqlite3は組み込みモジュールです) - PostgreSQL のサポートには
pip install psycopg2-binaryが必要です optimizeコマンドにはデータベース接続が不要で、外部依存関係もありません
コメント
Markdown 対応