SphinxQL(Sphinx 的 SQL 接口)不支持標準 COUNT(*) 聚合查詢,直接執行會報語法錯誤。本文詳細說明兩種獲取總命中數的標準方法(GROUP BY dummy 技巧與 SHOW META),並深度解析 SHOW META 返回字段含義及 PHP 調用示例。
Sphinx 設計為全文搜索引擎,核心指標是 total_found(總命中文檔數),而非關系數據庫的精確行計數。為了效能,SphinxQL 故意限制聚合函數,僅在 GROUP BY 時隱式提供 @count(組內計數)。
SELECT 1 AS dummy, COUNT(*) AS c
FROM main_index
GROUP BY dummy;
結果解析:
+------+--------+-------+--------+
| id | weight | dummy | @count |
+------+--------+-------+--------+
| 1001 | 1 | 1 | 15659 |
+------+--------+-------+--------+
@count 即總命中數(total_found)。id/weight 為第一組文檔屬性,無業務意義。-- 步驟 1:執行查詢,不返回文檔
SELECT * FROM main_index WHERE MATCH('keyword') LIMIT 0;
-- 步驟 2:獲取元數據
SHOW META;
SHOW META 返回示例:
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| total | 67 |
| total_found | 67 |
| time | 0.001 |
| keyword[0] | ha |
| docs[0] | 67 |
| hits[0] | 115 |
+---------------+-------+
| Variable_name | 含義 | 備註 |
|---|---|---|
| total | 當前結果集返回的文檔數(受 LIMIT/max_matches 限制) | 若 LIMIT 0 則為 0 |
| total_found | 總命中文檔數(無視 LIMIT,真實匹配總量) | 核心指標,分頁總頁數計算依據 |
| time | 查詢耗時(秒,含網絡/解析/執行) | 性能監控關鍵 |
| keyword[N] | 第 N 個關鍵詞(經過分詞/展開後) | 多詞查詢會有多行 |
| docs[N] | 包含第 N 個關鍵詞的文檔數 | 倒排索引統計 |
| hits[N] | 第 N 個關鍵詞在所有文檔中總出現次數 | 詞頻統計 |
SELECT * FROM test1 WHERE MATCH('test|one|two') LIMIT 0;
SHOW META;
-- 返回
| keyword[0] | test |
| docs[0] | 3 |
| hits[0] | 5 |
| keyword[1] | one |
| docs[1] | 1 |
| hits[1] | 2 |
| keyword[2] | two |
| docs[2] | 1 |
| hits[2] | 2 |
<?php
class SphinxHelper {
private $conn;
public function __construct($host, $port, $user, $pass) {
$this->conn = new mysqli($host, $user, $pass, '', $port);
if ($this->conn->connect_error) {
throw new Exception("Sphinx connect failed: " . $this->conn->connect_error);
}
}
// 獲取總命中數
public function getTotalFound($query) {
// 1. 執行主查詢 LIMIT 0
$this->conn->query($query . " LIMIT 0");
// 2. SHOW META
$result = $this->conn->query("SHOW META");
$meta = [];
while ($row = $result->fetch_assoc()) {
$meta[$row['Variable_name']] = $row['Value'];
}
$result->free();
return (int)($meta['total_found'] ?? 0);
}
// 完整搜索:返回文檔列表 + 總數
public function search($index, $keywords, $offset = 0, $limit = 20) {
$sql = "SELECT * FROM `$index` WHERE MATCH('{$this->conn->real_escape_string($keywords)}') LIMIT $offset, $limit";
$docs = [];
if ($res = $this->conn->query($sql)) {
while ($row = $res->fetch_assoc()) $docs[] = $row;
$res->free();
}
$total = $this->getTotalFound("SELECT * FROM `$index` WHERE MATCH('{$this->conn->real_escape_string($keywords)}')");
return ['docs' => $docs, 'total' => $total];
}
}
// 使用
$sphinx = new SphinxHelper('127.0.0.1', 9306, '', '');
$total = $sphinx->getTotalFound("SELECT * FROM main_index WHERE MATCH('keyword')");
echo "Total found: $total";
?>
關鍵提示:若代碼使用多數據庫連接,SHOW META 必須在同一連接上緊隨主查詢執行,否則獲取的是上一條語句的元數據(或空結果)。
SphinxQL 獲取總記錄數兩大法寶:
1. SELECT 1 AS dummy, COUNT(*) FROM index GROUP BY dummy:單條語句,適合純統計。
2. SELECT ... LIMIT 0; SHOW META;:標準雙查詢,total_found 為權威總數,time/keyword[N]/docs/hits 提供豐富診斷信息。
PHP 封裝時務必綁定連接對象,確保 SHOW META 讀取正確會話上下文。