我有这样的查询:
SELECT fields FROM table
WHERE field1='something' OR field2='something'
OR field3='something' OR field4='something'
为此查询索引此类表的正确方法是什么?
像这样的查询需要一整秒才能运行!我有1个索引,其中包含所有4个字段,所以我认为mysql会做这样的事情:
浏览索引中的每一行,想一想: field1是什么? field2怎么样?字段3?字段4?好吧,不,转到下一行。
答案 0 :(得分:15)
您误解了索引的工作原理。
想一下电话簿(相当于姓氏的两列索引,名字最后一个)。如果我要求您在电话簿中找到姓氏为“史密斯”的所有人,您可以从这样的事实中获益:你可以假设史密斯是一起组织的。但是,如果我要求你找到名字为“John”的所有人,你就无法从索引中获益。约翰斯可以有任何姓氏,所以他们分散在整本书中,你最终不得不从头到尾搜索。
现在,如果我要求你找到姓氏为“史密斯”的所有人,或者他们的名字是“约翰”,你可以像以前一样轻松找到史密斯,但这对你来说找不到约翰斯。它们仍然散布在整本书中,你必须以艰难的方式搜索它们。
SQL中的多列索引也是如此。索引按第一列排序,然后在第一列中绑定的情况下按第二列排序,然后在前两列中的绑定情况下按第三列排序,等等。它不按所有列排序同时。因此,除了索引中最左侧的列之外,您的多列索引无助于提高搜索条件的效率。
回到原来的问题。
为此查询索引此类表的正确方法是什么?
在每列上创建单独的单列索引。其中一个索引将是一个比其他索引更好的选择,基于MySQL estimation of how many I/O operations,如果使用该索引将会产生索引。
MySQL的现代版本也有一些关于index merging的智能,因此查询可能在给定的表中使用多个索引,然后尝试合并结果。否则,MySQL往往限于在给定查询中为每个表使用一个索引。
许多人成功使用的另一个技巧是为每个索引列(应使用相应的索引)执行单独查询,然后UNION
结果。
SELECT fields FROM table WHERE field1='something'
UNION
SELECT fields FROM table WHERE field2='something'
UNION
SELECT fields FROM table WHERE field3='something'
UNION
SELECT fields FROM table WHERE field4='something'
最后一个观察结果:如果您发现自己在四个字段中搜索相同的'something'
,那么您应该重新考虑所有四个字段是否实际上是同一个字段,并且您对设计{{3}的表感到内疚}}。如果是这样,则field1到field4可能属于子表中的单个列。然后索引和查询变得容易得多:
SELECT fields from table INNER JOIN child_table ON table.pk = child_table.fk
WHERE child_table.field = 'something'
答案 1 :(得分:0)
除了之前的评论: 如果优化器认为这是个好主意,一些像Mysql / PostgreSql这样的RDMS可以使用索引合并。 因此,您可以为每个字段创建不同的索引,或创建一些复合索引,如field1,field2和field3,field4。最后,您应该尝试几种不同的解决方案,并选择最佳的解释计划。