Zend Framework 1.x 的 Zend_Db_Profiler 內建於 Zend_Db 連線物件,可詳細記錄每條 SQL 的執行時間、參數、影響行數,是開發階段 SQL 優化、除錯的利器。本文示範啟用、查詢統計、單條分析、總耗時等核心用法。
在建立資料庫連線時設定 'profiler' => true:
$config = [
'host' => '127.0.0.1',
'username' => 'root',
'password' => '111',
'dbname' => 'test',
'profiler' => true // 關鍵:啟用分析器
];
$db = Zend_Db::factory('PDO_Mysql', $config);
<?php
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Db');
Zend_Loader::loadClass('Zend_Db_Statement_Pdo');
$config = [
'host' => '127.0.0.1', 'username' => 'root', 'password' => '111',
'dbname' => 'test', 'profiler' => true
];
$db = Zend_Db::factory('PDO_Mysql', $config);
$db->query('SET NAMES utf8');
// 執行任意查詢
$db->query('SELECT * FROM gongsi');
$db->query('SELECT COUNT(*) FROM sanguo WHERE s_gongzi > 3000');
// 1. 取得 Profiler 實例
$profiler = $db->getProfiler();
// 2. 總查詢數
echo "總查詢數: " . $profiler->getTotalNumQueries() . "<br>";
// 3. 總耗時 (秒,含微秒)
echo "總耗時: " . $profiler->getTotalElapsedSecs() . " 秒<br>";
// 4. 逐條查詢詳細資訊
$profiles = $profiler->getQueryProfiles();
foreach ($profiles as $query) {
echo "<strong>SQL:</strong> " . htmlspecialchars($query->getQuery()) . "<br>";
echo "<strong>耗時:</strong> " . $query->getElapsedSecs() . " 秒<br>";
echo "<strong>參數:</strong> " . print_r($query->getQueryParams(), true) . "<br>";
echo "<strong>影響行數:</strong> " . $query->getRowCount() . "<br><hr>";
}
// 5. 取得最慢查詢
$slowest = $profiler->getLongestQueryProfiles();
if ($slowest) {
echo "最慢查詢: " . $slowest[0]->getQuery() . " (" . $slowest[0]->getElapsedSecs() . " 秒)";
}
// 6. 依類型過濾 (SELECT/INSERT/UPDATE/DELETE)
$selectProfiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);
echo "SELECT 查詢數: " . count($selectProfiles);
// 7. 關閉/重置 Profiler
$profiler->setEnabled(false); // 暫停記錄
$profiler->clear(); // 清除已記錄資料
| 方法 | 回傳值 | 說明 |
|---|---|---|
getTotalNumQueries() | int | 已記錄查詢總數 |
getTotalElapsedSecs() | float | 所有查詢總耗時 (秒) |
getQueryProfiles($type = null) | Zend_Db_Profiler_Query[] | 所有查詢記錄,可選類型過濾 |
getLastQueryProfile() | Zend_Db_Profiler_Query / null | 最後一條查詢記錄 |
getLongestQueryProfiles() | Zend_Db_Profiler_Query[] | 最慢查詢 (可能多條並列) |
setEnabled(bool) | $this | 啟用/停用記錄 |
setFilterQueryType(int) | $this | 設定記錄過濾類型 (位元遮罩) |
setFilterElapsedSecs(float) | $this | 僅記錄超過指定秒數的查詢 |
clear() | $this | 清除所有記錄 |
| 方法 | 說明 |
|---|---|
getQuery() | 原始 SQL 字串 (含佔位符) |
getQueryParams() | 綁定參數陣列 |
getElapsedSecs() | 單條查詢耗時 (秒) |
getRowCount() | 影響/返回行數 |
getQueryType() | 查詢類型常數 (SELECT/INSERT/UPDATE/DELETE) |
// 僅記錄超過 0.1 秒的查詢 (找出慢查詢)
$profiler->setFilterElapsedSecs(0.1);
// 僅記錄 SELECT 和 INSERT
$profiler->setFilterQueryType(Zend_Db_Profiler::SELECT | Zend_Db_Profiler::INSERT);
// 結合使用:找出慢 SELECT
$profiler->setFilterElapsedSecs(0.05)
->setFilterQueryType(Zend_Db_Profiler::SELECT);
dispatchLoopShutdown,將 Profiler 結果輸出至 FirePHP、Chrome Logger 或頁面底部。$this->assertLessThan(0.05, $profiler->getTotalElapsedSecs()) 確保查詢效能不退化。getQueryParams() 確認預處理正確運作,避免 SQL 注入風險。class My_Profiler extends Zend_Db_Profiler {
public function queryEnd($queryId) {
parent::queryEnd($queryId);
$profile = $this->getLastQueryProfile();
if ($profile->getElapsedSecs() > 0.5) {
error_log("SLOW QUERY [{$profile->getElapsedSecs()}s]: {$profile->getQuery()}");
// 或發送至 StatsD/InfluxDB
}
}
}
// 使用
$db->setProfiler(new My_Profiler());
Connection::setSQLLogger(),支援 Monolog、Symfony Stopwatch。DB::listen(fn($q) => Log::debug($q->sql, $q->bindings, $q->time))。long_query_time=0.1,生產環境最權威。Zend_Db_Profiler 以零侵入式設計,讓開發者輕鬆掌握每個請求的 SQL 行為。善用過濾、最慢查詢、參數檢視等功能,能在上線前捕獲 90% 的效能問題。現代專案雖遷移至新框架,但「測量、分析、優化」的核心思維永不過時。