Mysql Innodb全文搜索失败,MyIsam返回结果
我已经将一个表从Mysql Innodb全文搜索失败,MyIsam返回结果,mysql,full-text-search,innodb,myisam,mysql-5.6,Mysql,Full Text Search,Innodb,Myisam,Mysql 5.6,我已经将一个表从myisam升级到innodb,但没有相同的性能。当应该存在某种关系时,innodb返回一个0分数。myisam表返回同一术语的匹配项(我保留了旧表的一个副本,以便仍然可以运行相同的查询) 返回: +-------+ | score | +-------+ | 1 | +-------+ 但是: 返回: +-------+ | score | +-------+ | 0 | +-------+ 我认为ex可能没有被索引,因为innodb\u ft\u min\
myisam
升级到innodb
,但没有相同的性能。当应该存在某种关系时,innodb
返回一个0
分数。myisam
表返回同一术语的匹配项(我保留了旧表的一个副本,以便仍然可以运行相同的查询)
返回:
+-------+
| score |
+-------+
| 1 |
+-------+
但是:
返回:
+-------+
| score |
+-------+
| 0 |
+-------+
我认为ex
可能没有被索引,因为innodb\u ft\u min\u token\u size
被设置为3
。我将其降低到1
,并优化了表格,但没有任何影响。列内容有99个字符长,因此我假设整个列没有被索引,因为innodb\u ft\u max\u token\u size
。我也将其增加到150
,并再次运行优化,但再次得到相同的结果
这些表之间的唯一区别是引擎和字符集。此表使用的是utf8
,myisam
表使用的是latin1
有没有人看到过这些行为,或者对如何解决它有什么建议
更新:
我将ft\u stopword\u file=”“
添加到我的my.cnf
中,并再次运行优化表。这次我得到了
优化|注意|表格不支持优化,改为重新创建+分析
此更改后,查询工作正常Ex
不是一个停止词,但不知道为什么它会起作用
但失败的新查询是:
SELECT MATCH (Columns) AGAINST ('+Term +Ex +in' IN BOOLEAN MODE) as score FROM Table where id = 1;
+-------+
| score |
+-------+
| 0 |
+-------+
中的导致此操作失败,但这是我表格中的下一个单词
SELECT MATCH (Columns) AGAINST ('+Term +Ex' IN BOOLEAN MODE) as score FROM Table where id = 1;
+--------------------+
| score |
+--------------------+
| 219.30206298828125 |
+--------------------+
我还尝试了创建表my_stopwords(value VARCHAR(30))ENGINE=INNODB
,然后使用innodb\u ft\u服务器\u stopword\u table='db/my\u stopwords'更新my.cnf
。我重新启动并运行:
show variables like 'innodb_ft_server_stopword_table';
这带来了:
+---------------------------------+---------------------------+
| Variable_name | Value |
+---------------------------------+---------------------------+
| innodb_ft_server_stopword_table | 'db/my_stopwords'; |
+---------------------------------+---------------------------+
所以我认为
中的不会导致现在的查询失败,但它会继续。我还再次尝试了optimizetable TABLE
,甚至alterttable TABLE DROP INDEX…
和alterttable TABLE ADD FULLTEXT KEY…
都没有效果
第二次更新
问题在于停止语
$userinput = preg_replace('/\b(a|about|an|are|as|at|be|by|com|de|en|for|from|how|i|in|is|it|la|of|on|or|that|the|this|to|was|what|when|where|who|will|with|und|the|www)\b/', '', $userinput);
解决了这个问题,但这对我来说并不是一个好的解决方案。我想要一个解决方案,避免停止词打破mysql这一点
停止字表数据:
CREATE TABLE `my_stopwords` (
`value` varchar(30) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
及
MyISAM的全文和InnoDB的全文有几个不同之处。我认为你被“短”字和/或“停止”字的处理抓住了。MyISAM将显示行,但InnoDB将无法显示行
我在使用FT时(以及切换到InnoDB后)所做的是过滤用户的输入,以避免短词。这需要额外的努力,但能让我达到所需的行数。我的情况略有不同,因为结果查询是这样的。请注意,我添加了+
以要求输入单词,但不要求输入短于3的单词(我的ft\u min\u token\u size
为3)。这些搜索用于构建表格
和构建表格
:
WHERE match(description) AGAINST('+build* a +table*' IN BOOLEAN MODE)
WHERE match(description) AGAINST('+build* +the* +table*' IN BOOLEAN MODE)
(尾随的*
可能是多余的;我没有对此进行调查。)
另一种方法
由于FT在不短、不间断的单词方面非常有效,因此搜索分为两个阶段,每个阶段都是可选的:要搜索“长单词”,请执行以下操作
要仅搜索单词“a”:
其中d REGEXP'[[::]]
警告:这种情况将是缓慢的
注意:我的示例允许单词在字符串中的任何顺序和位置。也就是说,在我所有的例子中,这个字符串都是匹配的:“她渴望从他那里得到一个词。”这里是一个循序渐进的过程,应该重现您的问题。(这实际上是你应该如何写你的问题。)环境是一个新安装的虚拟机,带有Debian 9.8和Percona服务器版本5.6.43-84.3
使用全文索引和一些虚拟数据创建InnoDB表:
create table test.ft_innodb (
txt text,
fulltext index (txt)
) engine=innodb charset=utf8 collate=utf8_unicode_ci;
insert into test.ft_innodb (txt) values
('Some dummy text'),
('Text with a long and short stop words in it ex');
执行一个测试查询,以验证它是否按照我们的需要工作:
select txt
, match(t.txt) against ('+some' in boolean mode) as score0
, match(t.txt) against ('+with' in boolean mode) as score1
, match(t.txt) against ('+in' in boolean mode) as score2
, match(t.txt) against ('+ex' in boolean mode) as score3
from test.ft_innodb t;
结果(四舍五入):
如您所见,它不适用于停止词(“+with”)或短词(“+ex”)
为自定义停止字创建空InnoDB表:
create table test.my_stopwords (value varchar(30)) engine=innodb;
编辑/etc/mysql/my.cnf
并在[mysqld]
块中添加以下两行:
[mysqld]
# other settings
innodb_ft_server_stopword_table = "test/my_stopwords"
innodb_ft_min_token_size = 1
使用service MySQL Restart重新启动MySQL
再次从(2.)运行查询(结果应相同)
使用以下命令重建全文索引:
它将实际重建整个选项卡,包括所有索引
再次执行来自(2.)的测试查询。现在的结果是:
txt | score1 | score1 | score2 | score3
-----------------------------------------------|--------|--------|--------|-------
Some dummy text | 0.0906 | 0 | 0 | 0
Text with a long and short stop words in it ex | 0 | 0.0906 | 0.0906 | 0.0906
你看,这对我来说很好。而且很容易复制。(同样,这是你应该如何写你的问题。)
由于你的程序相当混乱而不是详细,很难说你会出什么问题。例如:
CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;
这不包含您在哪个数据库中定义该表的信息。请注意,我已在所有表前面加上了相应数据库的前缀。现在考虑下面的内容:我改变<代码>我的.CNF并设置<代码> NoNdByftServIsStudiWordDeTab= =“Db/MyOxStaseWord”< /C>。注意-我的服务器上没有这样的表(甚至架构db
也不存在)。重新启动MySQL服务器。并使用检查新设置
show variables like 'innodb_ft_server_stopword_table';
这将返回:
Variable_name | Value
--------------------------------|----------------
innodb_ft_server_stopword_table | db/my_stopwords
在优化表test.ft_innodb之后代码>测试查询返回以下内容:
txt | score0 | score1 | score2 | score3
-----------------------------------------------|--------|--------|--------|-------
Some dummy text | 0.0906 | 0 | 0 | 0
Text with a long and short stop words in it ex | 0 | 0 | 0 | 0.0906
看到了吗?它不再适用于stopwords。但它适用于像“+ex”这样不停的短单词。因此,请确保您在innodb\u ft\u server\u stopword\u表中定义的表确实存在。搜索中的一种常见技术是使用“已消毒”字符串创建一个额外的列进行搜索。然后将全文索引添加到该列
create table test.my_stopwords (value varchar(30)) engine=innodb;
[mysqld]
# other settings
innodb_ft_server_stopword_table = "test/my_stopwords"
innodb_ft_min_token_size = 1
optimize table test.ft_innodb;
txt | score1 | score1 | score2 | score3
-----------------------------------------------|--------|--------|--------|-------
Some dummy text | 0.0906 | 0 | 0 | 0
Text with a long and short stop words in it ex | 0 | 0.0906 | 0.0906 | 0.0906
CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;
show variables like 'innodb_ft_server_stopword_table';
Variable_name | Value
--------------------------------|----------------
innodb_ft_server_stopword_table | db/my_stopwords
txt | score0 | score1 | score2 | score3
-----------------------------------------------|--------|--------|--------|-------
Some dummy text | 0.0906 | 0 | 0 | 0
Text with a long and short stop words in it ex | 0 | 0 | 0 | 0.0906