承接 denny/laravel-sql-monitor 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

denny/laravel-sql-monitor

最新稳定版本:v1.5.3

Composer 安装命令:

composer require denny/laravel-sql-monitor

包简介

A comprehensive SQL query monitoring and analysis tool for Laravel development environments

README 文档

README

Laravel PHP License

一個全功能的 Laravel 擴展,提供動態分析(執行時監控)和靜態分析(AST 掃描)能力,幫助開發者在開發時期就發現和優化 SQL 查詢問題。

功能概覽

動態分析(執行後)

功能 說明
實時查詢監控 捕獲每條 SQL 及執行時間
複雜度評分 自動計算查詢複雜度(0–100)
N+1 檢測 識別 N+1 查詢模式,代表查詢持久化到 DB
重複查詢檢測 找出完全相同的重複查詢,代表查詢持久化到 DB
Slow Query 追蹤 超過閾值即時寫入 DB,Log::warning 同步記錄
雙層持久化 問題查詢(DB 層)+ 正常查詢(Cache 層,TTL 60s)
Dashboard Polling 每 5 秒自動拉取,合併顯示 DB + Cache 查詢
Call Stack 收集 IDE 可點擊的調用棧

靜態分析(執行前)

透過 AST 解析 PHP 原始碼,不需要執行查詢即可偵測問題:

偵測項目 issue code 嚴重度
SELECT * select-star info
無 WHERE 全表掃描 no-where warning
無 LIMIT 無界結果集 no-limit warning
WHERE 欄位缺少索引 missing-index warning
過量 JOIN(>5) excessive-joins critical
偏多 JOIN(>3) many-joins warning
JOIN 索引提示 join-index-hint info
GROUP BY 索引提示 group-by-hint info
LIMIT 無 ORDER BY limit-without-order info
UNION 使用提示 union-detected info
Eloquent N+1 風險 n1-risk info
Raw SQL 偵測 raw-sql info
複合索引建議

安裝

composer require denny/laravel-sql-monitor

發布設定檔:

php artisan vendor:publish --tag=sql-monitor-config

啟用(.env):

APP_ENV=local
SQL_MONITOR_ENABLED=true

套件只在 APP_ENV=localtesting 時啟動,生產環境不會載入。

靜態分析

基本用法

# 掃描整個 app/ 目錄
php artisan sql-monitor:analyse

# 指定目錄
php artisan sql-monitor:analyse --path=app/Repositories

# 指定單一檔案
php artisan sql-monitor:analyse --path=app/Models/User.php

# 指定類別(完整命名空間或短名稱)
php artisan sql-monitor:analyse --class=UserRepository
php artisan sql-monitor:analyse --class="App\Repositories\UserRepository"

完整 CLI 選項

選項 預設 說明
--path= 分析指定目錄或檔案
--class= 分析指定類別
--format= table 輸出格式:table / json / summary
--min-severity= info 最低顯示嚴重度:info / warning / critical
--sort= file 排序:file / cost / complexity / severity
--no-index-check 跳過資料庫索引檢查(不需 DB 連線)
--no-index-recommend 跳過複合索引建議計算

輸出範例

=== app/Repositories/OrderRepository.php

  ▲ OrderRepository::findByUser()  行 24
    eloquent::where('user_id', '$userId')->where('status', '$status')->get
    表:order  | 複雜度:25/100 [OK]  | 成本:0.49 [LOW]
    ℹ  [select-star] 使用了 SELECT *
    ▲  [no-limit] 無 LIMIT 限制,可能回傳大量資料
    ▲  [missing-index] WHERE 欄位 `status` 在 `order` 表中無索引

=== 複合索引建議

  order(2 個建議,共 15 次查詢覆蓋)

    建議 1: (user_id, status)  使用次數:12
      → 等值欄位依選擇率排序:user_id(選擇率 0.920) → status(選擇率 0.005)
      ⚠  可 DROP 現有索引:idx_user(已被新索引 left-prefix 覆蓋)

    建議 2: (user_id, created_at)  使用次數:3
      → 等值欄位依選擇率排序:user_id(選擇率 0.920)
      → ORDER BY 欄位放尾端:created_at desc(可避免 filesort)

JSON 輸出(適合 CI / diff)

php artisan sql-monitor:analyse --format=json | jq '.summary'

JSON 結構:

{
  "generated_at": "2026-04-15T10:00:00+00:00",
  "total_sites": 1114,
  "summary": {
    "critical": 0, "warning": 397, "info": 335, "ok": 382,
    "avg_complexity": 11.0, "avg_cost": 1.21
  },
  "reports": [...],
  "index_recommendations": {
    "order": [
      {
        "columns": ["user_id", "status"],
        "frequency": 12,
        "selectivities": {"user_id": 0.92, "status": 0.005},
        "replaces": ["idx_user"],
        "patterns": [...]
      }
    ]
  }
}

複合索引建議演算法

