如何针对LIKE'%abc%'查询优化包含1600多万条记录的MySQL表

时间:2012-07-06 06:29:47

标签: mysql sql optimization

我有一个具有此结构的表,目前它包含大约160万条记录。

CREATE TABLE `chatindex` (
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `roomname` varchar(90) COLLATE utf8_bin NOT NULL,
    `username` varchar(60) COLLATE utf8_bin NOT NULL,
    `filecount` int(10) unsigned NOT NULL,
    `connection` int(2) unsigned NOT NULL,
    `primaryip` int(10) unsigned NOT NULL,
    `primaryport` int(2) unsigned NOT NULL,
    `rank` int(1) NOT NULL,
    `hashcode` varchar(12) COLLATE utf8_bin NOT NULL,
    PRIMARY KEY (`timestamp`,`roomname`,`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

房间名称和用户名列都可以包含相同的确切数据,但每个项目的唯一性和重要位来自于将时间戳与这两个项目相结合。

开始需要一段时间(10-20秒)的查询是:

SELECT timestamp,roomname,username,primaryip,primaryport 
    FROM `chatindex`
    WHERE username LIKE '%partialusername%'

我能做些什么来优化这个?我不能partialusername%,因为对于某些查询,我只会有一小部分实际用户名的中心,而不是实际值开头的前几个字符。

编辑:

另外,为了这个特殊目的,狮身人面像会更好吗?

6 个答案:

答案 0 :(得分:5)

使用Fulltext indexes,这些实际上是为此目的而设计的。现在InnoDb支持MySQL 5.6.4中的全文索引。

答案 1 :(得分:4)

  1. 在表格列用户名(全文索引)上创建索引。
  2. 作为一个想法,您可以在此表上创建一些视图,其中包含基于字母或其他条件的过滤数据,并根据您的代码决定使用哪个视图来获取搜索结果。

答案 2 :(得分:2)

您应该使用MyISAM表进行Fulltext搜索,因为它支持FULLTEXT索引,MySQL v5.6 +仍处于开发阶段,您不应该将其用作生产服务器,可能需要大约1年的时间才能完成GA

现在,您应该将此表转换为MyISAM并添加FULLTEXT索引,该索引在where子句中引用column

这些链接非常有用:

http://dev.mysql.com/doc/refman/5.0/en/create-index.html

http://dev.mysql.com/doc/refman/5.1/en/fulltext-fine-tuning.html

答案 3 :(得分:1)

在MSSQL上,这是将全文索引与CONTAIN子句一起使用的完美案例。 LIKE子句无法在如此大的表上获得良好的性能,并且需要搜索许多文本变体。

请看这个链接,有许多与dinamic search conditions相关的问题。

答案 4 :(得分:1)

如果您对当前查询进行了解释,您将看到您正在对表进行全表扫描,这就是为什么它如此慢。用户名的索引将大大加快搜索速度,因为MySQL可以缓存索引,只有匹配用户才能访问表行条目。

全文索引将实质上帮助%fred%之类的搜索匹配oldfredboy等。所以我不知道为什么其他人建议使用此功能。全文索引的作用是创建一个基于单词列表的索引,以便您搜索“解释当前查询”之类的列表,全文引擎会将包含“说明”的行ID与包含“当前”的行ID和包含“查询”的行ID相交“获取包含所有三个ID的ID列表。添加全文索引会大大增加插入,更新表的删除成本,因此会增加性能损失。此外,您需要使用特定于全文的“MATCH”语法来充分利用全文索引。

如果您在“[mysql] fulltext like”上搜索问题,请参阅进一步的讨论。

普通索引将完成您需要的所有操作。像'%fred%'这样的搜索需要对索引进行全面扫描,因此您需要尽可能保持索引的精确度。此外,如果高命中率与'fred%'相匹配,那么首先尝试类似'fred%'的搜索也是值得的,因为这将进行索引范围扫描。

还有一点,为什么使用时间戳,房间名,用户名作为主键?这对我来说没有意义。如果不使用主键作为访问路径,则auto_increment id更容易。我原以为 roomname,timestamp,username 会有所帮助,因为你肯定会在一个时间窗口内访问房间。

仅添加您将使用的索引。

答案 5 :(得分:0)

表索引(全文索引)对于如此大量的数据是必须的。 如果可能的话,进一步去分区表。所以这些肯定会提高性能。