我运行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数据库的模式匹配。
是否有人可以(非常友好地)撰写他们认为可能有助于实现此目的的查询,或者至少指向相关文档,并让我先于我可能需要使用哪些功能来完成这项工作?
答案 0 :(得分: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;