复合索引中列的顺序

时间:2016-10-29 05:37:21

标签: mysql sql indexing

我有一张这样的表:

// posts
+----+-------------+-----------------------------+
| id |    title    |             body            |
+----+-------------+-----------------------------+
| 1  | First Post  | The content of first post   |
| 2  | Second Post | The content of second post  |
+----+-------------+-----------------------------+

现在我需要搜索titlebody列。注意到我想要搜索这两列作为全文

我的问题:我是否需要在这两列上分别制作一个复合索引或分别在它们上制作两个单个索引?

换句话说,哪一个?

  • 索引:tb(title,body) |查询:WHERE MATCH(title,body) AGAINST(?,?)
  • 索引:t(title), b(body) |查询:WHERE MATCH(title) AGAINST(?) OR MATCH(body) AGAINST(?)

老实说,我无法理解这些的不同^。

同样是的,我知道,我的问题标题与内容不符。

2 个答案:

答案 0 :(得分:1)

首先,将通过主键或唯一键列自动创建索引。因此,我建议根据您的选择性制作主键。

第二件事是索引字符串值比读取和写入操作的整数值慢得多。不幸的是,您所需的两列都是字符串。

现在,如果您使用tb(title,body)这样的复合索引,那么在您调整WHERE MATCH(title)而不是WHERE MATCH(body)时,您将获益。

我建议使用两个不同于复合索引的索引,但这会导致写入速度变慢。但是根据基本原则,我总是建议尽量减少索引宽度,因为它减少了索引的大小和读取索引所需的磁盘I / O读取次数。

使用两个不同的索引,单个索引将根据您使用的列的条件而起作用。

答案 1 :(得分:1)

你的两个索引选项会给你(除了极少数涉及myisam表的情况)相同的行,但有一些细微的差别:

  • 组合的全文索引将至少快50%,因为它只需要查找一个索引而不必将两个结果合并
  • 如果要在其他查询中执行此操作,则组合的全文索引将不允许您仅在两列中的一列中进行搜索。虽然你当然可以创建所有三个索引来保持这种可能性。
  • 生成的顺序会有所不同:自然语言搜索模式(默认模式)除非您在查询中指定不同的顺序,否则将按相关性自动排序(在第二种情况下没有直接含义)。在大多数情况下,没有相关性排序进行此类搜索是没有意义的,因此您必须指定一个订单,例如order by (MATCH(title) AGAINST(?) + MATCH(body) AGAINST(?))。这会使您的查询减慢一些。
  • 因为相关性是根据所有其他行的内容计算/规范化的,并且每个索引的内容对于这两种情况不同,order by (MATCH(title) AGAINST(?) + MATCH(body) AGAINST(?))将产生与order by MATCH(title, body) AGAINST(?,?)略有不同的顺序(其中是自然模式下的默认顺序)。但要再次强调,你将得到相同的行,只是略有不同的顺序。
  • 如果使用一个索引,则不能使第一列比第二列更重要,它们将被视为一列。如果您有单独的索引,则可以计算个人相关性,例如order by (MATCH(title) AGAINST(?) + MATCH(body) AGAINST(?) * 0.5)使主题中的结果比正文中的结果更重要

所以,总结一下:

  • 一个组合的全文索引:更快,但无法控制列的相对权重。如果您不需要权重,请使用此权重。
  • 两个全文索引:较慢,但控制列权重(如果使用不正确,可能会搞乱)。如果你需要重量,请使用它。