如何优化基于搜索关键词提取高亮文本摘要的PHP函数性能
搜索摘要提取与高亮功能优化方案
一、MySQL层处理方案(优先推荐,适合大批量数据场景)
直接在数据库层完成匹配、摘要截取逻辑,避免将全量text字段拉取到PHP侧,大幅减少网络IO和PHP内存开销,单请求处理数千条数据的效率提升非常明显:
SELECT -- 其他业务字段按需添加 id, -- 计算关键词首次出现的位置(不区分大小写) @match_pos := IF(LOCATE(LOWER(:search_key), LOWER(text_content)) = 0, 1, LOCATE(LOWER(:search_key), LOWER(text_content))) AS match_pos, @search_len := CHAR_LENGTH(:search_key) AS search_len, @text_len := CHAR_LENGTH(text_content) AS text_len, -- 直接生成带前后缀的摘要 CONCAT( IF(@match_pos > 100, '...', ''), SUBSTRING(text_content, IF(@match_pos > 100, @match_pos - 100, 1), @search_len + 200), IF(@match_pos < @text_len - 100 - @search_len, '...', '') ) AS excerpt FROM your_table -- 前置过滤掉不包含关键词的行,减少后续处理量 WHERE LOWER(text_content) LIKE CONCAT('%', LOWER(:search_key), '%')
- 如果你的MySQL版本>=5.7,可给text字段建立全文索引,用
MATCH() AGAINST()替代LIKE做匹配,检索性能还能再提升5~10倍。 - 高亮逻辑如果要在MySQL层实现,可以自定义UDF函数,对性能要求极高的场景可以考虑。
二、PHP层现有代码优化(无需修改SQL逻辑的场景)
现有代码可优化冗余计算、替换更高性能的字符串处理函数,整体性能可提升30%以上:
function substrExcerpt(string $search, string $text): string { $search = trim($search); // 空关键词直接返回前200字摘要 if ($search === '') { return htmlspecialchars(mb_substr($text, 0, 200) . (mb_strlen($text) > 200 ? '...' : ''), ENT_QUOTES); } $pos = mb_stripos($text, $search); $searchLength = mb_strlen($search); $textLength = mb_strlen($text); // 无匹配返回前200字 if ($pos === false) { $excerpt = mb_substr($text, 0, 200) . ($textLength > 200 ? '...' : ''); } else { if ($textLength < $searchLength + 200) { $excerpt = $text; } else { $start = max(0, $pos - 100); $prefix = $start > 0 ? '...' : ''; $suffix = ($pos + $searchLength + 100) < $textLength ? '...' : ''; $excerpt = $prefix . mb_substr($text, $start, $searchLength + 200) . $suffix; } } // 用str_ireplace替代正则替换,减少不必要的正则解析开销 $escapedExcerpt = htmlspecialchars($excerpt, ENT_QUOTES); $escapedSearch = htmlspecialchars($search, ENT_QUOTES); return str_ireplace($escapedSearch, "<b>{$escapedSearch}</b>", $escapedExcerpt); }
- 批量处理场景可提前把关键词转义好,不用每次在函数内重复转义,进一步减少计算量。
三、成熟现成方案参考
- 数据量>10万、搜索请求量高的场景,可部署Elasticsearch/OpenSearch,内置了经过工业级优化的摘要提取、关键词高亮能力,性能是自建逻辑的数倍。
- 不想额外部署服务的场景,可直接使用PHP轻量检索库
teamtnt/tntsearch,纯PHP实现无额外依赖,内置了完整的关键词匹配、摘要提取、高亮功能,开箱即用。
内容的提问来源于stack exchange,提问作者shock_gone_wild
相关产品推荐
相关产品推荐

