MySQL中like模糊查询如何优化
在MySQL中like模糊查询可能会导致性能问题,特使是当使用通配符%开头时,因为这通常会导致全表扫描,以下方法可以帮助优化like模糊查询
本文以支付交易表t_pay为例
CREATE TABLE `t_pay` (`id` int unsigned NOT NULL AUTO_INCREMENT,`pay_no` varchar(50) NOT NULL COMMENT '支付流水号',`order_no` varchar(50) NOT NULL COMMENT '订单流水号',`user_id` int DEFAULT '1' COMMENT '用户账号ID',`amount` decimal(8,2) NOT NULL DEFAULT '9.90' COMMENT '交易金额',`deleted` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_pay_no` (`pay_no`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='支付交易表';
1.使用前缀匹配
使用like ‘XXX%’(%在后的形式),这种情况MYSQL会走索引
SELECT * from t_pay where pay_no like 'a2%'
但是使用like ‘%XXX’,这种情况MySQL不会走索引
SELECT * from t_pay where pay_no like '%a2'
2.使用反向索引
对于实际需要匹配后缀的情况(like ‘%XXX’),可以创建一个辅助列存储反转后内容,并基于此列进行前缀匹配
ALTER TABLE t_pay add reversed_pay_no varchar(50);
update t_pay set reversed_pay_no = REVERSE(pay_no);
CREATE INDEX idx_reversed_pay_no ON t_pay(reversed_pay_no);SELECT * from t_pay where reversed_pay_no like '2a%'
3.限制扫描范围
在有like查询中,若可以通过其他条件进一步缩小搜索范围,应尽量加入这些条件
SELECT * from t_pay where create_time >'2025-07-09 09:00:00' and pay_no like 'a2%'
4.使用缓存
对于经常需要查询的,可考虑在应用层实施缓存策略减少数据库负载,如使用Redis等
5.使用专业工具
对于非常大的数据集或需要复杂文本处理或搜索功能,可使用外部全文搜索引擎如ES,Solr等