MySQL объединяется с несколькими диапазонами в предложении WHERE - PullRequest
0 голосов
/ 06 мая 2011

Я пытаюсь использовать схему 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 

Где мне нужно получить предупреждения, которые появляются после указанного времени(06 мая 2011 г.) для двух наборов IP-адресов (xxx0 / 24 и xxy0 / 24)

Выполнение запроса для ТОЛЬКО ОДНОГО набора 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)

Яконечно, это часть ИЛИ, которая вызывает проблему, но не знаю, как ее исправить.

Таблицы event и iphdr имеют ок.Всего 150 000 строк

Поскольку в моей программе пользователь может указать несколько подсетей, для которых он хочет видеть предупреждения, мне нужно, чтобы запрос выполнялся безотказно, независимо от количества диапазонов в предложении WHERE.

Ответы [ 2 ]

1 голос
/ 06 мая 2011

В 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"
)

Второе условие нарушает корреляцию между iphdrи event, что приводит к декартовому объединению их подмножеств.

Поместите предложение 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)
1 голос
/ 06 мая 2011

Ваше ИЛИ в ГДЕ разрушает ваше объединение. Попытайтесь получить соединение из где или, по крайней мере, используйте скобки вокруг ИЛИ, например ::100100

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 
...