分析所有 call site 的 WHERE / ORDER BY 模式,依以下規則建構最優複合索引:

  1. Equality first — 等值條件(=, IN, IS NULL)放在索引左側
  2. High selectivity first — 等值欄位之間按選擇率(COUNT(DISTINCT) / COUNT(*))由高到低排序
  3. Range last — 範圍條件(>, <, BETWEEN)放在等值欄位之後(MySQL 限制:每個索引只能使用一個 range 欄位)
  4. ORDER BY tail — 若查詢排序欄位未被覆蓋且方向一致,放在索引尾端以避免 filesort
  5. Existing index deduplication — 若現有索引已能透過 leftmost prefix 覆蓋此 pattern,不重複建議
  6. Supersede detection — 若新索引的 left-prefix 完全涵蓋某個現有索引,標記可 DROP

不納入建議的條件:LIKE '%xxx%'(前導萬用字元)、!=NOT INwhereDate/Year/Month(非 sargable)。

設定檔

config/sql-monitor.php 完整說明:

return [
    // 啟用開關
    'enabled'      => env('SQL_MONITOR_ENABLED', true),
    'environments' => ['local', 'testing'],

    // 監控連線白/黑名單
    'connections'          => [],   // 空 = 監控所有連線
    'excluded_connections' => [],   // 永遠不監控(storage / IndexInspector 專用連線)

    // 持久化儲存(DB 層)— 問題查詢(慢查詢 / complexity >= warning / N+1 / duplicate)
    'storage' => [
        'driver'          => env('SQL_MONITOR_STORAGE_DRIVER', 'database'),
        // database(預設):寫入 Laravel 應用程式的 DB,connection = null 時自動跟隨 database.default
        // sqlite:使用獨立 SQLite 檔案(完全不影響應用程式 DB)
        'database'        => env('SQL_MONITOR_STORAGE_DATABASE') ?: null,  // SQLite 路徑(database driver 不需要)
        'connection'      => env('SQL_MONITOR_STORAGE_CONNECTION') ?: null, // null = database.default
        'table'           => 'sql_monitor_logs',
        'retention_hours' => 24,
    ],

    // Cache 層 — 正常查詢(info / low),TTL 到期自動消失
    'memory' => [
        'enabled'    => true,
        'ttl'        => (int) env('SQL_MONITOR_MEMORY_TTL', 60),  // 每筆查詢存活秒數
        'max_buffer' => 500,
    ],

    // Dashboard 自動拉取間隔
    'dashboard' => [
        'polling_interval' => (int) env('SQL_MONITOR_POLLING_INTERVAL', 5),  // 秒
    ],

    // 靜態分析 log 輸出(tee 模式)
    'static_analysis' => [
        'output_path'    => env('SQL_MONITOR_ANALYSE_OUTPUT_PATH', storage_path('logs/sql-monitor')),
        // null / 空字串 = 不寫檔
        'analyse_log'    => env('SQL_MONITOR_ANALYSE_LOG',    'analyse-{date}.log'),
        'suggestion_log' => env('SQL_MONITOR_SUGGESTION_LOG', 'suggestion-{date}.log'),
        // {date} 佔位符會替換為當天日期(YYYY-MM-DD),每日自動旋轉
        // 同一天多次執行:append 模式,不覆蓋
        'log_format'     => env('SQL_MONITOR_ANALYSE_LOG_FORMAT', 'text'),
        // text = plain text(人讀)| json = JSON 格式
    ],

    // SQL 複雜度分析
    'complexity' => [
        'enabled'              => true,
        'persist_severity'     => env('SQL_MONITOR_PERSIST_SEVERITY', 'warning'),
        // 複雜度達到此等級(含)以上的查詢持久化到 DB 層
        // 可用值:low | info | warning(預設)| critical
        'join_threshold'       => 5,
        'subquery_depth_limit' => 3,
        'detect_select_star'   => true,
        'detect_missing_where' => true,
        'detect_like_wildcard' => true,
    ],

    // N+1 偵測
    'n1_detection' => [
        'enabled'   => true,
        'threshold' => 2,
    ],

    // 重複查詢偵測
    'duplicate_detection' => [
        'enabled' => true,
    ],

    // Slow Query 追蹤
    'slow_query' => [
        'enabled'      => true,
        'threshold_ms' => (int) env('SQL_MONITOR_SLOW_QUERY_THRESHOLD_MS', 100),
    ],

    // WebSocket 即時推送
    'live_monitor' => [
        'enabled'           => true,
        'broadcast_channel' => 'sql-monitor',
        'max_buffer_size'   => 1000,
    ],

    // Call Stack 收集
    'stack_trace' => [
        'enabled'         => true,
        'limit'           => 20,
        'exclude_vendors' => true,
    ],

    'ide'          => env('SQL_MONITOR_IDE', 'vscode'),
    'route_prefix' => 'sql-monitor',
    'middleware'    => ['web'],
];

常用 .env 設定

# 基本啟用
SQL_MONITOR_ENABLED=true

# storage driver(預設 database,使用應用程式的 DB)
SQL_MONITOR_STORAGE_DRIVER=database
# SQL_MONITOR_STORAGE_CONNECTION=   # null = database.default(留空即可)

# 若需要獨立 SQLite 檔案(不影響應用程式 DB)
# SQL_MONITOR_STORAGE_DRIVER=sqlite

