【问题标题】:How to improve MySql query that trying to find duplicate entries in large database?如何改进试图在大型数据库中查找重复条目的 MySql 查询?
【发布时间】:2012-03-04 09:01:28
【问题描述】:

我必须对大型数据库(Snort 警报)进行查询以查找重复条目。但是,我想出了下面的查询,但是执行起来需要很多时间!

SELECT sid, cid, timestamp, sig_name, inet_ntoa(ip_src), layer4_sport,
       inet_ntoa(ip_dst), layer4_dport
  FROM DB
 WHERE (ip_dst IN
        (SELECT ip_dst FROM DB GROUP BY ip_dst HAVING count(*) > 1)
   AND timestamp IN
        (SELECT timestamp FROM DB GROUP BY timestamp HAVING count(*) > 1)
   AND layer4_dport IN
        (SELECT layer4_dport FROM DB GROUP BY layer4_dport HAVING count(*)>1 ))

上述查询试图查找具有相同timestamplayer4_dport 的警报ip_dst 如果他们来了不止一次。我希望它清楚!

任何提高效率的提示或技巧?

【问题讨论】:

    标签: mysql dataset acid snort


    【解决方案1】:

    我已经格式化了您的查询...如果我们将其分解,您似乎正在应用几个函数inet_ntoa。如果您没有迫切需要,请摆脱它们(尤其是当它们看桌子时)。

    其次,如果我们查看您的查询,您正在对 DB 进行 3 次完整扫描以获取各种计数,然后至少在您的顶级选择中进行范围扫描。

    SELECT sid, cid, timestamp, sig_name, inet_ntoa(ip_src), layer4_sport, inet_ntoa(ip_dst), layer4_dport 
      FROM DB 
     WHERE ( ip_dst IN ( SELECT ip_dst 
                           FROM DB 
                          GROUP BY ip_dst 
                         HAVING count(*) > 1 ) 
       AND timestamp IN ( SELECT timestamp 
                            FROM DB 
                           GROUP BY timestamp 
                          HAVING count(*) > 1 ) 
       AND layer4_dport IN ( SELECT layer4_dport 
                               FROM DB 
                              GROUP BY layer4_dport 
                             HAVING count(*) > 1 ) 
            ) 
    

    通过不将子查询链接回主表,您假设 ip_dsttimestamplayer4_dport 在整个表中每个都是唯一的,然后尝试查找其中不太可能出现的 3 个独立唯一值恰好在同一行中有重复。

    我怀疑你想要做的事情如下:

    SELECT a.sid, a.cid, a.ip_dst, a.timestamp, a.sig_name, a.layer4_sport, a.layer4_dport 
      FROM DB a 
      JOIN ( SELECT timestamp, layer4_dport 
               FROM DB 
              GROUP BY timestamp, layer4_dport
             HAVING count(*) > 1 ) b
        ON a.timestamp = b.timestamp
       AND a.layer4_dport = b.layer4_dport
    

    根据您的问题,这将为您找到有超过 1 个相同的 timestamplayer4_dport 组合的所有行。

    如果您想在ip_dst 级别查找所有重复项,则需要将其添加到您的子查询中。

    【讨论】:

    • 谢谢 Ben,我添加了 ip_dst 并且我将 inet_ntoa 返回到查询中,因为我想打印它的结果。但是,总是我得到错误 字段列表中的列'时间戳'不明确并且查询如下: SELECT sid, cid, timestamp, sig_name, inet_ntoa(ip_src), layer4_sport, inet_ntoa(ip_dst), layer4_dport FROM DB a JOIN ( SELECT timestamp, layer4_dport, ip_dst FROM DB GROUP BY timestamp, layer4_dport, ip_dst HAVING count(*) > 1 ) b ON a.timestamp = b.timestamp AND a.layer4_dport = b.layer4_dport AND a.ip_dst = b.ip_dst -Aymen
    • 现在工作正常。我刚刚在 select 语句上添加了 a.timestamp 如下:SELECT sid, cid, a.timestamp, sig_name, inet_ntoa(ip_src), layer4_sport, inet_ntoa(a.ip_dst), a.layer4_dport FROM DB a .... 谢谢很多本,-艾门
    • 啊,是的,对不起@user1247874,我没有明确引用选择变量来自哪个表。我已经更新了答案。
    【解决方案2】:

    下面的链接可以帮助你。

    Find duplicate records in MySQL

    希望这篇文章可以帮助您优化查询。

    【讨论】:

    • 非常感谢。我的查询与帖子上发布的想法或多或少相似。查询工作正常,但我正在寻找一种更好的方法来提高效率。
    • @user1247874:实际上不是。正如您从 Ben 上面给出的帖子中看到的那样,您的查询与我给您的链接中提出的想法相去甚远。检查上面给出的答案,然后检查 Powerlord 链接中给出的答案。通过遵循这些,您应该越来越接近您的需求。
    • 谢谢。非常感谢您的兴趣。艾门
    猜你喜欢
    • 1970-01-01
    • 2010-09-30
    • 2015-11-01
    • 2016-12-27
    • 2022-01-12
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多