全文和复合索引以及它们如何影响查询

Bre*_*ett 2 mysql indexing full-text-search

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

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;
Run Code Online (Sandbox Code Playgroud)

..我有fulltext索引name,subcategory,category,tag1composite索引city,state; 这个查询足够好吗?只是想知道AND在使用MATCH/AGAINST使用全文索引时混合附加内容是否需要额外的东西.

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

taz*_*r84 5

如果我理解你的问题,你知道MATCH AGAINST使用你的FULLTEXT索引,你想知道MySQL如何应用WHERE子句的其余部分(即它是做表扫描还是索引查找).

这是我对你的表的假设:它在某个id列和FULLTEXT索引上有一个PRIMARY KEY.

首先,MySQL 永远不会将FULLTEXT索引用于城市/州WHERE子句.为什么?因为FULLTEXT索引仅适用于MATCH AGAINST.见这里的第一套子弹(不是内容的子弹表)之后的段落.

编辑:在您的情况下,假设您的表不仅有10行,MySQL将为您的MATCH AGAINST应用FULLTEXT索引,然后对这些结果执行表扫描以应用城市/州WHERE.

那么如果你将BTREE指数添加到城市和州?

CREATE INDEX city__state ON table (city(10),state(2)) USING BTREE;
Run Code Online (Sandbox Code Playgroud)

那么MySQL只能为这个查询使用一个索引,因为它是一个简单的选择.它将要么使用FULLTEXT B树.请注意,当我说一个索引时,我的意思是一个索引定义,而不是多部分索引中的一个列.Anwway,这会引起人们使用的问题吗?

这取决于表格分析.MySQL将尝试估计(根据上一个OPTIMIZE TABLE中的表统计信息)哪个索引将修剪最多的记录.如果城市/状态让你到10条记录,而对阵只让你下降到100,那么MySQL将使用city__state指数第一的城市/状态,然后做了对阵表扫描.

另一方面,如果MATCH_AGAINST让你下降到10个记录,而城市/州WHERE让你下降到只有1000,那么MySQL将首先应用FULLTEXT索引并且表格扫描城市和州.

底线是索引的基数.从本质上讲,您的索引中的值有多独特?如果你的表中的每个记录都设置为奥克兰的城市,那么它不是一个非常独特的密钥,因此拥有city ='Oakland'并不会真正减少你所记录的数量.在这种情况下,我们说你的city__state索引的基数较低.

因此,如果您的FULLTEXT索引中90%的单词都是"John",那么由于完全相同的原因,这对您没有多大帮助.

如果你能负担得起空间和UPDATE/DELETE/INSERT开销,我建议添加BTREE索引并让MySQL决定他想要使用哪个索引.根据我的经验,他通常能够很好地选择合适的人选.

我希望能回答你的问题.

编辑:在旁注中,确保为您的BTREE索引选择合适的大小(在我的例子中,我选择了城市中的前10个字符).这显然会对基数产生巨大影响.如果你选择了城市(1),那么显然你会得到一个较低的基数,如果你做了城市(10).

EDIT2: MySQL的查询计划(估计),索引修剪最多的记录是你在EXPLAIN中看到的.