Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 1267 • Страница 48 из 64<  1 ... 45  46  47  48  49  50  51 ... 64  >
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 07.01.2010
видимо, эти пробелы уже внутри $from есть, где-то внутри <a></a>



Партнер
 

Member
Статус: Не в сети
Регистрация: 30.03.2009
Откуда: Екатеринбург
у меня такая проблема:
компонент сайта (банлист сервера) не показывает русский язык.
изначальнов базе кодирвока была utf8 я перекодировал в cl1251 но проблема осталась, как это решить?)


 

Member
Статус: Не в сети
Регистрация: 28.03.2004
Откуда: Surgut
Попробуй в компоненте перед запросами прописать setlocale(LC_CTYPE, "ru_RU.CP1251"); Ну или аналогичную.

_________________
:: Overclock your mind !!! ::


 

Member
Статус: Не в сети
Регистрация: 23.12.2004
Откуда: Беларусь, Минск
Код:
/* dropdownmenu.js, Copyright (C) 2007 - 2010 YOOtheme GmbH */

eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('8 17=f 1x({1w:4(5,9){1.1v({P:\'1y\',Z:\'1h\',V:\'1z\',1C:1u,X:1A,q:\'m\',1D:u.1s.1o,1n:Y},9);8 a=1;1.d=$(5);1.D=1t;1.E=[];1.m=[];i(!1.d)1p;1.d.U({S:4(n){a.m=[];a.B(10)},T:4(n){a.m.g(4(2){2.1r(a.9.q)});a.B(a.9.X)}});1.d.C(1.9.Z).g(4(2){8 7=2.1l(1.9.V);i(7){1.E.18(2);i(1.9.P==\'1P\'){1.15(2,7)}19{1.16(2,7)}2.U({S:4(n){2.O=1Q;a.m=[];i(!2.1i(a.9.q)&&!13.1E){2.F(\'j.7\')}},T:4(n){2.O=Y;i(a.d!=n.11&&!a.d.1T(n.11)){a.m.18(2)}19{2.F(\'1d\')}}})}}.1g(1))},16:4(2,7){8 h=7.1b(\'b\',\'6\',\'H\');8 v={\'b\':0,\'6\':0};8 e=f R(\'e\').W(7.Q()).14(7).L(\'b\',h.b.c());8 j=f u.I(7,1.9);1G(1.9.P){12\'b\':v={\'b\':0};1a;12\'6\':v={\'6\':0};1a}2.1e(\'j.7\',4(){j.K();j.5.r($1I(v,13.1J?{\'N\':\'J\'}:{\'H\':0,\'N\':\'J\'}));j.G(h).1j(4(){j.5.r(h)})})},15:4(2,7){8 h=7.1b(\'b\',\'6\',\'H\');8 e=f R(\'e\').W(7.Q()).14(7);8 s=f u.I(7,1.9);8 w=f u.I(e,1.9);2.1e(\'j.7\',4(){s.K();s.5.r({\'6\':0,\'N\':\'J\'});s.G(h).1j(4(){s.5.r(h)});w.K();w.5.r({\'1k-l\':-h.6.c()});w.G({\'1k-l\':0})})},B:4(1m){$1L(1.D);1.D=(4(){1.E.g(4(2){i(2.1i(1.9.q)&&!2.O)2.F(\'1d\');2.1F(1.9.q)}.1g(1))}).1H(1m,1)},1N:4(){i(1.d){1.d.C(\'1h.1R e.p\').g(4(p){8 t=p.1O().1l(\'e.t-1B\');8 6=1f.1c(p.M().6,t.M().6);8 o=[p,t];o.g(4(5){8 y=5.k(\'A-l\').c()+5.k(\'A-z\').c()+5.k(\'x-l-b\').c()+5.k(\'x-z-b\').c();5.L(\'6\',6-y)})})}},1q:4(){i(1.d){1.d.C(\'e.7-3\').g(4(e){8 o=e.Q();8 6=0;o.g(4(5){6=1f.1c(5.M().6,6)});o.g(4(5){8 y=5.k(\'A-l\').c()+5.k(\'A-z\').c()+5.k(\'x-l-b\').c()+5.k(\'x-z-b\').c();5.L(\'6\',6-y)})})}}});17.1M(f 1S,f 1K);',62,118,'|this|item||function|element|height|dropdown|var|options|obj|width|toInt|menu|div|new|each|styles|if|fx|getStyle|top|remain|event|elements|sub|remainClass|setStyles|fx1|hover|Fx|reset|fx2|border|offset|bottom|padding|removeRemain|getElements|timer|dropdowns|fireEvent|start|opacity|Styles|hidden|stop|setStyle|getCoordinates|overflow|_dropdownhover|mode|getChildren|Element|mouseenter|mouseleave|addEvents|dropdownSelector|adopt|remainTime|false|itemSelector||relatedTarget|case|window|injectInside|attachSlideFx|attachDefaultFx|YOODropdownMenu|include|else|break|getStyles|max|dropdownleave|addEvent|Math|bind|li|hasClass|chain|margin|getElement|delaytime|wait|linear|return|matchUlHeight|addClass|Transitions|null|600|setOptions|initialize|Class|default|ul|800|box4|duration|transition|opera|removeClass|switch|delay|extend|ie|Options|clear|implement|matchHeight|getParent|slide|true|level2|Events|hasChild'.split('|'),0,{}))

