Sphinx自动补全返回空结果问题排查求助
首先,最可能导致自动补全无结果的原因是PDO参数绑定的引号冲突,我们来一步步拆解问题:
1. 核心问题:MATCH语句的引号重复
看你代码里的SQL语句:
$stmt = $ln_sph->prepare("SELECT * FROM ".implode(",", $used_indexes)." WHERE MATCH(':match') LIMIT 0,10 OPTION ranker=sph04");
这里你在:match外面已经手动加了单引号,但PDO在绑定字符串参数时,会自动给参数值包裹单引号。比如当$query是пирс*时,最终生成的SQL会变成:
SELECT * FROM app_catalog_prod_suggests WHERE MATCH(''пирс*'') LIMIT 0,10 OPTION ranker=sph04
Sphinx会把''пирс*''当成一个包含单引号的搜索词,自然匹配不到任何结果——而你用mysql客户端直接执行时,是手动写的MATCH('пирс*'),没有重复引号,所以能正常返回结果。
修正方案
把SQL里的单引号去掉,让PDO来处理引号:
$stmt = $ln_sph->prepare("SELECT * FROM ".implode(",", $used_indexes)." WHERE MATCH(:match) LIMIT 0,10 OPTION ranker=sph04");
这样PDO绑定参数时会自动给$query加上正确的单引号,生成的SQL就和你手动执行的一致了。
2. 次要检查点:字符集与字符串长度计算
字符集一致性
虽然你在PDO初始化时加了SET NAMES utf8,但要确保PHP的内部字符集也是UTF-8,避免mb_strlen计算错误。可以在代码开头添加:
mb_internal_encoding('UTF-8');
否则对于俄文字符,mb_strlen可能无法正确计算长度,导致通配符*的添加逻辑出错。
通配符添加逻辑验证
你当前的逻辑是判断最后一个单词长度是否≥3才加*,可以在绑定参数前打印一下最终的$query值,确认是否和你手动测试的一致(比如пирс是否变成了пирс*)。
3. 额外验证:查看Sphinx查询日志
打开你的query_log(配置里的query_log=/path/to/querylog),查看自动补全请求对应的SQL语句,对比和你手动执行的语句是否一致。这是排查Sphinx问题最直接的方式——如果日志里的SQL有重复引号,就坐实了第一个问题。
总结
优先修正MATCH语句的引号问题,这是最可能的根源。如果问题还存在,再检查字符集和查询日志,确认请求的SQL是否符合预期。
内容的提问来源于stack exchange,提问作者Rulisp

