4

我一直在忙于更改一些 SQL 查询,以便它们看起来对人眼更具可读性,我还被告知它们可能会快 5-10%。

前面的 SQL 语句看起来像这样。

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

我把它改成

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

新查询慢了大约 10 倍,在检查了可能是什么原因后,我发现它没有使用任何索引,即使我尝试强制使用索引,它仍然不会使用它。

该表大约有 120,000 行,我无法更改表格式,因为我无权访问的其他应用程序使用它。Team1、Team2、Team3 列都是 VARCHAR(45)

谁能解释为什么索引用于原始查询而不是新查询?我已经阅读了大量页面,但找不到答案,我已经读到 mysql 可能确定不使用索引的速度更快,但是这里不应该是这种情况,因为 IN 查询几乎慢了 10 倍。

多个 OR SELECT(在没有缓存的情况下运行 1000 次)-经过 12.863906860352 IN SELECT(在没有缓存的情况下运行 1000 次)-经过 122.73787903786

感谢您的时间。

4

4 回答 4

5

在查询中:

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 索引在各个列中查找它们。这表现如您所期望和正在看到的。

于 2018-07-26T14:12:58.660 回答
0

我不知道为什么性能会有所不同——在这两种情况下似乎都不会使用索引。

您可以这样编写查询:

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)

于 2018-07-26T14:15:33.560 回答
0

你有一个“倒置的IN”;优化器只会使用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 次,但每次都会使用一个索引。

如果您确定不会有任何欺骗,或者您不介意欺骗,请改为UNION进一步UNION ALL加快速度(UNION有额外的开销或重复数据删除)。

于 2018-07-26T14:18:30.817 回答
0

计划 A:使用FULLTEXT (team1, team2, team3)MATCH(team1, team2, team3) AGAINST ('+Joe +Briggs' IN BOOLEAN MODE)。使用这种方法有很多注意事项,但是,如果它适用于您的情况,它会非常快。

计划 B:尽管“无法更改表格格式”,但您可以使用 VIEW 玩一些游戏,以避免跨列展开数组(团队)。

于 2018-08-17T05:41:23.083 回答