помогите плиз с этим скиптом разобраться - из-за него в выпадающем меню сайиата пункты меняют цвет с определенного в ЦСС на какой-то серый градиент, что не нужно ниразу. Где тут это определяется?

_________________
ASUS A4M88T-M, Athlon II X3 425, 2GB NCP, video - internal ATI 4250, 200GB Samsung HDD, Win7 x64


 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
AzaZeo Это не скрипт а хлам какой-то, ни один вменяемый программист в нём не разберётся (просто не станет) выпадающее меню проще делается и в наше время даже без JS просто на CSS

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Member
Статус: Не в сети
Регистрация: 23.12.2004
Откуда: Беларусь, Минск
Грустно весьма
Просто в целом все эффекты этого скрипта нужны, кроме изменения цвета, потому с нуля и делать не хотелось

Добавлено спустя 4 минуты 53 секунды:
фишка в том, чтобы меню выезжало плавно, и цвета выделения пункта тоже менялись плавно

_________________
ASUS A4M88T-M, Athlon II X3 425, 2GB NCP, video - internal ATI 4250, 200GB Samsung HDD, Win7 x64


 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
http://anton.shevchuk.name/javascript/j ... ginners-2/

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Junior
Статус: Не в сети
Регистрация: 02.06.2010
Откуда: Украина, Херсон
Добрый вечер!
Народ, помогите разобраться в таком коде:
Код:
if (!isset($_SERVER['PHP_AUTH_USER']))

{
        Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
        Header ("HTTP/1.0 401 Unauthorized");
        exit();
}

else {
        if (!get_magic_quotes_gpc()) {
                $_SERVER['PHP_AUTH_USER'] = mysql_escape_string($_SERVER['PHP_AUTH_USER']);
                $_SERVER['PHP_AUTH_PW'] = mysql_escape_string($_SERVER['PHP_AUTH_PW']);
        }

        $query = "SELECT pass FROM person WHERE login='".$_SERVER['PHP_AUTH_USER']."'";
        $lst = @mysql_query($query);

        if (!$lst)
        {
            Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
        Header ("HTTP/1.0 401 Unauthorized");
        exit();
        }

        if (mysql_num_rows($lst) == 0)
        {
           Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
           Header ("HTTP/1.0 401 Unauthorized");
           exit();
        }

        $pass =  @mysql_fetch_array($lst);
        if ($_SERVER['PHP_AUTH_PW']!= $pass['pass'])
        {
            Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
           Header ("HTTP/1.0 401 Unauthorized");
           exit();
        }
}

