Postgres使用连接汇总netflow数据

时间:2012-09-14 00:03:21

标签: mysql postgresql

我运行pmacct,每小时将网络流量汇总到postgres数据库中。 我需要编写一个脚本/查询来将不同格式的数据移动到mysql数据库中。我希望使用SQL尽可能多地进行数据处理,因为这个数据集会快速增长。

我运行了一个perl脚本来添加一个额外的字段(agent_id)来跟踪数据所在的区域(本地/国家/国际),它将显示为0,1或2。

表格架构的相关字段我将这些数据拉出来:

ip_src, ip_dst, agent_id, bytes, stamp_updated, processed

我想要插入数据的架构是:

ip, local_down_mb, nat_down_mb, int_down_mb, local_up_mb, nat_up_mb, int_up_mb, timestamp

由于我只是在寻找源或目标是我的范围之一的流量,我现在有一个查询,它以我想要的方式从postgres数据库中获取上传数据:

SELECT DISTINCT ip_src, agent_id, SUM(bytes), stamp_updated FROM acct
WHERE ip_src <<= '192.168.0.0/22'
   OR ip_src <<= '10.1.2.0/24'
   OR ip_src <<= '1.2.3.4/32'
GROUP BY ip_src, agent_id, stamp_updated
ORDER BY ip_src, agent_id, stamp_updated

该查询的示例输出是:

   ip_src     | agent_id |    sum    |    stamp_updated    
--------------+----------+-----------+---------------------
10.1.2.134    |        2 |      3192 | 2012-09-13 21:20:01
10.1.2.134    |        2 |      3192 | 2012-09-13 22:20:01
10.1.2.134    |        2 |      3192 | 2012-09-13 23:20:01
10.2.3.252    |        2 |       448 | 2012-09-11 06:00:01
10.2.3.252    |        2 |       448 | 2012-09-11 07:20:01
10.2.3.252    |        2 |       448 | 2012-09-11 08:20:01
10.2.3.252    |        2 |      8112 | 2012-09-11 09:20:01

在这个阶段,我知道我可以为ip_dst运行相同的查询,然后在以新格式将数据重新插入mysql时有一些手动过程,以确保ip源和目标匹配时间戳,然后使用agent_id的组合以及是否是我插入的ip源或ip目的地,以了解它是入站还是出站,以及流量是本地的,国内的还是国际的。

然而,我想要的是一个查询,它将为我做所有这些。几个月前,我的SQL知识的限制已经通过了W3C网站教程,这让我能够像上面那样编写一个查询,但不会更进一步。

据我所知,我需要帮助的是在两组结果之间编写连接,一组用于ip_src,另一组用于ip_dst,然后做一些魔术来使用流量传输方向的信息。与agent_id结合使用,使其输出与mysql数据库的模式匹配。

是否有人可以(非常友好地)撰写他们认为可能有助于实现此目的的查询,或者至少指向相关文档,并让我先于我可能需要使用哪些功能来完成这项工作?

1 个答案:

答案 0 :(得分:3)

  • 要解决您如何将ip_src粘贴到ip_dst搜索的主要问题,您希望对已经处理IP仅在一个方向上具有流量的情况的两个查询使用FULL OUTER JOIN给定时间戳。如果您的数据加载器可以保证匹配数据,那么您可以放弃INNER JOIN,但为什么要冒险呢?
  • 由于您希望将agent_id转移到目标模式中的3个单独的列中,因此我在聚合函数中显示了一种条件。
  • 我假设在最终输出中根据列名将字节数转换为向上舍入的兆字节。

      SELECT down.ip,
             ceil(down.lb/1048576) AS local_down_mb,
             ceil(down.nb/1048576) AS nat_down_mb,
             ceil(down.ib/1048576) AS int_down_mb,
             ceil(up.lb/1048576) AS local_up_mb,
             ceil(up.nb/1048576) AS nat_up_mb,
             ceil(up.ib/1048576) AS int_up_mb,
             down.timestamp
        FROM (SELECT ip_src AS ip,
                     SUM(CASE WHEN agent_id=0 THEN bytes ELSE 0 END) AS lb,
                     SUM(CASE WHEN agent_id=1 THEN bytes ELSE 0 END) AS nb,
                     SUM(CASE WHEN agent_id=2 THEN bytes ELSE 0 END) AS ib,
                     stamp_updated AS timestamp
                FROM acct
               WHERE ip_src <<= '192.168.0.0/22'
                  OR ip_src <<= '10.1.2.0/24'
                  OR ip_src <<= '1.2.3.4/32'
            GROUP BY ip,timestamp) down
        FULL OUTER JOIN
             (SELECT ip_dst AS ip,
                     SUM(CASE WHEN agent_id=0 THEN bytes ELSE 0 END) AS lb,
                     SUM(CASE WHEN agent_id=1 THEN bytes ELSE 0 END) AS nb,
                     SUM(CASE WHEN agent_id=2 THEN bytes ELSE 0 END) AS ib,
                     stamp_updated AS timestamp
                FROM acct
               WHERE ip_dst <<= '192.168.0.0/22'
                  OR ip_dst <<= '10.1.2.0/24'
                  OR ip_dst <<= '1.2.3.4/32'
            GROUP BY ip,timestamp) up
       USING (ip,timestamp)
    ORDER BY ip,timestamp;