3

以下 MYSQL 语句耗时 0.577251 秒:

SELECT synonym_group FROM synonym WHERE name LIKE '%ak%'

名称是一个 varchar(250) 字段。同义词数据库表中当前有 356,187 条记录。数据:21 MB。索引:23 MB。总大小:45 MB。每行字节数:67。

那么 0.577251 秒是一个合理的时间吗?如果不是,那是什么,我应该怎么做?我已经阅读了有关此类问题的几个主题,我可以看到的主要解决方案是使用 sphinx 之类的东西。

事实上,我表中的几个字段可能是无关的。例如,如果我通过消除不必要的字段将每行的字节数减少一半,那会使搜索速度提高一倍吗?

提前致谢。

4

3 回答 3

5

如果您使用LIKE以开头的运算符,%那么您的选择将不会使用任何索引。

所以,是的,那个时间是正常的。

于 2012-04-15T19:51:32.440 回答
4

如果ak是一个单词,那么 FULLTEXT 索引将起作用(如果您调整最小单词长度,请参见下文)。

因此,使用 FULLTEXT 索引搜索“ak”将与此匹配:

  • “这就是那个。”
  • 'AK'
  • 'AK。任何。'
  • '任何。啊。

但是,它与此不匹配:

  • 'BAK'
  • 'AKT'

必须有单词边界才能匹配。

FULLTEXT 搜索的默认最小字长为 4 个字符。因此,您仍然无法对 'ak' 进行 FULLTEXT 搜索,因为它太短了。您可以降低最小字长设置,但最终会得到 'the'、'and' 和所有其他三个或更短的字母单词,您不想弄乱 FULLTEXT 索引。

使用 LIKE 搜索可能是您唯一可行的选择。当您使用前导通配符 ( '%ak') 时,MySQL 无法利用索引来定位记录。它必须扫描所有行。不过,如果您有覆盖索引,它将使用索引进行扫描。

因此,对于您的查询:

SELECT synonym_group FROM synonym WHERE name LIKE '%ak%'

如果你有一个多列、覆盖、索引 on (name, synonym_group),它实际上仍然会使用索引来回答查询,但不是传统意义上的。MySQL会扫描索引,一般比扫描实际表数据(表扫描)要快。另外,理想的系统有足够的 RAM 来将所有索引存储在 RAM 中,因此它只是扫描内存而不是磁盘。

因此,使用覆盖索引,行的大小将不起作用。

如果没有覆盖索引,行的大小会影响扫描速度,因为磁盘必须移动得更远。

如果您最终进行了表扫描,您将希望对表进行碎片整理,并且最好具有固定长度的行(CHAR 而不是 VARCHAR)。

于 2012-04-15T21:45:15.160 回答
3

正如 juergen d 所提到的,以 % 开头的搜索不能使用您的索引,并且必须扫描整个表(不好并且随着表大小的增加只会变得更糟)。减少列数可能无济于事,因为真正的 CPU 消耗是循环遍历每一行中的字符串。

在这种情况下,您应该考虑使用全文搜索和索引: http ://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

于 2012-04-15T19:58:22.437 回答