это файл для входа в админскую зону через пароль. Но он не работает. Выдает ошибки:
Код:
Warning: Cannot modify header information - headers already sent by (output started at Z:\home\localhost\www\phpsite\admin\index.php:2) in Z:\home\localhost\www\phpsite\admin\lock.php on line 6

Warning: Cannot modify header information - headers already sent by (output started at Z:\home\localhost\www\phpsite\admin\index.php:2) in Z:\home\localhost\www\phpsite\admin\lock.php on line 7

Ругаеться на первых 2 хидера
В чем может быть проблема? файлик писал не я.


 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
Смотри что выводится перед этим кодом, если ничего проверь BOM (если вайл в UTF)

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Junior
Статус: Не в сети
Регистрация: 02.06.2010
Откуда: Украина, Херсон
Vladson писал(а):
Смотри что выводится перед этим кодом, если ничего проверь BOM (если вайл в UTF)

Спасибо. Помогло :beer:

Добавлено спустя 22 минуты 40 секунд:
Да, а как несчет безопасности, смогут взломать?


 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
Могут, и легко если включен magic_quotes

mysql_escape_string надо делать в любом случае, а если включен magic_quotes то сначала надо его убрать (stripslash) ибо он не полностью защищает как mysql_escape_string, а только "от дурака"

(так-же это нужно для "логики" скрипта, ведь в $_SERVER['PHP_AUTH_USER'] у нас должен лежать "чистый" ник без "magic_quotes" и "mysql_escape_string", мало ли ниже в скрипте нам понадобится вывести его на экран, или отправить на мыло, или даже нарисовать картинку с таковым...)

Да и проверку на логин лучше вынести сразу в SQL

И пароль в базе хранить не принято, лучше хранить хеш на всякий случай

Т.е лучше типа такого
Код:
        if (get_magic_quotes_gpc()) {
                $_SERVER['PHP_AUTH_USER'] = stripslashes($_SERVER['PHP_AUTH_USER']);
                $_SERVER['PHP_AUTH_PW'] = stripslashes($_SERVER['PHP_AUTH_PW']);
        }
        $username_sql = mysql_escape_string($_SERVER['PHP_AUTH_USER']);
        $password_sql = md5($_SERVER['PHP_AUTH_PW']);
        $query = "SELECT * FROM person WHERE login='$username_sql' AND pass = '$password_sql'";


Добавлено спустя 10 часов 52 минуты 38 секунд:
И от собак в коде лучше избавиться, это не тот случай когда они нужны (и даже не тот когда допустимы)

Добавлено спустя 1 минуту 36 секунд:
А вообще лучше учись сразу с PDO уже на 99% хостеров стоит, удобно просто ОЧЕНЬ

Добавлено спустя 23 минуты 8 секунд:
Вот небольшой пример.
Код:
<?php
/* сама наша база
CREATE TABLE `users` (
   `username` varchar(64) NOT NULL,
   `password` varchar(192) NOT NULL,
   UNIQUE KEY `username` (`username`),
   KEY `password` (`password`)
) ENGINE=MyISAM;

INSERT INTO `users` (`username`, `password`) VALUES ('Vladson', '123456');
*/

// тут всё логично
if (!isset($_SERVER['PHP_AUTH_USER'])) {
        Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
        Header ("HTTP/1.0 401 Unauthorized");
        exit();
}

// тут посылаем нафик кавычки
if (get_magic_quotes_gpc()) {
   $_SERVER['PHP_AUTH_USER'] = stripslashes($_SERVER['PHP_AUTH_USER']);
   $_SERVER['PHP_AUTH_PW'] = stripslashes($_SERVER['PHP_AUTH_PW']);
}

// конект к базе (как я понимаю у тебя в скрипте он раньше)
$dbh = new PDO('mysql:dbname=test;host=localhost', 'root', '');

// готовим запрос
$sth = $dbh->prepare('SELECT * FROM `users` WHERE `username` = :username AND `password` = :password;');

// отправляем запрос
$sth->execute(array(
      ':username' => $_SERVER['PHP_AUTH_USER'],
      ':password' => $_SERVER['PHP_AUTH_PW']
   )
);