# Cache 層 TTL(正常查詢在 Dashboard 的可見時間,秒)
SQL_MONITOR_MEMORY_TTL=60

# Dashboard polling 間隔(秒)
SQL_MONITOR_POLLING_INTERVAL=5

# 複雜度持久化閾值(warning = warning + critical 都寫入 DB)
SQL_MONITOR_PERSIST_SEVERITY=warning

# 靜態分析 log 輸出
SQL_MONITOR_ANALYSE_OUTPUT_PATH=storage/logs/sql-monitor
SQL_MONITOR_ANALYSE_LOG=analyse-{date}.log
SQL_MONITOR_SUGGESTION_LOG=suggestion-{date}.log
SQL_MONITOR_ANALYSE_LOG_FORMAT=text

# 慢查詢閾值(ms)
SQL_MONITOR_SLOW_QUERY_THRESHOLD_MS=100

# IDE 跳轉
SQL_MONITOR_IDE=vscode

動態分析

套件在 boot() 時自動完成以下兩件事,無需改動應用程式代碼

  1. 監聽 QueryExecuted 事件(QueryListener
  2. QueryMonitoringMiddleware 自動掛載到所有 HTTP request(全域 Middleware)

持久化邏輯

條件 寫入目的地 時機
執行時間 >= slow_query.threshold_ms DB 層 即時(QueryListener)
複雜度 >= complexity.persist_severity DB 層 即時(QueryListener)
N+1 pattern 代表查詢 DB 層 request 結束(Middleware)
重複查詢代表查詢 DB 層 request 結束(Middleware)
其餘查詢(info / low) Cache 層(TTL 60s) request 結束(Middleware)

sql_monitor_logs 資料表由套件自動建立(ensureTableExists),無需手動執行 migration。

Web Dashboard

訪問 http://localhost:8000/sql-monitor 查看:

  • 查詢摘要與統計(DB 層歷史 + Cache 層近期,每 5 秒自動更新)
  • N+1 警告面板
  • 重複查詢面板
  • 完整查詢日誌(可按 Slow / N+1 / Duplicate / Recent 篩選)
  • 歷史慢查詢列表

REST API

GET  /sql-monitor/api/queries       查詢列表(DB 層,支援 is_slow / is_n1 / is_duplicate 等 filter)
GET  /sql-monitor/api/analytics     分析數據
GET  /sql-monitor/api/slow-queries  慢查詢
GET  /sql-monitor/api/stats         統計信息
GET  /sql-monitor/api/poll          Dashboard polling(DB 層 + Cache 層合併)
DELETE /sql-monitor/api/logs        清理日誌

在程式碼中讀取指標

use LaravelSqlMonitor\Lifecycle\RequestQueryManager;
use LaravelSqlMonitor\Monitor\MetricsCollector;

$manager = app(RequestQueryManager::class);
$count   = $manager->count();
$stats   = $manager->getStats(); // slow_query_count, n1_count, ...

$metrics = app(MetricsCollector::class)->collect();

支援的資料庫

動態分析

  • MySQL / MariaDB
  • PostgreSQL
  • SQLite
  • SQL Server(基本)

靜態分析 — 索引檢查與選擇率計算

  • MySQL / MariaDB(完整支援:INFORMATION_SCHEMA + COUNT DISTINCT)
  • SQLite(基本:PRAGMA index_list)
  • PostgreSQL(待擴展)
  • SQL Server(待擴展)

CI/CD 整合

# 只顯示 warning 以上,有 critical 時 exit code = 1
php artisan sql-monitor:analyse --min-severity=warning --no-index-recommend

# JSON 輸出供後續處理
php artisan sql-monitor:analyse --format=json > analyse.json

模組結構

src/
├── StaticAnalysis/
│   ├── Ast/
│   │   ├── AstAnalyser.php              # PHP-Parser 驅動的 AST 掃描
│   │   ├── QueryChainExtractor.php      # 從 AST 節點提取查詢方法鏈
│   │   └── QueryCallSite.php            # 查詢呼叫點資料模型
│   ├── CallSiteAnalyser.php             # 規則引擎(偵測 no-limit / missing-index 等)
│   ├── CallSiteReport.php               # 分析結果資料模型
│   ├── CompositeIndexRecommender.php    # 複合索引建議演算法
│   └── IndexInspector.php               # DB 索引 / cardinality 查詢
│
├── Console/Commands/
│   └── AnalyseQueries.php              # sql-monitor:analyse 命令
│
├── Core/                               # 動態分析核心
│   ├── QueryAnalyzer.php
│   ├── ComplexityDetector.php
│   └── OptimizationSuggester.php
│
├── Lifecycle/
│   ├── N1QueryDetector.php
│   └── DuplicateQueryDetector.php
│
├── Monitor/
│   ├── SlowQueryTracker.php
│   └── LiveQueryMonitor.php
│
├── Storage/
│   ├── SqliteQueryStore.php
│   └── DatabaseQueryStore.php
│
└── Http/
    ├── Controllers/
    └── Routes/

License

MIT License © 2026.

统计信息

  • 总下载量: 31
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-04-13

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固