【发布时间】:2019-04-09 15:00:06
【问题描述】:
我已将表从 myisam 升级到 innodb,但性能不一样。当应该存在某种关系时,innodb 返回一个0 分数。 myisam 表返回相同术语的匹配项(我保留了旧表的副本,因此我仍然可以运行相同的查询)。
SELECT MATCH (COLUMNS) AGAINST ('+"Term Ex"' IN BOOLEAN MODE) as score
FROM table_myisam
where id = 1;
返回:
+-------+
| score |
+-------+
| 1 |
+-------+
但是:
SELECT MATCH (COLUMNS) AGAINST ('+"Term Ex"' IN BOOLEAN MODE) as score
FROM table
where id = 1;
返回:
+-------+
| score |
+-------+
| 0 |
+-------+
我认为ex 可能没有被编入索引,因为innodb_ft_min_token_size 被设置为3。我将其降低到1 并优化了表格,但这没有影响。列内容的长度为 99 个字符,因此我推测由于 innodb_ft_max_token_size 而没有为整个列编制索引。我也将其增加到 150 并再次运行优化,但再次得到相同的结果。
这些表之间的唯一区别是引擎和字符集。此表使用utf8,myisam 表使用latin1。
有没有人看到这些行为,或者有解决方法的建议?
更新:
我将ft_stopword_file="" 添加到我的my.cnf 并再次运行OPTIMIZE TABLE table。这次我得到了
优化 |注意 |表不支持优化,做recreate+analyze代替
此更改后查询有效。 Ex 不是停用词,但不知道为什么它会有所作为。
一个失败的新查询是:
SELECT MATCH (Columns) AGAINST ('+Term +Ex +in' IN BOOLEAN MODE) as score FROM Table where id = 1;
+-------+
| score |
+-------+
| 0 |
+-------+
in 导致此操作失败,但这是我表中的下一个单词。
SELECT MATCH (Columns) AGAINST ('+Term +Ex' IN BOOLEAN MODE) as score FROM Table where id = 1;
+--------------------+
| score |
+--------------------+
| 219.30206298828125 |
+--------------------+
我也尝试了CREATE TABLE my_stopwords(value VARCHAR(30)) ENGINE = INNODB;,然后将my.cnf 更新为innodb_ft_server_stopword_table='db/my_stopwords'。我重新启动并运行:
show variables like 'innodb_ft_server_stopword_table';
带回来的:
+---------------------------------+---------------------------+
| Variable_name | Value |
+---------------------------------+---------------------------+
| innodb_ft_server_stopword_table | 'db/my_stopwords'; |
+---------------------------------+---------------------------+
所以我认为in 现在不会导致查询失败,但它会继续。我也再次尝试了OPTIMIZE TABLE table,甚至ALTER TABLE table DROP INDEX ... 和ALTER TABLE 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
和
Name: my_stopwords
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 0
Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: 2019-04-09 17:39:55
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
【问题讨论】:
-
请同时发布
columns的值(或值 - 如果它是一个复合索引)。 -
@PaulSpiegel 是 14 列的列表。我应该添加它,还是只添加一个
create table声明? -
重现问题不需要 14 列。创建一个包含两行、两列和值的示例表,它们具有相同的问题。
-
@PaulSpiegel 我认为这些证明了这个问题。 db-fiddle.com/f/t9iXPrxq1ZwPa6CPzdiL6M/2db-fiddle.com/f/t9iXPrxq1ZwPa6CPzdiL6M/3
-
您无法在 DB-fiddle 上演示它,因为您无法覆盖全局或只读变量。我已经在本地机器上使用 v5.6.21 对其进行了测试 - 并且无法重现您的问题。 “+Term +Ex +In”有一个非零值。这就是为什么我要求创建一个MCVE。
标签: mysql full-text-search innodb myisam mysql-5.6