// Получаем ответ
$user_data = $sth->fetch(PDO::FETCH_ASSOC);

// false в случае если юзера нет или пароль неверный
if ($user_data == false || !is_array($user_data)) {
        Header ("WWW-Authenticate: Basic realm=\"Admin Page\"");
        Header ("HTTP/1.0 401 Unauthorized");
        exit();
}

// или вся информация в $user_data если всё удачно
var_dump($user_data);
?>

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Member
Статус: Не в сети
Регистрация: 19.03.2003
Вопрос скорее чисто по MySQL.
Есть таблица geoip с ~4M записей, состоящая из 3ёх столбцов: start_ip, end_ip и loc_id. IP хранятся в числовом формате.
Нужно проверить, к какому loc_id относится определённый IP.

Делаю запрос:
Код:
SELECT
  loc_id
FROM
  geoip_cities_mem WHERE (2999999999 BETWEEN start_ip AND end_ip) LIMIT 1;


Выполняется он примерно 0,2-0,4 секунды, а это долго. Как можно оптимизировать этот запрос?

Я пробовал таблицы MYISAM и MEMORY - разница между ними не очень большая (про InnoDB я молчу - там запрос занимает около 30 секунд).
Пробовал секционирование для обоих типов таблиц, но то ли я чего-то не так кромсаю, то ли секционирование просто неэффективно. Думаю, что первое - где-то я недорыл, так что буду признателен за совет с примером в этом направлении.
Пробовал индексы и первичные ключи - толку никакого, а на MYISAM сплошной вред - время запроса возрастает.

Есть вариант костыля - создать отдельную БД под geoip, а в ней 1000 таблиц типа MEMORY с названиями geoip_[первый_start_ip]_[последний_end_ip], а потом сначала определять имя таблицы, а затем уже искать в этой таблице. Но это самый крайний вариант.
Есть ещё совершенно адское решение - проиндексировать вообще все IP адреса из таблицы, чтобы таблица имела вид |ip|loc_id|. Но в таком случае таблица станет занимать несколько гигабайт, а в памяти её можно будет размещать только на очень дорогом сервере.


Версия MySQL: 5.1.48
ОС: Windows Vista/7
Процессор: AMD Athlon 6000+/Intel Core2Duo P8700
Память: 2GB/4GB
(на обеих системах результаты примерно одинаковые)

Добавлено спустя 11 часов 39 минут 6 секунд:
Нашёл на Хабре решение, правда оно было в одном-единственном посте (не про MySQL) в одном из комментариев.

Решение:
Удалить из таблицы столбец end_ip (а можно, в принципе и не удалять - разница по скорости где-то 20%), оставив только start_ip и loc_id. Затем добавить простой индекс на start_ip.
Код таблицы:
Код:
CREATE TABLE geoip_city_blocks(
  start_ip INT(10) UNSIGNED NOT NULL,
  loc_id INT(5) UNSIGNED NOT NULL,
  UNIQUE INDEX UK_geoip_city_blocks_start_ip (start_ip)
)
ENGINE = MYISAM
AVG_ROW_LENGTH = 9;


Запрос должен выглядеть так:
Код:
SELECT loc_id FROM geoip_city where start_ip <= @ip order by start_ip desc limit 1;

Запрос открыт за 0,001c [0,001c выполнение, < 0,001c выборка]

Единственная проблема: если нужной группы IP изначально не было в базе, loc_id определится неправильно, но это меньшее зло, на мой взгляд.

Ещё нужно иметь ввиду, что запрос "SELECT SQL_SMALL_RESULT DISTINCT loc_id FROM geoip_city_blocks WHERE @ip BETWEEN start_ip AND end_ip LIMIT 1;" (если оставить end_ip, конечно) будет выполняться в таком случае уже секунды.

