首页 文章

MySQL使用索引进行多个OR,但IN没有索引,速度慢得多

提问于
浏览
3

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

以前的SQL语句看起来像这样 .

SELECT * FROM团队WHERE Team1 ='Joe Bloggs'或Team2 ='Joe Bloggs'或Team3 ='Joe Bloggs'

我改成了

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

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

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

任何人都可以解释为什么索引用于原始查询而不是新查询?我已经阅读了大量的页面,但找不到答案,我已经读过可能的mysql确定它更快不使用索引,但不一定是这种情况,因为IN查询几乎慢了10倍 .

多个ORs SELECT(没有缓存运行1000次) - 12.863906860352经过IN SELECT(没有缓存运行1000次) - 122.73787903786已过去

感谢您的时间 .

4 回答

  • 0

    在查询中:

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

    你正在比较(查找)一串列与字符串文字 . 优化器通常会使用搜索目标上的索引(在本例中为 Joe Bloggs )来查找 IN 子句中的值 . 但是,它可以帮助.742728_ t .

    另一方面,在您的第一个查询中:

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

    MySQL将获取字符串文字,然后使用B树索引查找各种列 . 这表现得像你期望的那样 .

  • 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 有额外的开销或重复数据删除) .

  • 4

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

    计划B:尽管“无法更改表格格式”,您可以使用VIEW播放一些游戏,以避免跨列扩展阵列(团队) .

  • 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) 上的索引 .

相关问题