mysql对多个ors使用索引,但对in没有索引,速度慢得多

ffvjumwh  于 2021-06-20  发布在  Mysql
关注(0)|答案(4)|浏览(506)

我一直在忙着改变一些sql查询,以便它们看起来更易于人眼阅读,我还被告知它们可能会快5-10%。
前面的sql语句如下所示。
从team1='joe bloggs'或team2='joe bloggs'或team3='joe bloggs'所在的团队中选择*
我把它改成了
从“joe bloggs”所在的团队中选择*(团队1、团队2、团队3)
新的查询大约慢了10倍,在检查了可能的原因后,我发现它没有使用任何索引,即使我试图强制索引,它仍然不会使用它。
这个表有大约120000行,我无法更改表格式,因为我无法访问其他应用程序,请使用它。team1、team2、team3列都是varchar(45)
有人能解释为什么索引用于原始查询而不是新查询吗?我已经读了很多页,但是找不到答案,我读到mysql可能决定不使用索引更快,但是这里不应该这样,因为in查询几乎慢了10倍。
多个ors选择(无缓存运行1000次)-选择中经过12.863906860352次(无缓存运行1000次)-经过122.73787903786次
谢谢你抽出时间。

w9apscun

w9apscun1#

我不知道为什么性能会不同——在这两种情况下似乎都不会使用索引。
您可以这样编写查询:

SELECT t.*
FROM teams t
WHERE Team1 = 'Joe Bloggs'
UNION ALL
SELECT t.*
FROM teams t
WHERE Team2 = 'Joe Bloggs' AND Team1 <> 'Joe Bloggs' 
UNION ALL
SELECT t.*
FROM teams t
WHERE Team3 =  'Joe Bloggs'
  AND Team2 <> 'Joe Bloggs'
  AND Team1 <> 'Joe Bloggs';

这可以利用上的索引 (Team1) , (Team2, Team1) ,和 (Team3, Team2, Team1) .

syqv5f0l

syqv5f0l2#

你有一个“倒进”;优化器只会使用索引 column in (value1, value2, value3) .
但是,如果您在3列中的每一列上都有单独的索引,那么还有另一种方法可以产生比您的任何一种尝试都要好得多的性能:

SELECT * FROM teams WHERE Team1='Joe Bloggs'
UNION
SELECT * FROM teams WHERE Team2='Joe Bloggs'
UNION
SELECT * FROM teams WHERE Team3='Joe Bloggs'

该表将被查询3次,但每次都将使用索引。
如果你确定不会有任何欺骗,或你不介意欺骗,改变 UNIONUNION ALL 进一步加速( UNION 有额外的开销或重复数据消除)。

jrcvhitl

jrcvhitl3#

方案a:使用 FULLTEXT (team1, team2, team3) 以及 MATCH(team1, team2, team3) AGAINST ('+Joe +Briggs' IN BOOLEAN MODE) . 使用这种方法有很多注意事项,但是,如果它适用于您的情况,它将非常快。
方案b:尽管“不能改变表格格式”,您还是可以使用视图玩一些游戏,以避免数组(团队)在列之间展开。

zvms9eto

zvms9eto4#

在查询中:

SELECT * FROM teams WHERE 'Joe Bloggs' IN (Team1,Team2,Team3)

您正在比较(查找)一组列和一个字符串文本。在这种情况下,优化器通常会在搜索目标上使用索引 Joe Bloggs ,以在 IN 条款。但是,它不能在字符串文本上放置索引。所以,这里的一切都是颠倒的,这就是为什么指数没有帮助。
另一方面,在第一个查询中:

SELECT * FROM teams WHERE Team1='Joe Bloggs' OR Team2='Joe Bloggs' OR Team3='Joe Bloggs'

mysql将获取字符串文本,然后使用b-tree索引在不同的列中查找它们。它的行为正如你所期望的和看到的。

相关问题