Теоретически, при правильном ручном секционировании, с равномерным распределением значений start_ip по секциям, можно ещё сильнее увеличить производительность. Но, как я ни старался, ничего путного с секционированием у меня не выходит :(

Добавлено спустя 4 минуты 45 секунд:
PS: Спасибо товарищу Wott с Хабра.

Добавлено спустя 13 минут 56 секунд:
PPS: Наилучшие типы таблиц: для geoip_blocks - MYISAM, а для geoip_locations (в которой страны, города, широта и долгота) - InnoDB. Сейчас ещё поиграюсь с секционированием таблицы geoip_locations.


Последний раз редактировалось Cruel_Crow 13.07.2010 15:32, всего редактировалось 1 раз.

 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
Я бы предложил поискать GeoIP на файлах, есть одна очень быстрая реализация, но я совершенно не помню где я её видел, то-ли на phpclub то-ли на ru-board...

Так-же если действительно
Cruel_Crow писал(а):
Запрос открыт за 0,001c

против
Cruel_Crow писал(а):
0,2-0,4 секунды

То
Cruel_Crow писал(а):
можно, в принципе и не удалять

И делать два запроса, один чтоб проверить нижнюю границу второй чтоб верхнюю чтоб избежать
Cruel_Crow писал(а):
если нужной группы IP изначально не было в базе

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Member
Статус: Не в сети
Регистрация: 19.03.2003
Vladson
Цитата:
Я бы предложил поискать GeoIP на файлах, есть одна очень быстрая реализация, но я совершенно не помню где я её видел, то-ли на phpclub то-ли на ru-board...

Нужно именно SQL-решение. Решение MaxMind быстрое, но где-то в тех же пределах, что и оптимизированный MySQL запрос.

Цитата:
И делать два запроса, один чтоб проверить нижнюю границу второй чтоб верхнюю чтоб избежать

Хе-хе, уже так и сделал, как раз хотел здесь отпостить :)
Таблица:
Код:
CREATE TABLE geoip_city_blocks(
  start_ip INT(10) UNSIGNED NOT NULL,
  end_ip INT(10) UNSIGNED NOT NULL,
  loc_id INT(5) UNSIGNED NOT NULL,
  UNIQUE INDEX UK_geoip_city_blocks_end_ip (end_ip),
  UNIQUE INDEX UK_geoip_city_blocks_start_ip (start_ip)
)
ENGINE = MYISAM;


Запрос с одиночной проверкой:
Код:
SET @ip = INET_ATON('12.4.48.249');
SELECT loc_id FROM geoip_city_blocks WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 1;

Запрос открыт за 0,002c [0,001c выполнение, 0,001c выборка]

Запрос с двойной проверкой:
Код:
SET @ip = INET_ATON('12.4.48.249');
SELECT t.loc_id FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= @ip ORDER BY end_ip ASC LIMIT 1) t WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 1;

Запрос открыт за 0,003c [0,002c выполнение, 0,001c выборка]

Если задать несуществующий IP, например "SET @ip = INET_ATON('192.168.0.1');", то второй запрос верёнт NULL.

Теперь протестируем всё тоже самое, но с бОльшим LIMIT (практического толку никакого -чисто для более точной оценки производительности):
На существующем IP:
Код:
SET @ip = INET_ATON('121.120.220.220');


Код:
SELECT loc_id FROM geoip_city_blocks WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 100000;

Запрос открыт за 0,922c [0,290c выполнение, 0,632c выборка]

Код:
SELECT t.loc_id FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= @ip ORDER BY end_ip ASC LIMIT 100000) t WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 1;

Запрос открыт за 0,795c [0,794c выполнение, 0,001c выборка]

На несуществующем IP:
Код:
SET @ip = INET_ATON('127.0.0.1');

Код:
SELECT loc_id FROM geoip_city_blocks WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 100000;

Запрос открыт за 0,969c [0,287c выполнение, 0,682c выборка]
Код:
SELECT t.loc_id FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= @ip ORDER BY end_ip ASC LIMIT 100000) t WHERE start_ip <= @ip ORDER BY start_ip DESC LIMIT 1;

Запрос открыт за 0,802c [0,801c выполнение, 0,001c выборка]

