MySQL在'WHERE'子句中与多个范围连接

时间:2011-05-06 11:13:09

标签: mysql join where-clause

我正在尝试使用snort的架构并提取与我的程序相关的信息。 我使用以下查询来提取针对给定IP集合在指定时间段内发生的警报。查询类似于

select event.sid,event.cid,event.signature,event.timestamp,iphdr.ip_proto,iphdr.ip_src,iphdr.ip_dst from 
event join iphdr 
where event.sid=iphdr.sid and event.cid=iphdr.cid and iphdr.ip_dst >= inet_aton('x.x.x.1') and iphdr.ip_dst <= inet_aton('x.x.x.255') 
or iphdr.ip_dst >= inet_aton('x.x.y.1') and iphdr.ip_dst <= inet_aton('x.x.y.255') 
and event.timestamp > "2011-05-06 00:00:00" order by timestamp 

我需要获取两组IP(x.x.x.0 / 24和x.x.y.0 / 24)后指定时间(2011年5月6日)之后发生的警报

只对一组IP(例如192.168.1.0/24)(即在192.168.1.1和192.168.1.255之间)执行查询是快速而简单的

如果WHERE子句中有多个范围,则会出现问题。例如。 IP在192.168.1.1和192.168.1.255之间或在10.21.18.1和10.21.18.255之间。如上面的查询中所述

在这种情况下,执行mysql查询需要很长时间才能执行(我运行了30分钟然后不得不杀死MySQL守护进程)

我确信导致问题的是OR部分,但不知道如何纠正它。

事件和iphdr表都有大约。所有

中的150,000行

因为在我的程序中,用户可以指定他想要查看警报的多个子网,所以我需要查询无缝运行,而不管WHERE子句中的范围数量。

2 个答案:

答案 0 :(得分:1)

您在WHERE中的OR会破坏您的加入。尝试从OR周围的地方或至少使用括号进行连接,例如:

select event.sid,event.cid,event.signature,event.timestamp,
iphdr.ip_proto,iphdr.ip_src,iphdr.ip_dst 
from event join iphdr on (event.sid=iphdr.sid and event.cid=iphdr.cid)
where iphdr.ip_dst >= inet_aton('x.x.x.1') 
and (
iphdr.ip_dst <= inet_aton('x.x.x.255') 
or iphdr.ip_dst >= inet_aton('x.x.y.1') 
)
and iphdr.ip_dst <= inet_aton('x.x.y.255') 
and event.timestamp > "2011-05-06 00:00:00" 
order by timestamp 

答案 1 :(得分:1)

SQL中,AND的优先级高于OR

您的过滤器实际上是这样的:

(
event.sid=iphdr.sid and event.cid=iphdr.cid and iphdr.ip_dst >= inet_aton('x.x.x.1') and iphdr.ip_dst <= inet_aton('x.x.x.255')
)
or
(
iphdr.ip_dst >= inet_aton('x.x.y.1') and iphdr.ip_dst <= inet_aton('x.x.y.255') and event.timestamp > "2011-05-06 00:00:00"
)

第二个条件打破了iphdrevent之间的相关性,导致其子集的笛卡尔连接。

OR子句放入括号:

event.sid=iphdr.sid
AND event.cid=iphdr.cid
AND
(
iphdr.ip_dst BETWEEN inet_aton('x.x.x.1') AND inet_aton('x.x.x.255')
OR
iphdr.ip_dst BETWEEN inet_aton('x.x.y.1') AND inet_aton('x.x.y.255')
)
AND event.timestamp > "2011-05-06 00:00:00"

您可能还想创建这些索引:

iphdr (ip_dst)
event (timestamp)