Там путь состоит в том, чтобы соответствовать IP IP+CIDR прямо от Запроса Select?

library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))
19
задан raspi 27 February 2009 в 17:28
поделиться

3 ответа

Помните, что дюйм/с не является текстовым адресом, а числовым идентификатором. У меня есть аналогичная ситуация (мы делаем геоIP поиски), и если Вы храните все свои IP-адреса как целые числа (например, мой IP-адрес 192.115.22.33, таким образом, он хранится как 3228767777), тогда Вы можете дюйм/с поиска легко при помощи операторов сдвига вправо.

оборотная сторона всех этих типов поисков - то, что Вы не можете извлечь выгоду из индексов, и необходимо сделать полное сканирование таблицы каждый раз, когда Вы делаете поиск. Вышеупомянутая схема может быть улучшена путем хранения обоих сетевой IP-адрес сети CIDR (начало диапазона) и широковещательный адрес (конец диапазона), так например, для хранения 192.168.1.0/24, можно сохранить два столбца:

network     broadcast
3232235776, 3232236031 

И затем Вы можете для соответствия ему, Вы просто делаете

SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast

, Это позволило бы Вам сохранить сети CIDR в базе данных и соответствовать им против IP-адресов быстро и эффективно путем использования в своих интересах быстрых числовых индексов.

Примечание из обсуждения ниже :

MySQL 5.0 включает расположенную оптимизацию запросов, названную" , индексное слияние пересекается ", который позволяет ускорять такие запросы (и избегать полных сканирований таблицы), пока:

  • существует многостолбцовый индекс, который соответствует точно столбцам в запросе в порядке. Таким образом - для вышеупомянутого примера запроса, индекс должен был бы быть (network, broadcast).
  • Все данные могут быть получены от индекса. Это верно для COUNT(*), но не верно для SELECT * ... LIMIT 1.

MySQL 5.6 включает оптимизацию под названием MRR, который также ускорил бы полное извлечение строки, но это вне объема этого ответа.

25
ответ дан 30 November 2019 в 00:35
поделиться

Hmmm. Вы могли создать таблицу cidr масок, присоединиться к ней и затем выдержать сравнение, IP внес (& в MySQL) с маской с блоком запрета ipaddress. Это сделало бы то, что Вы хотите?

, Если Вы не хотите создавать таблицу маски, Вы могли бы вычислить маску как -1 << (x-cidr) с x = 64 или 32 зависящий.

0
ответ дан 30 November 2019 в 00:35
поделиться

Для IPv4, можно использовать:

SET @length = 4;

SELECT  INET_NTOA(ipaddr), INET_NTOA(searchaddr), INET_NTOA(mask)
FROM  (
  SELECT
        (1 << (@length * 8)) - 1 & ~((1 << (@length * 8 - cidr)) - 1) AS mask,
        CAST(CONV(SUBSTR(HEX(ipaddr), 1, @length * 2), 16, 10) AS DECIMAL(20)) AS ipaddr,
        CAST(CONV(SUBSTR(HEX(@myaddr), 1, @length * 2), 16, 10) AS DECIMAL(20)) AS searchaddr
  FROM  ip
) ipo
WHERE ipaddr & mask = searchaddr & mask
2
ответ дан 30 November 2019 в 00:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: