在MySQL中使用组合索引

时间:2011-12-06 21:17:54

标签: mysql sql optimization indexing query-optimization

我有一个翻译表(MySQL MyISAM)用于单词(现在为空,但插入单词后会变得很大)。

  • id_word
  • lang_original(原始单词中的语言) VARCHAR(2)
  • lang_target(翻译后的字词) VARCHAR(2)
  • 字(单词本身) VARCHAR(50)
  • 翻译(翻译) VARCHAR(50)

只有两种SELECT可以在该表上请求信息:

通过定义原始语言

SELECT translation FROM table WHERE lang_original='en' AND lang_target='de' AND word = 'house'
//this will return 'Haus'

让脚本自动检测原始语言

SELECT lang_original,translation FROM table WHERE lang_target='de' AND word = 'house'
//this will return 'en','Haus'

通常情况下,这些字段会包含单独的索引:

  • id_word
  • lang_original
  • lang_target

但是,我刚刚读到另一个thread中的组合索引,但我仍然对如何使用它们有一些疑问。

  1. 我应该只有3个索引吗?

    • id_word(主要/自动增量)
    • 合并:lang_target + word
    • 合并:lang_original + lang_target + word
  2. 这些组合索引应该是UNIQUE还是INDEX类型?为什么呢?

  3. 我是否还需要为lang_original,lang_target和word设置单独的索引,尽管它们不会被自己过滤掉?

  4. 更新1 fixed =而不是LIKE

2 个答案:

答案 0 :(得分:5)

正如我上面提到的,使用EXPLAIN将显示如何执行查询以及使用哪些索引或

  

1)我应该只有3个索引吗?

     
      
  • id_word(主要/自动增量)
  •   
  • 合并:lang_target + word
  •   
  • 合并:lang_original + lang_target + word
  •   

拥有那些复合索引会起作用。两个复合索引之间有很多重叠,所以也许你可以找到一种方法将它们组合起来:

(lang_target, word(10), lang_original)

我建议为word列使用合理的前缀大小,这样它们就是一个设定长度(例如10)。绝大多数单词在前10个字符中是不同的,因此它必须从磁盘读取的情况因为它们通过10个字符相同才是罕见的。前缀长度是索引大小和执行速度之间的平衡。较大的前缀将遇到较少的前缀冲突,但它将是一个更耗费内存的索引。另一方面,较小的前缀将节省内存但可能导致更多的前缀冲突(因此必须转到磁盘以在几个记录之间进行最终确定)。玩适合你的东西。也许它是5,也许是15。

  

这些组合索引应该是UNIQUE还是INDEX类型?为什么呢?

如果(lang_target, word, lang_original)将是一个独特的组合(似乎就是这种情况),请继续使用UNIQUE约束,但前提是您不要砍{{1}带有前缀(在这种情况下,可能存在具有相同部分word值的多个记录)。作为一个指标,我认为它们在功能上仍然相同。

  

我是否还需要为lang_original,lang_target和word设置单独的索引,尽管它们不会被自己过滤掉?

复合索引中的列从左到右使用。在word中,如果您仅查询(lang_target, word(10), lang_original)上的条件,则可以使用该索引,但如果您在lang_target上有条件,则除非您使用该条件,否则无法使用该条件还要查询lang_originallang_target。因此,如果您需要在没有 word条件的情况下查询,则只为word和/或lang_original创建其他索引。有关详细说明,请参阅this doc page on multiple column indexes

另一个想法: 如果您的lang_target列始终只有两个字符,请将其设为lang_而不是CHAR。对于大小的列,VARCHAR为每个值指定一个额外的字节来指定数据长度,而VARCHAR是一个固定的长度。凭借数百万条记录,每个字节对于大小和速度都很重要。

答案 1 :(得分:1)

正如有人指出的那样,除非你需要,否则不要使用LIKE。

另外,不要使用UNIQUE,除非组合确实是唯一的,看起来每个单词只能有一个翻译,所以UNIQUE on(lang_target,word)应该是okey但我觉得非唯一索引的性能更好,认为他们不需要独特的检查。

这两个查询只需要一个索引。不要添加超出需要的索引,每个索引在插入和更新时都会带来很小的成本。

(lang_target,word,lang_original)。顺序在这里很重要,因为MySQL可以使用索引的任何左侧部分,因此对* lang_target *,* lang_target + word *或* lang_target + word + lang_original *的查询都可以使用该单个索引。