添加FULLTEXT索引:没有太大的区别,它是否会索引旧数据?

时间:2013-12-12 21:30:22

标签: mysql indexing myisam full-text-indexing

我有一个使用like条件的查询,它正在查杀我的服务器 (这个查询是我在慢查询日志中经常得到的)  顺便说一下,我的表有大约120k行 - 请求忽略语法错误

select * from `images` where `category` like `%,3,%` and ( `tags` like '%,tag1,%' or `tags` like '%,tag2,%' or `tags` like '%,tag3,%' or `tags` like '%,tag4,%')

我现在不想更改查询和数据库设计,因此我决定切换到myisam并使用tags列的全文索引。

之后服务器负载没有那么大变化,mysql仍然不时使用高达90%的cpu(8个诅咒中的1个)。

所以我喜欢这个全文索引......它是否会索引旧数据(在添加此索引之前)?因为它发生得非常快,我的桌子有点大。

或者它只能用于新存储的数据?

2 个答案:

答案 0 :(得分:2)

全文索引通常仅对令牌上的前缀匹配有帮助。换句话说,tags列的每一行中的所有非字母数字加下划线分隔的单词(AZ,0-9或_除以外的任何内容 - 请参阅here)将被编入索引用于前缀匹配。然后,您必须使用MATCH (tags) AGAINST ('tag1')来匹配全文索引搜索。您可以为每个标记重复这些匹配,以获得完整查询。在完全配置匹配查询后,执行Explain查询将告诉您查询构建器是否正在使用索引。

不幸的是,MySQL在如何改变全文索引/搜索方面相当有限 - 所以你大多坚持使用它的默认搜索方法(全文有几种搜索模式 - 见docs)。

答案 1 :(得分:2)

现有数据已编入索引,但根据Pyrce的建议,LIKE %[token]%的查询无法利用全文索引。

重写你的条件,这完全相当于你的初始查询(忽略stopwords and the likes):

WHERE MATCH(tags) AGAINST ('tag1 tag2 tag3 tag4' IN BOOLEAN MODE)

但是,您应该专注于规范化您的结构。在字段中存储非标量值(例如逗号分隔值)会违反first normal form

创建一个新的image_tag表并与images建立1-N关系。常规索引将允许即时查询。

CREATE TABLE image_tags (
    image_id INT,
    tag VARCHAR(50),
    PRIMARY KEY (image_id, tag),
    FOREIGN KEY (image_id) REFERENCES images(id), -- replace with "images" table's actual primary key
    KEY(tag, image_id) -- this index may be superfluous, check EXPLAIN
);

SELECT images.*
FROM images
JOIN image_tags ON image_id = images.id
WHERE tag IN ('tag1', 'tag2', 'tag3', 'tag4');

重复images.category