优化含大量LIKE条件的MySQL查询性能问题
25K行entities表关键词筛选优化方案
先修正否定条件的逻辑错误
你当前的否定条件逻辑完全错误——用OR会导致只要某一行不匹配其中一个否定关键词就被保留,根本达不到「排除所有包含任意否定关键词的行」的目的。正确逻辑应该是所有否定关键词都不匹配,要把否定条件里的OR换成AND:
SELECT id, title, description FROM entities WHERE ( title LIKE '%keyword_1%' OR description LIKE '%keyword_1%' OR title LIKE '%keyword_2%' OR description LIKE '%keyword_2%' OR title LIKE '%keyword_3%' OR description LIKE '%keyword_3%' ) AND ( title NOT LIKE '%negative_keyword_1%' AND description NOT LIKE '%negative_keyword_1%' AND title NOT LIKE '%negative_keyword_2%' AND description NOT LIKE '%negative_keyword_2%' AND title NOT LIKE '%negative_keyword_3%' AND description NOT LIKE '%negative_keyword_3%' )
逻辑修正后,既能避免无效数据被保留,也能减少后续不必要的计算开销。
用布尔模式的全文索引替代LIKE
你之前用MATCH() AGAINST()性能差,大概率是没用到布尔模式,或者没创建正确的联合全文索引。
第一步:创建联合全文索引
针对title和description字段创建联合全文索引:
CREATE FULLTEXT INDEX idx_entities_title_desc ON entities(title, description);
第二步:用布尔模式编写查询
布尔模式支持+(必须包含)、-(必须排除)、*(通配符)等操作,完美适配你的需求:
SELECT id, title, description FROM entities WHERE MATCH(title, description) AGAINST( 'keyword_1 keyword_2 keyword_3 -negative_keyword_1 -negative_keyword_2 -negative_keyword_3' IN BOOLEAN MODE );
注:如果需求是「包含任意关键词」而非「包含所有关键词」,直接写关键词即可——布尔模式下默认是OR逻辑,只要匹配任意一个关键词就算符合条件;如果需要强制匹配所有关键词,给每个关键词加+前缀即可。
这个方案性能远优于LIKE,因为全文索引是专门为文本检索设计的,不会像LIKE那样触发全表扫描。
用正则表达式简化多LIKE的OR逻辑
如果暂时不想改全文索引,可以把多个LIKE的OR合并成一个REGEXP,减少SQL语句复杂度,也能小幅提升性能:
SELECT id, title, description FROM entities WHERE (title REGEXP 'keyword_1|keyword_2|keyword_3' OR description REGEXP 'keyword_1|keyword_2|keyword_3') AND (title NOT REGEXP 'negative_keyword_1|negative_keyword_2|negative_keyword_3' AND description NOT REGEXP 'negative_keyword_1|negative_keyword_2|negative_keyword_3')
不过正则的性能仍不如全文索引,适合关键词数量不多的场景。
预处理分词存储(长期优化方案)
如果你的业务高频做这类关键词检索,可以提前把title和description的分词结果(比如用分词工具拆分后的词语)存储到单独字段,比如keywords:
- 存储为逗号分隔字符串:
'苹果,手机,智能',查询用FIND_IN_SET('keyword', keywords) - 或存储为JSON数组:
["苹果","手机","智能"],查询用JSON_CONTAINS(keywords, '"keyword"')
这种方案需要在数据插入/更新时做预处理,但查询时性能极高,还能给预处理后的字段加普通索引进一步提速。
内容的提问来源于stack exchange,提问作者Vasyl
相关产品推荐
相关产品推荐

