我有一个翻译表(MySQL MyISAM)用于单词(现在为空,但插入单词后会变得很大)。
只有两种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'
通常情况下,这些字段会包含单独的索引:
但是,我刚刚读到另一个thread中的组合索引,但我仍然对如何使用它们有一些疑问。
我应该只有3个索引吗?
这些组合索引应该是UNIQUE还是INDEX类型?为什么呢?
我是否还需要为lang_original,lang_target和word设置单独的索引,尽管它们不会被自己过滤掉?
更新1 fixed =而不是LIKE
答案 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_original
和lang_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 *的查询都可以使用该单个索引。