使用OR运算符时正确索引

Jam*_*s T 8 mysql indexing where-clause

我有这样的查询:

SELECT fields FROM table
WHERE field1='something' OR field2='something' 
OR field3='something' OR field4='something'
Run Code Online (Sandbox Code Playgroud)

为此查询索引此类表的正确方法是什么?

像这样的查询需要一整秒才能运行!我有1个索引,其中包含所有4个字段,所以我认为mysql会做这样的事情:

浏览索引中的每一行,想一想:field1是什么?field2怎么样?字段3?字段4?好的,不,转到下一行.

Bil*_*win 17

你误解了索引的工作原理.

想想一本电话簿(相当于姓氏的两列索引,名字最后一个).如果我要求你找到姓氏为"史密斯"的电话簿中的所有人,你可以从这样的事实中获益:你可以假设史密斯是一起组织的.但是,如果我要求你找到名字为"John"的所有人,你就无法从索引中获益.约翰斯可以有任何姓氏,所以他们分散在整本书中,你最终不得不从头到尾搜索.

现在,如果我要求你找到姓氏为"史密斯"的所有人,或者名字叫"约翰"的人,你可以像以前一样轻松找到史密斯,但这根本无助于你找到约翰斯.它们仍然散布在整本书中,你必须以艰难的方式搜索它们.

SQL中的多列索引也是如此.索引按第一列排序,然后在第一列中绑定的情况下按第二列排序,然后在前两列中的绑定情况下按第三列排序,等等.它不按所有列排序同时.因此,除索引中最左侧的列外,您的多列索引无法使搜索项更有效.

回到原来的问题.

为此查询索引此类表的正确方法是什么?

在每列上创建单独的单列索引.根据MySQL 估计索引在使用时会产生多少I/O操作,这些索引中的一个将是比其他索引更好的选择.

现代版本的MySQL也有一些关于索引合并的智能,因此查询可能在给定的表中使用多个索引,然后尝试合并结果.否则,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' 
Run Code Online (Sandbox Code Playgroud)

最后一个观察结果:如果你发现自己'something'在四个领域中搜索同样的东西,你应该重新考虑所有四个领域是否真的是同一个东西,并且你犯了设计一个违反First Normal形式且重复组的表的罪名.如果是这样,则field1到field4可能属于子表中的单个列.然后索引和查询变得容易得多:

SELECT fields from table INNER JOIN child_table ON table.pk = child_table.fk
WHERE child_table.field = 'something'
Run Code Online (Sandbox Code Playgroud)