3

只是说我有一个查询如下..

SELECT 
    name,category,address,city,state
FROM
    table
WHERE 
    MATCH(name,subcategory,category,tag1) AGAINST('education')
AND 
    city='Oakland'
AND
    state='CA' 
LIMIT
    0, 10;

..我有一个fulltext索引 asname,subcategory,category,tag1和一个composite索引 as city,state; 这对这个查询是否足够好?AND只是想知道在将全文索引与 MATCH/AGAINST混合使用时是否需要额外的东西。

编辑:我想了解的是,查询中但未在所选索引(全文索引)中编制索引的其他列会发生什么,上面的示例是cityand state。MySQL 现在如何为这些找到匹配的行,因为它不能使用两个索引(或者可以吗?) - 所以,基本上,我试图了解 MySQL 如何为不在所选列中的列找到最佳数据全文索引以及我可以或应该做些什么来优化查询。

4

3 回答 3

7

如果我理解您的问题,您就知道 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 只能为这个查询使用一个索引,因为它是一个简单的选择。它将使用FULLTEXTBTREE。请注意,当我说一个索引时,我的意思是一个索引定义,而不是多部分索引中的一列。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 中看到的。

于 2012-09-21T03:37:02.333 回答
1

EXPLAIN我认为您可以通过在查询中使用来轻松确定使用哪个索引。请检查这个问题的已接受答案,它提供了一些关于如何解释EXPLAIN.

MySQL 现在如何为这些找到匹配的行,因为它不能使用两个索引

是的,它可以:MySQL 可以为单个查询使用多个索引吗?此外,您应该阅读文档:MySQL 如何使用索引

于 2012-09-17T22:41:49.717 回答
1

前段时间我有类似的任务,我注意到 MySQL 可以在一个查询中使用 FULLTEXT 索引或任何其他索引/索引,但不能同时使用两者;我无法将 FULLTEXT 与任何其他索引混合。任何带有全文搜索的选择都将以这种方式工作:

  • 使用 FULLTEXT 搜索选择子集
  • 从该子集中选择与其他条件匹配的记录“使用位置”

因此,您可以使用全文索引或任何其他索引(我无法通过 FORCE INDEX 或其他任何方式使用这两个索引)。

我建议尝试使用全文和使用其他索引(即在 City 和 State 列上)并比较结果 - 它们可能会因数据库中的实际内容而异。

就我而言,我发现在此类查询中强制使用常规(非全文)索引会产生更好的性能(因为我有非常多的行,大约 300 000 行,并且非全文条件匹配其中大约 1000 个)。

我使用的是 MySQL 5.5.24

于 2012-09-20T08:27:18.933 回答