CREATE DATABASE cc;
USE cc;
CREATE TABLE string_find (
id INT AUTO_INCREMENT PRIMARY KEY,
charList VARCHAR(100)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO string_find (charList) VALUES
('鄧先驅者'), ('鄧先驅者'), ('fdafdsaf'), ('www.bKjia.c0m');
SELECT * FROM string_find WHERE charList LIKE '鄧%';
EXPLAIN 關鍵列:
type=ref / rangekey=idx_charList(需在 charList 上建索引)rows=預估匹配行數SELECT * FROM string_find WHERE charList REGEXP '^鄧';
EXPLAIN 關鍵列:
type=ALL(全表掃描)key=NULLrows=全表行數| 指標 | LIKE 'prefix%' | REGEXP '^prefix' |
|---|---|---|
| 執行時間 | ~2 ms | ~1,200 ms |
| 掃描行數 | 匹配行數 | 1,000,000 |
| 索引使用 | 是 | 否 |
| CPU 佔用 | 極低 | 高(正則引擎開銷) |
^prefix,優化器也不識別REGEXP_LIKE() 但仍不走索引-- 1. 建立前綴索引(節省空間,足夠區分度)
ALTER TABLE string_find ADD INDEX idx_charList_prefix (charList(20));
-- 2. 查詢只取需要的列(覆蓋索引)
SELECT id, charList FROM string_find WHERE charList LIKE '鄧%';
<?php
$pdo = new PDO('mysql:host=localhost;dbname=cc', 'root', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$prefix = '鄧';
$stmt = $pdo->prepare("SELECT id, charList FROM string_find WHERE charList LIKE ?");
$stmt->execute([$prefix . '%']);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo "{$row['id']} | {$row['charList']}\n";
}
| 誤區 | 正確做法 |
|---|---|
用 REGEXP 做前綴匹配 | **永遠用 LIKE 'prefix%'** |
用 LIKE '%suffix' 後綴匹配 | 建立反轉列 REVERSE(col) + 前綴匹配,或全文索引 |
用 LIKE '%mid%' 中間匹配 | 全文索引 / ES / n-gram 解析器 |
| 字符集不匹配導致索引失效 | 表/列/連接/查詢字符集**統一 utf8mb4** |
**前綴查詢 = LIKE 'prefix%' + 索引**。這是 B-Tree 索引的原生優勢,**REGEXP 完全無法利用索引**,大表嚴禁。若業務極其複雜(如模糊前綴、多模式),引入 Elasticsearch 或 MySQL 8.0 n-gram 全文解析器,切勿在 SQL 層硬扛正則。