MySQL Query返回无效行并且非常慢

时间:2016-03-20 23:29:11

标签: mysql sql performance

我正在编写一个查询来从另一个表中选择玩家禁令,但首先是非常缓慢的大约需要7-14秒,其次是它返回的无效行。

第一个查询如下:

SELECT *
FROM   sourcebans.sb_bans  
WHERE  removetype IS NULL
       AND removedon IS NULL
       AND reason NOT LIKE '%[FragSleuth] Duplicate account%'
       AND ip IN(SELECT DISTINCT ip
                 FROM   fragsleuth.history
                 WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9")
       OR authid IN(SELECT DISTINCT steamid
                    FROM   fragsleuth.history
                    WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9") 

第二个查询如下

SELECT * FROM `history` WHERE trackingid = "ad000c3803b48190aabf382e01b957c9"

还有一些屏幕截图显示我的意思: First Query Second Query

在屏幕截图1中,当我要求查询仅返回带有NULL的行时,您可以看到它返回了一行,其中removedon和removetype不为null。

我也担心在历史表中会有重复的steamid和ip列条目可能会使查询变慢,有没有办法让查询只选择具有唯一ip或steamid的行基于trackingid?

非常感谢任何帮助。

由于

编辑:我被帮助淹没了,感谢@maraca,@ Skorpioh和@Adam Silenko,查询时间现在不到一秒!

3 个答案:

答案 0 :(得分:2)

并且具有更高的优先级或者...... 您需要索引表 NP。如果你没有

,请在fragsleuth.history中为trackingid字段添加索引

你可以使用一个子查询做得更快,但我不确定。

SELECT *
FROM   sourcebans.sb_bans  
WHERE  removetype IS NULL
AND removedon IS NULL
AND reason NOT LIKE '%[FragSleuth] Duplicate account%'
AND exists (
  SELECT 1 from fragsleuth.history
  WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9"
  and (ip = sourcebans.ip or steamid = sourcebans.authid) )

答案 1 :(得分:1)

查询返回的行不是NULL,因为它被解释为
(... AND ... AND ... ) OR ...而不是... AND ... AND ( ... OR ...)

所以你需要添加一个大括号,而且不需要DISTINCT

SELECT *
FROM   sourcebans.sb_bans  
WHERE  removetype IS NULL
       AND removedon IS NULL
       AND reason NOT LIKE '%[FragSleuth] Duplicate account%'
       AND (ip IN(SELECT ip
                 FROM   fragsleuth.history
                 WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9")
       OR authid IN(SELECT steamid
                    FROM   fragsleuth.history
                    WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9"))

答案 2 :(得分:1)

这里有一个操作员优先级问题,这就是为什么它最终会导致removetype / removedon不为空的结果。

如果您检查http://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html,您会发现AND的优先级高于OR,这意味着您的查询将运行所有谓词与" AND"操作员,之后才进行OR意味着您将看到作者匹配的结果,其余的不再重要。

如果我没错,下面的内容应该正常:

SELECT *
FROM   sourcebans.sb_bans  
WHERE  removetype IS NULL
       AND removedon IS NULL
       AND reason NOT LIKE '%[FragSleuth] Duplicate account%'
       AND
           (
                ip IN (SELECT DISTINCT ip
                       FROM   fragsleuth.history
                       WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9")
                OR
                authid IN(SELECT DISTINCT steamid
                          FROM   fragsleuth.history
                          WHERE  trackingid = "ad000c3803b48190aabf382e01b957c9")
           )

关于速度改进,您应该首先为removetype,removedon,ip和authid列创建覆盖索引。这将有所帮助,但由于LIKE操作非常昂贵,可能还不够。

你应该做的最后一件事是检查你是否可以改变

  

理由不喜欢'%[FragSleuth]重复帐户%'

进入别的东西。例如,你可以消除领先的%,这样它至少可以做得更快吗?当然取决于这些列存储的内容。