Добавлено спустя 6 минут 44 секунды:
То есть, на один запрос при одиночной проверке уходит где-то 0,00000922 сек. (9-10 usec), а при двойной - 0,00000795 сек. (8-9 usec).

Результаты тестирования меня озадачили, если честно. Каким образом двойная проверка выполняется быстрее одиночной при большом количестве результатов - загадка.


Последний раз редактировалось Cruel_Crow 13.07.2010 15:32, всего редактировалось 1 раз.

 

member+
Статус: Не в сети
Регистрация: 16.01.2004
Откуда: Estonia,Tallinn
Мускул полон загадок, у меня вообще результаты были "весёлые" когда выборка из двух таблиц была быстрее чем из одной

_________________
X99-TF/E5-2678v3+Evo212/2x16Gb-DDR4-Gloway-TYPE-a@2133-12-13-13-26/GTX1070TI/KINGSTON-SNV2S1000G


 

Member
Статус: Не в сети
Регистрация: 03.04.2010
Откуда: Полоцк
Cruel_Crow писал(а):
То есть, на один запрос при одиночной проверке уходит где-то 0,00000922 сек. (9-10 usec), а при двойной - 0,00000795 сек. (8-9 usec).

Обратите внимание на это:
Cruel_Crow писал(а):
0,922c [0,290c выполнение, 0,632c выборка]

Cruel_Crow писал(а):
0,795c [0,794c выполнение, 0,001c выборка]


У вас выполнение первого запроса идет в 2,7 раза быстрее чем второго, но куча времени уходит на выборку. Вот вам и разница получается из-за выборки.
Нужно учитывать не только время выполнения запроса, но и объемы возвращаемых данных.

_________________
955BE•TT BT VX•M4A78T-E•KVR1333D3N9K2/4G•ST31000528AS•WD15EARS-00MVWB0•WD20EARX•HD4870 VAPOR-X 1GB•INWIN IP-S550AQ3-0


 

Member
Статус: Не в сети
Регистрация: 19.03.2003
AlimAlex
Да, но для того, кто будет общаться с MySQL (например, php), важно всё-таки общее время.

---

Написал вот несколько функций для работы с GeoIpCity в MySQL.
Для начала, таблицы:
Код:
CREATE TABLE geoip_city_blocks(
  start_ip INT(10) UNSIGNED NOT NULL,
  end_ip INT(10) UNSIGNED NOT NULL,
  loc_id INT(5) UNSIGNED NOT NULL,
  UNIQUE INDEX UK_geoip_city_blocks_end_ip (end_ip),
  UNIQUE INDEX UK_geoip_city_blocks_start_ip (start_ip)
)
ENGINE = MYISAM
AVG_ROW_LENGTH = 13
CHARACTER SET utf8
COLLATE utf8_general_ci;


CREATE TABLE geoip_city_location(
  loc_id INT(11) UNSIGNED NOT NULL,
  country VARCHAR(2) NOT NULL,
  region VARCHAR(2) DEFAULT NULL,
  city VARCHAR(255) DEFAULT NULL,
  postal_code VARCHAR(255) DEFAULT NULL,
  latitude FLOAT(8, 4) DEFAULT NULL,
  longitude FLOAT(8, 4) DEFAULT NULL,
  area_code INT(5) DEFAULT NULL,
  PRIMARY KEY (loc_id)
)
ENGINE = INNODB
AVG_ROW_LENGTH = 57
CHARACTER SET utf8
COLLATE utf8_general_ci;



Сами функции:
Код:
CREATE FUNCTION determine_reserved_ip(ip_numeric INT(10) UNSIGNED)
  RETURNS bit(1)
  DETERMINISTIC
  SQL SECURITY INVOKER
  NO SQL
  COMMENT 'Returns NULL if IP is reserved, 0 when IP is local. 1 when ip ok'
