MySQL LIKE 查詢效能測試:百分號數量不影響執行速度,多條件拆分更優
常見迷思:LIKE '%abc%def%' 中百分號越多越慢?實測證明:百分號數量不影響執行速度,關鍵在於前導百分號導致全表掃描與條件寫法。本文呈現實測數據與優化建議。
實測環境
- 表:
goods,約 10 萬行
- 欄位:
goods_name VARCHAR(200),無索引(前導 % 無法用索引)
- 條件:
stime/etime 時間範圍過濾,flag 排序
三組測試語句與耗時
| # | SQL 寫法 | 耗時 (秒) | 說明 |
| 1 | WHERE goods_name LIKE '%iPhone%iPod%' | 0.0489 / 0.0691 / 0.0485 / 0.0467 | 單 LIKE 多個關鍵字 |
| 2 | WHERE goods_name LIKE '%iPhone%' AND goods_name LIKE '%iPod%' | 0.0460 / 0.0430 / 0.0493 / 0.0783 / 0.0496 | 多 LIKE 條件 AND 連接(推薦) |
| 3 | WHERE goods_name LIKE '%%%%%%%%%iPhone%iPod%%%%%%%%%' | 0.0458 / 0.0441 / 0.0449 | 大量百分號(無影響) |
結論
- 百分號數量不影響速度:MySQL 內部正則/模式匹配引擎處理
% 為「任意長度字符」,多個連續 % 自動合併優化
- 多條件
AND 拆分略優:LIKE '%a%' AND LIKE '%b%' 允許優化器短路求值(先匹配選擇率高的),單 LIKE '%a%b%' 需完整匹配模式
- 前導
% 導致全表掃描:無論多少百分號,LIKE '%xxx' 無法使用 B+樹索引,必須全表掃描
優化建議
| 場景 | 方案 | 效果 |
| 固定前綴搜尋 | LIKE 'prefix%' | 可用索引範圍掃描,極快 |
| 全文搜尋需求 | MySQL 5.6+ FULLTEXT INDEX + MATCH() AGAINST() | 倒排索引,支援自然語言/布爾模式 |
| 高並發模糊搜尋 | Elasticsearch / Solr 外掛 | 專業搜尋引擎,分詞、評分、高亮 |
| 小表/低頻查詢 | 前導 % 全表掃描可接受 | 資料量 <10萬、QPS 低時無需優化 |
索引條件下推 (ICP) 5.6+
若有複合索引 (stime, etime, goods_name),且查詢 WHERE stime < ? AND etime > ? AND goods_name LIKE '%xxx%',ICP 會在儲存引擎層過濾 goods_name,減少回表次數,但前導 % 仍無法用索引查找,僅能過濾已讀取的行。
最佳實踐建議
- 優先用多條件 AND 拆分:
LIKE '%a%' AND LIKE '%b%'
- 避免前導 %:業務允許時改為前綴匹配或全文索引
- 大表必上搜尋引擎:ES 解決模糊搜尋、分詞、同義詞、評分
- EXPLAIN 驗證:確認
type=ALL (全表掃描) vs type=range/ref (索引)
百分號數量是偽議題,前導百分號才是效能殺手。寫法上 LIKE '%a%' AND LIKE '%b%' 優於 LIKE '%a%b%',但根治之道在於「不讓前導 % 落在大表上」—— 用索引、用全文、用 ES。