MySQL 对长唯一值使用 MATCH AGAINST (8.0.27)
MySQL using MATCH AGAINST for long unique values (8.0.27)
我有这样一种情况,我们在数据库中存储长的唯一 ID(最多 200 个字符),它们是单个 TEXT 条目。问题是我们出于速度目的使用 FULLTEXT 索引,它对较小的 GUID 样式条目非常有用。问题是由于 innodb_ft_max_token_size 的限制,它不适用于条目 > 84 个字符,这显然不能设置 > 84。这意味着索引中省略了任何超过 84 个字符的条目。
示例条目(我需要匹配来自不同来源的实际数据):
AQMkADk22NgFmMTgzLTQ3MzEtNDYwYy1hZTgyLTBiZmU0Y2MBNDljMwBGAAADVJvMxLfANEeAePRRtVpkXQcAmNmJjI_T7kK7mrTinXmQXgAAAgENAAAAmNmJjI_T7kK7mrTinXmQXgABYpfCdwAAAA==
和
<j938ir9r-XfrwkECA8Bxz6iqxVth-BumZCRIQ13On_inEoGIBnxva8BfxOoNNgzYofGuOHKOzldnceaSD0KLmkm9ET4hlomDnLu8PBktoi9-r-pLzKIWbV0eNadC3RIxX3ERwQABAgA=@t2.msgid.quoramail.com>
和
["ca97826d-3bea-4986-b112-782ab312aq23","ca97826d-3bea-4986-b112-782ab312aaf7","ca97826d-3bea-4986-b112-782ab312a326"]
那么我的选择是什么?有什么方法可以使用 FULLTEXT 索引获取 160 个(左右)字符的唯一字符串?
对于没有空格(最多 200 个字符)的大字符串值,我可以使用的最有效索引是什么?
以下是评论中的讨论摘要:
ID 有多种格式,可以是长度不超过 200 个字符的单个标记,也可以是一个“数组”,即具有多个标记的 JSON-formatted 文档。这些条目来自不同的来源,格式不在您的控制范围内。
MySQL 中的 FULLTEXT 索引实现的最大标记大小为 84 个字符。这无法搜索更长的标记。
您可以使用传统的 B-tree 索引(不是 FULLTEXT)来索引更长的字符串,在当前版本的 MySQL 中最多可达 3072 字节。但这不支持 JSON 多个标记数组的情况。您不能使用 B-tree 索引来搜索字符串中间的单词。您也不能使用带有 LIKE
谓词的索引来匹配在模式前面使用通配符的子字符串。
因此要使用 B-tree 索引,您必须每行存储一个标记。如果您收到一个 JSON 数组,则必须将其拆分为单独的标记并将每个标记单独存储在一行中。这意味着在将它们插入数据库之前编写一些代码来转换您收到的内容作为 id。
MySQL 8.0.17 在 JSON 数组上支持一种新的索引,称为 Multi-Value Index。如果您可以将所有标记存储为 JSON 数组,即使是那些作为单个标记接收的标记,您也可以使用这种类型的索引。但这也需要编写一些代码将 id 的单数形式转换为 JSON 数组。
底线是,如果您必须支持任何和所有格式,则没有单一的文本索引解决方案。您要么必须忍受 non-optimized 搜索,要么您需要找到一种方法来修改数据以便将其编入索引。
- 新建table 2列:a
VARCHAR(200) CHARSET ascii COLLATION ascii_bin
(BASE64需要区分大小写。)
- 您的 table 中的一行可能有多行 table。
- 使用一些简单的解析来查找 table 中的字符串(或多个字符串),将它们添加到这个新的 table。
PRIMARY KEY(that-big-column)
- 更新您的代码以对新数据执行
INSERT
新行。
现在一个简单的 BTree 查找加上 Join 将解决您的所有计划。
TEXT
不适用于索引,但 VARCHAR
达到某个限制确实有效。 200 with ascii 只有 200 字节,远低于 3072 的限制。
我有这样一种情况,我们在数据库中存储长的唯一 ID(最多 200 个字符),它们是单个 TEXT 条目。问题是我们出于速度目的使用 FULLTEXT 索引,它对较小的 GUID 样式条目非常有用。问题是由于 innodb_ft_max_token_size 的限制,它不适用于条目 > 84 个字符,这显然不能设置 > 84。这意味着索引中省略了任何超过 84 个字符的条目。
示例条目(我需要匹配来自不同来源的实际数据):
AQMkADk22NgFmMTgzLTQ3MzEtNDYwYy1hZTgyLTBiZmU0Y2MBNDljMwBGAAADVJvMxLfANEeAePRRtVpkXQcAmNmJjI_T7kK7mrTinXmQXgAAAgENAAAAmNmJjI_T7kK7mrTinXmQXgABYpfCdwAAAA==
和
<j938ir9r-XfrwkECA8Bxz6iqxVth-BumZCRIQ13On_inEoGIBnxva8BfxOoNNgzYofGuOHKOzldnceaSD0KLmkm9ET4hlomDnLu8PBktoi9-r-pLzKIWbV0eNadC3RIxX3ERwQABAgA=@t2.msgid.quoramail.com>
和
["ca97826d-3bea-4986-b112-782ab312aq23","ca97826d-3bea-4986-b112-782ab312aaf7","ca97826d-3bea-4986-b112-782ab312a326"]
那么我的选择是什么?有什么方法可以使用 FULLTEXT 索引获取 160 个(左右)字符的唯一字符串?
对于没有空格(最多 200 个字符)的大字符串值,我可以使用的最有效索引是什么?
以下是评论中的讨论摘要:
ID 有多种格式,可以是长度不超过 200 个字符的单个标记,也可以是一个“数组”,即具有多个标记的 JSON-formatted 文档。这些条目来自不同的来源,格式不在您的控制范围内。
MySQL 中的 FULLTEXT 索引实现的最大标记大小为 84 个字符。这无法搜索更长的标记。
您可以使用传统的 B-tree 索引(不是 FULLTEXT)来索引更长的字符串,在当前版本的 MySQL 中最多可达 3072 字节。但这不支持 JSON 多个标记数组的情况。您不能使用 B-tree 索引来搜索字符串中间的单词。您也不能使用带有 LIKE
谓词的索引来匹配在模式前面使用通配符的子字符串。
因此要使用 B-tree 索引,您必须每行存储一个标记。如果您收到一个 JSON 数组,则必须将其拆分为单独的标记并将每个标记单独存储在一行中。这意味着在将它们插入数据库之前编写一些代码来转换您收到的内容作为 id。
MySQL 8.0.17 在 JSON 数组上支持一种新的索引,称为 Multi-Value Index。如果您可以将所有标记存储为 JSON 数组,即使是那些作为单个标记接收的标记,您也可以使用这种类型的索引。但这也需要编写一些代码将 id 的单数形式转换为 JSON 数组。
底线是,如果您必须支持任何和所有格式,则没有单一的文本索引解决方案。您要么必须忍受 non-optimized 搜索,要么您需要找到一种方法来修改数据以便将其编入索引。
- 新建table 2列:a
VARCHAR(200) CHARSET ascii COLLATION ascii_bin
(BASE64需要区分大小写。) - 您的 table 中的一行可能有多行 table。
- 使用一些简单的解析来查找 table 中的字符串(或多个字符串),将它们添加到这个新的 table。
PRIMARY KEY(that-big-column)
- 更新您的代码以对新数据执行
INSERT
新行。
现在一个简单的 BTree 查找加上 Join 将解决您的所有计划。
TEXT
不适用于索引,但 VARCHAR
达到某个限制确实有效。 200 with ascii 只有 200 字节,远低于 3072 的限制。