BEGIN
  IF ((ip_numeric < 0) OR (ip_numeric > 4294967295)) THEN RETURN NULL; END IF;

  #determine reserved ip addresses
  /*
  v0.0.0.0/8
  v10.0.0.0/8
  v14.0.0.0/8
  v192.0.2.0/24
  v192.88.99.0/24
  v198.18.0.0/15
  v224.0.0.0/4
  v240.0.0.0/4 - multicast and other
 
  #locals:
  v127.0.0.0/8 - loopback
  v169.254.0.0/16
  v172.16.0.0/12
  192.168.0.0/16
  */
  IF (
    (ip_numeric & 4278190080 = 0)/*0.0.0.0/8*/
    OR
    (ip_numeric & 4278190080 = 167772160)/*10.0.0.0/8*/
    OR
    (ip_numeric & 4278190080 = 234881024)/*14.0.0.0/8*/
    OR
    (ip_numeric & 4294967040 = 3221225984)/*192.0.2.0/24*/
    OR
    (ip_numeric & 4294967040 = 3227017984)/*192.88.99.0/24*/
    OR
    (ip_numeric & 4294836224 = 3323068416)/*198.18.0.0/15*/
    OR
    (ip_numeric & 3758096384 = 3758096384)/*224.0.0.0/4*/
    OR
    (ip_numeric & 4026531840 = 4026531840)/*240.0.0.0/4*/
      ) THEN RETURN NULL; END IF;

  IF (
    (ip_numeric & 4278190080 = 2130706432)/*127.0.0.0/8*/
    OR
    (ip_numeric & 4294901760 = 2851995648)/*169.254.0.0/16*/
    OR
    (ip_numeric & 4293918720 = 2886729728)/*172.16.0.0/12*/
    OR
    (ip_numeric & 4294901760 = 3232235520)/*192.168.0.0/16*/
      ) THEN RETURN 0; END IF;

  RETURN 1;
END

Код:
CREATE FUNCTION get_loc_id_from_ip(ip VARCHAR(255))
  RETURNS int(7)
  DETERMINISTIC
  SQL SECURITY INVOKER
  READS SQL DATA
  COMMENT 'Returns NULL when address is unproper and 0 when local address'
BEGIN
  DECLARE ip_check BIT DEFAULT NULL;
  DECLARE ip_numeric INT(10) UNSIGNED;
  SET ip_numeric = INET_ATON(ip);
  IF (ip_numeric IS NULL) THEN RETURN NULL; END IF;
 
  SET ip_check = determine_reserved_ip(ip_numeric);
  IF (ip_check IS NULL) THEN RETURN NULL; END IF;
  IF (ip_check = 0) THEN RETURN 0; END IF;

  RETURN (SELECT t.loc_id FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= ip_numeric ORDER BY end_ip ASC LIMIT 1) t WHERE start_ip <= ip_numeric ORDER BY start_ip DESC LIMIT 1);

  RETURN NULL;
END

Код:
CREATE FUNCTION get_location_from_loc_id(loc_id INT)
  RETURNS varchar(255) CHARSET utf8
  DETERMINISTIC
  SQL SECURITY INVOKER
  READS SQL DATA
  COMMENT 'Reads locations table and returns country/region/city'
BEGIN
  IF (loc_id = NULL) THEN RETURN NULL; END IF;
  IF (loc_id = 0) THEN RETURN 'LAN'; END IF; #ip is in local network

  RETURN (SELECT CONCAT(`country`, '/', `region`, '/', `city`) FROM geoip_city_location WHERE geoip_city_location.loc_id = loc_id ORDER BY geoip_city_location.loc_id ASC LIMIT 1);
END

Код:
CREATE FUNCTION get_location_from_ip(ip VARCHAR(255))
  RETURNS varchar(255) CHARSET utf8
  DETERMINISTIC
  SQL SECURITY INVOKER
  READS SQL DATA
  COMMENT 'Determines geographic location by ip address'
