我有一个具有此结构的表,目前它包含大约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%
,因为对于某些查询,我只会有一小部分实际用户名的中心,而不是实际值开头的前几个字符。
编辑:
另外,为了这个特殊目的,狮身人面像会更好吗?
答案 0 :(得分:5)
使用Fulltext indexes,这些实际上是为此目的而设计的。现在InnoDb支持MySQL 5.6.4中的全文索引。
答案 1 :(得分:4)
答案 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)
表索引(全文索引)对于如此大量的数据是必须的。 如果可能的话,进一步去分区表。所以这些肯定会提高性能。