Cast
4 отговора
390 прегледа
Cast
Опитвам се да направя скрипт, който проверява принадлежност на IP към мрежа със SQL заявка. Разполагам с bigint ip, network и subnet mask, НО имам проблем.
Резултатът от битово в mysql & e SIGNED bigint, а на мен ми трябва UNSIGNED bigint. От Cast няма полза. Усещам в случая общотеоретична липса, SOS?
Реално ми трябва число, което като го извадя от signed bigint и да получа онова, което би било, ако резултатът от bitwise операции беше unsigned bigint:)
Резултатът от битово в mysql & e SIGNED bigint, а на мен ми трябва UNSIGNED bigint. От Cast няма полза. Усещам в случая общотеоретична липса, SOS?
Реално ми трябва число, което като го извадя от signed bigint и да получа онова, което би било, ако резултатът от bitwise операции беше unsigned bigint:)
Re: Cast
Еми, да живее калкулатора. Търсеното число е 2147483648, приложено на данните, а не на SQL query-то, което стана много бързо. Така и трябва, защото му предстои да се изпълнява често.
Може да пробвате дали съм постигнал коректно разпознаване на IP-та на [линк]
Може да пробвате дали съм постигнал коректно разпознаване на IP-та на [линк]
Редактирано от dzver на
Re: и добре и лошо :)
Добре е, че си се преборил макар, че не си особено прав.
Първо резултатът от
x & y
винаги е BIGINT UNSIGNED
SELECT 0xffffffffffffffff & 0xffffffffffffffff;
+-----------------------------------------+
| 0xffffffffffffffff & 0xffffffffffffffff |
+-----------------------------------------+
| 18446744073709551615 |
+-----------------------------------------+
Или ако искаш така:
mysql> SELECT @x := INET_ATON('10.10.10.20') & INET_ATON('255.255.255.0') AS x;
+-----------+
| x |
+-----------+
| 168430080 |
+-----------+
1 row in set (0.00 sec)
mysql> SELECT HEX(@x), INET_NTOA(@x);
+---------+---------------+
| HEX(@x) | INET_NTOA(@x) |
+---------+---------------+
| A0A0A00 | 10.10.10.0 |
+---------+---------------+
1 row in set (0.00 sec)
Което общо взето е каквото ти трябва.
Съгласен ли си дотук?
Второто е доста по-весело.
Ако сравняваш колонка от таблица маскирането по "обичайния" начин е адски лош вариант. Просто защото
SELECT ... WHERE ip & INET_ATON('255.255.255.0') = INET_ATON('10.10.10.0');
или еквивалентното
SELECT ... WHERE ip & 0xFFFFFF00 = 0xA0A0A00;
никога ама никога няма да използваникакъв индекс.
Затова е много по-добре да постъпиш по най-хамалския начин и да проверяваш обхват от числа т.е. горното става
SELECT ... WHERE ip BETWEEN INET_ATON('10.10.10.1') AND INET_ATON('10.10.10.254');
или какъвто и да е еквивалентен вариант.
Знам, че за всеки програмист това звучи много по-дървено, но така индексите работят. А когато имащ да преравяш таблица с 2 милиона IP адреса определено ще предпочетеш да го правиш чрез индекс. нали така?

salle.online.bg/sig
Първо резултатът от
x & y
винаги е BIGINT UNSIGNED
SELECT 0xffffffffffffffff & 0xffffffffffffffff;
+-----------------------------------------+
| 0xffffffffffffffff & 0xffffffffffffffff |
+-----------------------------------------+
| 18446744073709551615 |
+-----------------------------------------+
Или ако искаш така:
mysql> SELECT @x := INET_ATON('10.10.10.20') & INET_ATON('255.255.255.0') AS x;
+-----------+
| x |
+-----------+
| 168430080 |
+-----------+
1 row in set (0.00 sec)
mysql> SELECT HEX(@x), INET_NTOA(@x);
+---------+---------------+
| HEX(@x) | INET_NTOA(@x) |
+---------+---------------+
| A0A0A00 | 10.10.10.0 |
+---------+---------------+
1 row in set (0.00 sec)
Което общо взето е каквото ти трябва.
Съгласен ли си дотук?
Второто е доста по-весело.
Ако сравняваш колонка от таблица маскирането по "обичайния" начин е адски лош вариант. Просто защото
SELECT ... WHERE ip & INET_ATON('255.255.255.0') = INET_ATON('10.10.10.0');
или еквивалентното
SELECT ... WHERE ip & 0xFFFFFF00 = 0xA0A0A00;
никога ама никога няма да използваникакъв индекс.
Затова е много по-добре да постъпиш по най-хамалския начин и да проверяваш обхват от числа т.е. горното става
SELECT ... WHERE ip BETWEEN INET_ATON('10.10.10.1') AND INET_ATON('10.10.10.254');
или какъвто и да е еквивалентен вариант.
Знам, че за всеки програмист това звучи много по-дървено, но така индексите работят. А когато имащ да преравяш таблица с 2 милиона IP адреса определено ще предпочетеш да го правиш чрез индекс. нали така?
salle.online.bg/sig
Re: и добре и лошо :)
Освен ако намерените съвпадения не са 1.9 млн...
Everything louder than everything else...
Everything louder than everything else...
Re: и добре и лошо :)
Много благодаря, тайно се надявах да намериш темата за интересна :)
Базата ми няма да се усложни от тази промяна. В момента съхранявам 2 полета - за ip и за subnet mask, вместо subnet mask трябва да сложа най-голямото ip от мрежата и да добавя индекс.
Мислих донякъде стереотипно, защото предната версия на това ми нещо беше с парсване на файл, в който мрежите са във формат
194.12.244.0/19
Сега обаче ще го изпълнявам 30 - 40000 пъти дневно и вече стана важно да е направено добре.
Още веднъж благодаря!
Базата ми няма да се усложни от тази промяна. В момента съхранявам 2 полета - за ip и за subnet mask, вместо subnet mask трябва да сложа най-голямото ip от мрежата и да добавя индекс.
Мислих донякъде стереотипно, защото предната версия на това ми нещо беше с парсване на файл, в който мрежите са във формат
194.12.244.0/19
Сега обаче ще го изпълнявам 30 - 40000 пъти дневно и вече стана важно да е направено добре.
Още веднъж благодаря!