BEGIN
  DECLARE ip_check BIT DEFAULT NULL;
  DECLARE ip_numeric INT(10) UNSIGNED;
  SET ip_numeric = INET_ATON(ip);
  IF (ip_numeric IS NULL) THEN RETURN NULL; END IF;
 
  SET ip_check = determine_reserved_ip(ip_numeric);
  IF (ip_check IS NULL) THEN RETURN NULL; END IF;
  IF (ip_check = 0) THEN RETURN 'LAN'; END IF;

  RETURN (SELECT CONCAT(`country`, '/', `region`, '/', `city`) FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= ip_numeric ORDER BY end_ip ASC LIMIT 1) t INNER JOIN geoip_city_location ON t.loc_id = geoip_city_location.loc_id WHERE start_ip <= ip_numeric ORDER BY start_ip DESC LIMIT 1);
END


Добавлено спустя 7 минут 27 секунд:
BIT determine_reserved_ip(ip_numeric INT(10) UNSIGNED) - вспомогательная функция. Принимает IP в числовом формате (можно воспользоваться INET_ATON()) Возвращает NULL, если IP был некорректный или зарезервированный, '0' - если IP из локалки и '1', если всё в порядке.

INT get_loc_id_from_ip(ip VARCHAR(255)) - определяет по IP-адресу ID местоположения, который можно получить из таблицы geoip_city_location.

VARCHAR get_location_from_loc_id(loc_id INT) - если есть ID, полученный из предыдущей функции, можно воспользоваться этой для определения местоположения. Оно вернётся в формате Страна/Регион/Город (NULL - если такого ID нету и 'LAN', если адрес из локальной сети).

VARCHAR get_location_from_ip(ip VARCHAR(255)) - объединяет две предыдущие функции, возвращая Страну/Регион/Город прямо из IP.


 

Member
Статус: Не в сети
Регистрация: 07.01.2010
а попробуй сделать такой индекс:
UNIQUE INDEX geoip_ip_range (start_ip desc, end_ip ask)

и в запросе писать where @ip >= start_ip and @ip <= end_ip

по-идее оно тогда должно прошуршать по первой колонке индекса, потом по второй и быстро-быстро найти

да, ещё попробуй explain plan посмотреть, очень сильно помогает при таких задачах. секционировать имхо смысла никакого, если будет активно использоваться индекс, т.к. проблем с извлечением данных у тебя вроде как нету


 

Member
Статус: Не в сети
Регистрация: 19.03.2003
ToSHiC
Цитата:
а попробуй сделать такой индекс:
UNIQUE INDEX geoip_ip_range (start_ip desc, end_ip ask)

и в запросе писать where @ip >= start_ip and @ip <= end_ip

Цитата:
по-идее оно тогда должно прошуршать по первой колонке индекса, потом по второй и быстро-быстро найти

Пробовал. Время выполнения запроса увеличивалось где-то в два раза. Я знаю, что, в теории, должно было помочь, но не помогает, зараза.

Цитата:
да, ещё попробуй explain plan посмотреть, очень сильно помогает при таких задачах.

Когда только столкнулся с проблемой выборки из GeoIP, юзал его. Потом забил и перешёл на метод тыка :)


Цитата:
секционировать имхо смысла никакого, если будет активно использоваться индекс, т.к. проблем с извлечением данных у тебя вроде как нету

Отвлекаясь от GeoIP: есть где-нибудь в Интернете примеры реального использования секционирования с бенчмарками? Не нашёл чего-то.


 

Member
Статус: Не в сети
Регистрация: 07.01.2010
тоже попробовал вчера вечером. тоже не проканало :) приучил меня оракл ко всяким вкусностям... но меня всё равно не покидает мысль, что надо как-то заставить его юзать составной индекс. ну или если он совсем не хочет, то, в теории, шустрее всего будет запрос
SELECT t.loc_id FROM (SELECT loc_id, start_ip FROM geoip_city_blocks WHERE end_ip >= ip_numeric ORDER BY end_ip ASC LIMIT 1) t WHERE start_ip <= ip_numeric ORDER BY start_ip DESC LIMIT 1


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 1267 • Страница 48 из 64<  1 ... 45  46  47  48  49  50  51 ... 64  >
-

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan