如果我理解您的问题,您就知道 MATCH AGAINST 使用您的 FULLTEXT 索引,并且您想知道 MySQL 如何应用 WHERE 子句的其余部分(即它是执行表扫描还是索引查找)。
这是我对您的表的假设:它在某些 id 列和 FULLTEXT 索引上有一个 PRIMARY KEY。
所以首先,MySQL永远不会为城市/州 WHERE 子句使用 FULLTEXT 索引。为什么?因为 FULLTEXT 索引仅适用于 MATCH AGAINST。请参见第一组项目符号后面的段落(不是目录项目符号)。
编辑:在您的情况下,假设您的表不仅有 10 行,MySQL 将为您的 MATCH AGAINST 应用 FULLTEXT 索引,然后对这些结果进行表扫描以应用城市/州 WHERE。
那么,如果您将 BTREE 索引添加到城市和州呢?
CREATE INDEX city__state ON table (city(10),state(2)) USING BTREE;
那么 MySQL 只能为这个查询使用一个索引,因为它是一个简单的选择。它将使用FULLTEXT或BTREE。请注意,当我说一个索引时,我的意思是一个索引定义,而不是多部分索引中的一列。Anwway,这就引出了一个问题,它使用的是哪一个?
这取决于表格分析。MySQL 将尝试估计(基于上一个 OPTIMIZE TABLE 的表统计信息)哪个索引将修剪最多的记录。如果城市/州 WHERE 将您减少到 10 条记录,而 MATCH AGAINST 仅将您减少到 100,则 MySQL 将首先使用 city__state 索引来查找城市/州 WHERE,然后为 MATCH AGAINST 执行表扫描。
另一方面,如果 MATCH_AGAINST 让你减少到 10 条记录,而城市/州 WHERE 让你只剩下 1000 条,那么 MySQL 将首先应用 FULLTEXT 索引,然后对城市和州应用表扫描。
底线是索引的基数。本质上,将进入您的索引的值有多独特?如果您表中的每条记录都将 city 设置为 Oakland,那么它不是一个非常独特的键,因此city = 'Oakland'并不会真正减少您的记录数量。在这种情况下,我们说您的 city__state 索引具有低基数。
因此,如果您的 FULLTEXT 索引中 90% 的单词是“John”,那么出于完全相同的原因,这也对您没有太大帮助。
如果你能负担得起空间和 UPDATE/DELETE/INSERT 开销,我建议添加 BTREE 索引并让 MySQL 决定他想使用哪个索引。根据我的经验,他通常会很好地挑选合适的人。
我希望这能回答你的问题。
编辑:附带说明,确保为 BTREE 索引选择正确的大小(在我的示例中,我选择了 city 中的前 10 个字符)。这显然会对基数产生巨大影响。如果您选择城市(1),那么显然您将获得比城市(10)更低的基数。
EDIT2: MySQL 的查询计划(估计)哪个索引修剪最多记录是您在 EXPLAIN 中看到的。