2012-07-06 61 views
4

我有一个包含此结构的表,它目前包含大约160万条记录。如何优化包含LIKE'%abc%'查询的160多万条记录的MySQL表

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; 

无论是ROOMNAME和用户名的列包含相同的确切数据,但独特性和每个项目的重要位来自时间戳与这两个项目相结合。

正在启动需要一段时间(10-20秒)查询是这样的:

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

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

编辑:

此外,将狮身人面像为这个特殊的目的更好?

+0

如果你需要“%part%”,那么你必须这样做。你会用什么查询的结果?你可以在非数据库方面改变你的方法吗? – 2012-07-06 06:38:02

回答

5

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

1

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

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

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

你应该使用MyISAM表做Fulltext搜索,因为它支持FULLTEXT索引,MySQL的V5.6 +仍处于开发阶段,你不应该把它作为一个生产服务器,它可能需要约1年走GA 。

现在,你应该此表转换为MyISAM和添加是指在where子句column FULLTEXT指数:

这些链接可能是有用的:

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

+0

全文索引添加超过此查询的正常索引的优点。 'username'上的任何索引都将阻止全表扫描。这种类型的查询将不会使用全文功能。 – TerryE 2012-07-06 10:08:05

1

如果您对当前查询做一个解释,你会看到你正在对表进行全表扫描,这就是为什么它太慢了。用户名索引将大大提高搜索速度,因为MySQL可以缓存索引,并且只有匹配用户才能访问表格条目。

一个全文索引将不会重大喜欢帮助搜索%fred%匹配oldfredboy等,所以我在亏损,为什么别人都在用这个建议。全文索引的作用是创建一个基于单词表的索引,以便您可以搜索“解释当前查询”这样的列表,全文引擎将包含“explain”的行ID与包含“current”的行标识符以及包含“query “以获得包含全部三个的ID的列表。添加一个全文索引实质上增加了插入,更新了表的删除成本,所以它确实增加了性能损失。此外,您需要使用全文特定的“MATCH”语法来充分利用全文索引。

如果您对“[mysql]全文类似”进行问题搜索,请参阅此处的进一步讨论。

一个正常的索引将做你需要的一切。像'%fred%'这样的搜索需要对索引进行全面扫描,因此您需要尽可能保持索引尽可能精简。另外,如果命中率高达'fred%',那么它可能首先尝试像'fred%'搜索,因为这将执行索引范围扫描。

另外一点,为什么您使用时间戳,房间名称,用户名作为主键?这对我没有意义。如果您不使用主键作为访问路径,那么auto_increment id更容易。我原以为房间名称,时间戳,用户名会有一定的意义,因为您肯定倾向于在一个时间窗口内访问房间。

只添加您将使用的索引。

0

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