4

我有一个具有这种结构的表,它目前包含大约 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;

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

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

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

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

编辑:

另外,狮身人面像对于这个特定目的会更好吗?

4

6 回答 6

5

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

于 2012-07-06T06:39:03.003 回答
4
  1. 在表列用户名上创建索引(全文索引)。
  2. 作为一个想法,您可以在此表上创建一些视图,这些视图将包含基于字母或其他条件的过滤数据,并基于此您的代码将决定使用哪个视图来获取搜索结果。
于 2012-07-06T06:54:44.200 回答
2

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

column现在,您应该将此表转换为 MyISAM 并添加在 where 子句中引用的 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

于 2012-07-06T07:32:01.840 回答
1

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

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

如果您在“[mysql] fulltext like”上进行问题搜索以查看对此的进一步讨论。

一个普通的索引会做你需要的一切。像 '%fred%' 这样的搜索需要对索引进行全面扫描,因此您需要尽可能保持索引精简。此外,如果匹配“fred%”的命中率很高,那么首先尝试类似“fred%”搜索可能也是值得的,因为这将执行索引范围扫描。

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

仅添加您将使用的索引。

于 2012-07-06T10:02:37.090 回答
1

在 MSSQL 上,这是将全文索引与 CONTAIN 子句一起使用的完美案例。LIKE 子句在如此大的表和要搜索的文本变体如此多的情况下未能获得良好的性能。

看看这个链接,有很多与动态搜索条件相关的问题。

于 2012-07-06T06:43:09.193 回答
0

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

于 2012-07-19T02:38:38.657 回答