MySQL查询返回无效行,速度非常慢

MySQL查询返回无效行,速度非常慢,mysql,sql,performance,Mysql,Sql,Performance,我正在编写一个查询,从另一个表中选择player bans,但首先非常慢,大约需要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

我正在编写一个查询,从另一个表中选择player bans,但首先非常慢,大约需要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"
还有几个屏幕截图来说明我的意思:

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

我还担心在历史记录表中,streamid和ip列会有重复的条目,这可能会使查询速度变慢。有没有办法使查询仅根据trackingid选择具有唯一ip或streamid的行

任何帮助都将不胜感激

谢谢


编辑:由于@maraca、@Skorpioh和@Adam Silenko的帮助,我被淹没了,查询时间现在不到一秒钟

查询返回的行不是
NULL
,因为它被解释为
(…和…和…)或…
,而不是
。。。而且。。。和(…或…)

因此,您需要添加大括号,也不需要使用
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"))

和的优先级高于或。。。 你需要在你的表上建立索引 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) )

这里有一个operatior Prevendence问题,这就是为什么它最终会产生removetype/removedon不为null的结果

如果您选中该选项,您将看到它的优先级高于或意味着您的查询将运行所有用“AND”运算符粘在一起的谓词,并且仅在之后执行或意味着您将看到结果,其中authorid是匹配的,其余的不再重要

如果我没有错,下面的代码应该可以正常工作:

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列创建覆盖索引。这将有所帮助,但可能还不够,因为类似的操作非常昂贵

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

原因与“%[FragSleuth]重复帐户%不同”


变成别的东西。例如,您是否可以消除前导的%以便它至少可以进行更快的匹配?当然,这取决于这些列存储的具体内容。

而且您可能需要在
ip
之前使用
),最后使用
。谢谢,这就解决了问题!但是现在有没有办法让查询更快?@SM9不客气。您可以分析查询并为重要列编制索引。或者如果你做不到这一点,你可以试着在where中重新排序条件,这有时会有帮助。@SM9。您可以问另一个有关加快查询速度的问题。原因是这样附加的:\“[FragSleuth]重复帐户(名称:%s)(AuthId:%s)(原因:%s)\”,因此我不确定是否有更好的方法。如果要筛选的原因总是以“[FragSleuth]重复帐户”开头,那么您可以通过将其更改为”来改善这一点原因与“[FragSleuth]Duplicate account%”不同(请注意,前导的%已被删除)。这将大大加快类似操作的速度。啊,好的,我会这样做,编辑:哇,我这样做了,我也做了@Adam Silenko说的,查询时间减少了7秒到0.0397秒,非常感谢:)嗨,你能解释一下在trackingid上添加索引会做什么吗?谢谢如果表历史记录很大(可能是的话)并且您在子查询中有列trackingid的条件,此字段上的索引可以改进此子查询的行搜索