【问题标题】:The order of columns in composite indexes复合索引中的列顺序
【发布时间】:2017-03-12 00:18:00
【问题描述】:

我有一张这样的桌子:

// 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(?)

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


我也知道,我的问题的标题与内容不匹配。

【问题讨论】:

  • 那是FULLTEXT tb(title, body) 吗?还是INDEX tb(title, body)?前者适用于MATCH;后者没有。

标签: mysql sql indexing


【解决方案1】:

首先,索引将在主键或唯一键列上自动创建。所以我想建议你根据你的选择性来制作你的主键。

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

现在,如果您使用像tb(title,body) 这样的复合索引,您将在条件WHERE MATCH(title) 时受益,但不适用于WHERE MATCH(body)

我建议使用两个不同的索引而不是复合索引,尽管它会导致您的写入速度更慢。但根据基本原则,我始终建议尽可能减小索引宽度,因为它可以减少索引大小和读取索引所需的磁盘 I/O 读取次数。

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

【讨论】:

  • 错了。或者至少是误导。 PRIMARY KEYUNIQUE 给你常规的INDEXes,而不是FULLTEXT 索引。使用MATCH 需要FULLTEXT 索引,不能是PRIMARYUNIQUE
【解决方案2】:

您的两个索引选项将为您提供(除了涉及 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) 使主题中的结果比正文中的结果更重要

所以,总结一下:

  • 一个组合全文索引:速度更快,但无法控制列的相对权重。如果您不需要重量,请使用它。
  • 两个全文索引:速度较慢,但​​可以控制列权重(包括如果使用不当可能会搞砸)。如果您需要重量,请使用它。

【讨论】:

  • MyISAM 和 InnoDB 关于何时使用单列与多列 FULLTEXT 索引的规则存在显着差异。
  • @RickJames 我不确定你到底是什么意思。如果您参考您的帖子here,我认为这是不正确的。 MyISAM 允许(仅)布尔模式在根本没有任何全文索引的情况下进行搜索(至少在技术上,因为对于大表来说它会变得非常缓慢),当你有一个复合全文索引和仅搜索其列的子集(反之亦然,搜索多于一个索引覆盖的列)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
相关资源
最近更新 更多