Pull to refresh

Comments 104

вы маньяк,
где записывают в вашу армию захвата мира?
:)
Дык тут, на Хабре :) Кажется это назывется «добавить в друзья» :)
Эх, было б еще мозгов сделать все то, что реально хочется сделать — но вот серой массы не хватает :)
дык, уже в друзьях

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

хитро придумано :)
В таком случае, надеюсь Хабр уже скопирован)
А то и читать не чего будет потом… =)
А я то думал гугл этим занимается 0_o
думаете стоит выкуп назначить за то, чтобы оставить интернет на месте? :)
мне вот только покоя гугл не дает — пока его один датацентр скопируешь — он новый строит :)
это потому что пока вы копируете у гугла он копирует у вас!
интернет можно на месте не оставлять. просто потом брать деньги за просмотр с каждого желающего :)
> это потому что пока вы копируете у гугла он копирует у вас!
:))) что-то я об этом и не подумал. а мужики-то не знают. может гуглу рассказать что у них нет триллиона страниц в интернете, а это они скачивают то, что я скачал с них? или «улыбаемся и машем ручкой»? :) © мадагаскар
лучше ускорьте уже закачку интернета и постройку новых датацентров
гугл первый сдаться, я уверен :)
план по созданию кнопки «скачать интернет» уже в действии
да, и судя по всему web 3.0 будет доступен только избранным и за большие деньги :)
да уж. тут ситуация вырисовывается похлеще, чем текущее господство гугла на просторах интернета =))
можно полюбопытствовать по поводу конечной скорости сбора страниц?

зы. у самого есть слабость к подобным вещам, практикую бывает. оттуда и интерес ;)
Она очень скачет — интернет неоднороден, то бывает пустые сайты прям подряд идут, то один за одним тяжелые научные трактаты. ) Как я и сказал есть 72 млн. страниц и обход длиться 55 дней = 72 000 000 / 55 / 86 400 = 15 сайтов в секунду. Датацентр Amazon.
хм. всё таки 55дней — это слишком.

я бы посоветовал подумать над алгоритмом, уж больно затратный у вас.
я с рунета начинал обходить. сначала рунет за 3 дня, потом за сутки, потом за 6 часов))
теперь на хилом серваке можно еще меньше потратить… главное чтобы места хватило))

как подсказка — зря так много бд спрашиваете, можно практически без запросов к бд сделать.
а бд использовать только для обработки конечных показателей.
(и не файловая, просто немного подумать — как именно в очередь ставить в многопоток, с точками останов одновременно — чтобы остановить-продолжить можно было… ;) )
MySQL CPU usage: 3%
CPU CPU usage: 97%
iowait: 0
:)

алгоритм уже настолько оптимизирован насколько мне хотелось бы — дорабатывать я его не буду.
Проиндексировать весь рунет за 6 часов одним сервером? Извините, но не верю =)
жесть. читал на одном дыхании, как триллер какойто :) спасиб.
а увеличить память для mysql не пробовали? а также временные файлы и файлы для кешей таблиц?
для увеличения скорости вставки можно вставлять сразу несколько записей одним запросом
для увеличения скорости update, select и delete, неплохо бы ввести индексы на те поля, которые используете при выборке (where)
ввод индексов, конечно, увеличит потребление диска, а также замедлит вставку, поэтому стоит отключать индексы при вставке (alter table… disable keys)
В тот момент — многое из этого не делал, ну только памяти давал, потом уж научился, правда кардинально это не спасает. Я понял что проектирование базы куда важнее, чем .conf :)

> ввести индексы на те поля, которые используете при выборке (where)

Вот из-за них тормозил insert/update/delete, а без них тормозит select :)
Не, конечно индексы сделаны были, но это не спасало, потому что нужно было и ту и ту операцию делать.

Я вам еще страшнее расскажу — я чтобы не долбиться на одни и те же пытался order by rand() делать :) на таблице из 72 млн. :)
все-таки, по-моему, индексы должны увеличить скорость update и delete… по крайней мере теоретически.

update без индекса:
* поиск записи — без индексов, это просмотр N записей
* обновление значения, не зависит от наличия или отсутствия индекса
итого: N * t_поиска + t_обновления

update с индексом:
* поиск записи — с индексом, logN (обычно б-дерево)
* обновление значения
* обновления индекса — поиск в дереве + запись
итого: logN * t_поиска + t_обновления + logN * t_поиска + t_обновление_индекса

т.е. апдейт с индексом выигрывает при больших таблицах
ну смотрите — индекс это ж у нас b-tree насколько я понимаю, скорее всего сбалансированный b-tree. сначала у нас есть индекс на 100 кб, допустим. а потом он становится на 1000 мб. понятно что она не дописала эти 900 кб, а раздвигала дерево, сдвигая от центра к концу файла (ну условно говоря, в общем — перебрасывала почти половину при каком-то количестве запросов). по крайней мере, я так думаю.

во всяком случае, как факт — все получилось, и индекс остался primary(id) + index(status). работало нормально. сейчас правда я методику другую использую, но она питонская, а не php — так что сюда уже не стал ее дописывать.
>т.е. апдейт с индексом выигрывает при больших таблицах
А вот апдейт индексА сильно проигрывает, т.к. это вызывает перестройку всего индекса
ну это то, что я и подозревал постом выше про «скорее всего сбалансированный b-tree»…
а вот что такое «апдейт С индексОМ»?
под «апдейтом с индексом» я подразумевал апдейт таблицы с индексом (т.е. сравнивал таблицу с индексом и без)
> индексы должны увеличить скорость update и delete
если вы работаете с myISAM, то так и происходит.
Этот тип хранилища оптимизирован под UPDATE.

Для очень быстрого селекта и инсерта используется InnoDB с инкрементальным первичным ключом. Однако скорость апдейта будет O(log(x)) или даже x*log(x) — на больших количествах данных очень болезненно.

Но автор, сам признался что отказался от апдейтов, в данном случае это правильно :)

Вообще хороший такой боевой опыт, положительный. Был бы захабрен — плюсов понаставил бы…
update более ресурсоемкая операция чем delete?
update и delete имеют одинаковый порядок скорости выполнения. речь о перестройке индекса после них.
просто я как-то слушал доклад разработчиков одно популярно фотохостинга, так вот они отказались вообще от запросов delete и как-то вроде даже снизили нагрузку.
> Для очень быстрого селекта и инсерта используется InnoDB с инкрементальным первичным ключом.

Честно говоря, весь мой опыт говорит об обратном. Последний тест показал разницу в 10 раз и InnoDB медленнее оказалась. (Правда без тюнинга, но и MyISAM тоже дефолтовый был для сравнения.)
Интересно, а покажите структуру.
интересно, а как «грамотно» сделать order by rand() на таких объемах?
UFO just landed and posted this here
а вам не кажется, что where id in (1,2,3) = where id in (3,1,2)?
да и вложенные запросы обычно дольше двух запросов
UFO just landed and posted this here
так а почему
select * from table where id in (SELECT id table ORDER BY rand())
будет лучше чем

select * from table ORDER BY rand()

??
UFO just landed and posted this here
я попробовал, действительно быстро, но ведь в подзапросе есть select * from table ORDER BY rand() который по вашим словам «создаст же темп таблицу, в в которой придется мешать все записи рандомом а не int11 числа ;)»

т.е я согласен что быстро и спасибо за наводку, но мне просто любопытно почему )))
а сорри, кажеться начинаю понимать, все дело в *
UFO just landed and posted this here
Mysql позволяет сортировать случайным образом

SELECT * FROM my_table ORDER BY RAND()

Проблема в том, что такая сортировка зачастую вовсе не нужна для всей выборки — хочется просто достать случайный элемент из определённого множества, к тому же ORDER BY RAND() достаточно медленный выход из ситуации. Можно попробовать делать выборку основываясь на числе элементов в целом и функции RAND():

SELECT name FROM my_table JOIN (
SELECT CEIL(RAND() * (
SELECT MAX(id) FROM my_table
)) AS randomID
) AS random_table ON random_table.randomID=my_table.ID

На 50000 рядов такой запрос занимает 0.00086 сек… Сравните с 1.56356 сек обычного варианта ORDER BY RAND().
UFO just landed and posted this here
ну вы ж понимаете что запрос можно чуть-чуть изменить и разрывы в id уже будут не помеха
UFO just landed and posted this here
yoihj yoihj yoihj — ну вот, теперь это не самое редкое слово…

Придется Вам все пересчитывать с начала…
Эх… знали бы Вы сколько раз я УЖЕ перекачивал это снова, обнаружив, например на 35 день индексации (полный индекс идет 55 дней) что у меня индексируется все внутри [style] [/style]… заново!.. потом на где-то 40 день после нового индекса, обнаружил что некоторые слова сливаются при стечении некоторых обстоятельств… заново… если честно — у меня до сих пор нет полного ПРАВИЛЬНОГО индекса… последний раз завис 30 дней назад и из-за чего-то сбросилась переменная, которая указывала с какого места индексируем и пошло заново… я все еще жду полного обхода :) сейчас на букве «k»… до «z» уже недалеко )) еще дней 20 ))
Вы живёте на проценты от какой-то халтурки для гугла? =) или получили наследство?

Я бы тоже с удовольствием позанимался подобным, разве что чуть более полезным ;) но приходится работать =\
Если процедура разовая, то проще выгрузить все урлы в несколько текстовых файлов. И запустить каждый процесс на определенный диапазон этих самых файлов. Что делать с результатами — другой вопрос
Ну да, сейчас уже что-то подобное и делаю — select into outfile, правда файл один, а Python'ский скрипт через пул threadов читает подряд (fgets), а в mysql хранится только в каком месте файл читаем.
я бы сделал примерно так
for($treadnum=1;$treadnum<=100;$treadnum++) {
exec ('php tread.php '.$treadnum)
}
а в tread.php
$num=(mt_rand(1,72000000)%$argv[1]);
SELECT id, url WHERE status='еще не были' AND id=$num;
окей, а когда у Вас останется всего миллион записей, то есть программа будет запускаться 72 раза в среднем в пустую? если время запуска 0.01 — значит уже 1 сайт = 1 секунда, теперь полмиллиона (а это дофига!) — 1 сайт = 2 секунды, до четверти миллиона мы доползем лишь через 6 дней, еще через 6 дней до 1/8 миллиона… когда в базе останется 100 сайтов — сервер устареет раньше, чем они найдутся :)

не, я понимаю, что решения этого есть и в принципе, Ваш план имеет право быть, но обходить тут очень многое придется.
:)) да согласен rand там вообще неподходит. но тогда можно сделать так первый поток выберает заиси 1 ,101,201… второй поток 2,102,202… 99-й 99,199,299 тогда точно никаких блокировок ненужно.

$treadnum=$argv[1];
for($num=$treadnum;$num<720000,$num+=100) {

SELECT id, url WHERE id=$num;

}

тоже вариант, но тогда потоки должны помнить в каком месте они остановились, ибо если мы их останавливаем (например для апдейта кода — php это ж не erlang, который перезагружать код не останавливаясь может) — то начинай все с начала. посмотрите финальное решение (я его дописал в статью, не так давно, в самом конце).
немного ошибся в tread.php
$treadnum=$argv[1];
while(1) {
$num=mt_rand(1,72000000);
// %100 = кол. тредов
if( (($num+$treadnum)%100)==0 ) {
SELECT id, url WHERE id=$num;
if(status='еще не были') {.......}
}
usleep(x);
}

наверное, примерно так и появляются поисковики: )
UFO just landed and posted this here
Яблоко — это сиськи в ИТ-сфере =) без него никуда
жескач то какой :)

Зачем вы в таблице слов исходный url то хранили, если он уже не нужен был для вашей задачи? Без него (только word, cnt) — не было бы 72 млрд…

и почему нельзя было делать какую нть блокировку самодельную при выборке урлов?

Потому что мне результат нужно хранить для отдельных сайтов — смотрите сами therarestwords.com/slashdot.org, к примеру (или любой другой домен, для русских напоминаю, почти не работает — там свои нюансы — борьба fastbot с crawlbot :) )… а попутно уж и глобальную статистику считать.
Я бы сделал динамическое создание однотипных таблиц, чтоб не работать с такими объемами. Лимитом записей в 100 000 — 500 000. Закончив одну таблицу переходил бы к следующей и так далее… Это чтоб не работь с 72 миллионами записей.
Я могу ошибаться, но, в этом тоже есть свои моменты, связанные с файловой системой и большим количеством файлов в одном каталоге.
72 000 000 / 500 000 = 144
72 000 000 / 100 000 = 720

Макс. 720 файлов в одном каталоге — это вполне допустимо.
720 * 3 :) но все равно вполне допустимо. хотя, вообще говоря, опыты по разбиению на таблицы, у меня обычно заканчивались даже еще более медленной скоростью, чем одна большая. но это если выборка из нескольких, если же постоянно одна, в основном, будет — думаю это было бы быстрее.
И это кстати самый простой и многоиспользуемый алгоритм.
таблица url_aa где aa «суффикс» url
url_ab
url_ac

и т.п. всего по ~80000 записей в каждой (кажись:) )
но правда где-то 900 таблиц ;) но скорость же :)

а можно и url_aa…

Я кстати вообще долго понять не мог, а почему вы сразу так не сделали… данные то иерархические и уникальные (url),
причем к тому же распихали таблицы на разные винты, или серверы… очень легко. И самое главное «балансер-раздуплятор» очень легкий.

1. Посмотрите на mapreduce подход. Раз у вас там питон то возмите Disco (discoproject.org), ну или Apache Hadoop
2. Возможно для хранения лучше подойдет Amazon SimpleDB или иная колоночная БД
ой не надо вот про Amazon SimpleDB :) а то придется еще и про нее статью написать, как она людям съедает по несколько тысяч долларов в месяц только за счет посещений GoogleBot :)))

mapreduce знаю, но… у него есть много минусов (хотя и плюсов тоже), но для моих целей больше минусов.
А расскажите, кстати, про минусы mapreduce, особенно для вашего случая?
Я рассматривал многие варианты, в т.ч. даже CouchDB, mogileFS, hadoop, gearman, все они проиграли MySQL по каким-то параметрам. Т.е. в конкретно моей задаче проиграли. rarestwords далеко не самая сложная задача, что я решаю. вот редчайшиеновости — это конец, то, что описано в этой статье — это даже не детский сад, а ясли, по сравнению с теми задачами. )
Вот этого я не понял:
затем каждый thread генерит случайное число и делает СНАЧАЛА UPDATE… rand='92803423' WHERE (status='еще не были')) AND (rand IS NULL), а потом уже SELECT WHERE rand='92803423'. Получаем полный ATOMIC — только один thread гарантированно получит эту запись без транзакций.
— первый thread заполнит ВСЕ пустые записи своим случайным числом и остальным ничего не достанется?
UPDATE … rand='92803423' WHERE (status='еще не были')) AND (rand IS NULL) LIMIT 1 конечно же, забыл.
не понял как вы индексировали слова на сайте ((
почему 1000 слов на домене? может вы главную страницу только парсили?

Извиняюсь, если я что то пропустил в статье…
да, только главную изначально, точнее 400, кажется, слов [1000 просто для примера] = 100 самых редких, 100 редких, 100 общих и 100 слишком общих.
сейчас, кстати, бот идет вглубину до 10 страниц смотрит, чтобы эти 400 набрать )
ясненько, пасибки :)
а сколько заняло место в базе данных индексация на одну главную страницу 72 млн сайтов?
говорят Анатолий Вассерман хранит в голове копию всего интернета и при случае можно бэкап у него взять.
я так понимаю вы решили составить ему конкуренцию:)))
Дык какое оно то самое слово?
Никакое ) почти любой ник, всякие опечатки редких слов, всякие слова на других языках (в зоне .com их мало). Получается очень длинный «long tail», то есть слова с частотой 1 из 72 000 000 занимают едва ли не 90% таблицы.
а самое частовстречающееся?
А мне вот интересно, откуда ресурсы на это берутся. Трафика это должно сжирать немало, да еще
на какой машине это все крутится. Неужели это действительно чисто хобби проект )?
трафика сжирает много но и провайдеров с безлимитками достаточно.

ресурсы нужны не такие уж и большие))
именно для сбора — главное оперативная память, процессор и более главно — широта канала.

имея опыт подобных проделок, могу сказать, что
имея машинку 500Мгц, 128мб рамы + 100mb/s порт — можно сохранять странички со скоростью 15к/минуту
при стабильной нагрузке, оставляя немного ресурсов для работы с сервером.
и ~20к/минуту если серв не жалко(в это время ответ от сервера достаточно долггий идет, максимум ssh).

15к у меня выливалось примерно в 60-80 потоков, 20к в 80-120 потоков

так, что представьте что можно сделать — имея например машинку 3гц CoreDuo/ 2Gb рамы/ 1Gb/s порт — на которой можно запускать для стабильности ~1000 потоков, которые к тому же будут работать быстрее — ибо 1gb порт — не халабала))
а пиво? какое место пиво занимает среди всего этого?
Отнюдь — главный лимит — процессор — обработка Core2duo на Python&psyco+libxml (обработка html'я — а это самый тяжелый момент — идет в быстрой c-библиотеке) чуть-чуть превышает возможности 10мбитного канала. HTML очень вредный язык, особенно когда приходится использовать детектирование кодировки (ибо далеко не всегда она четко указана), а детектирование отнимает полную секунду процессорного времени.

1000 тредов тоже бесполезняк на Коре2дуо (именно такая машина и стоит) = пик скорости в районе 200 тредов наступает — больше-меньше — скорость падает.
у вас канал маленький — 10мб — очень худо для таких проделок.
минимум 100мб. и разделяйте сбор & обработку данных
сначала использовался amazon ec2 с 100 мбит — загрузка канала составляла 9-11 мбит.
MySQL CPU usage: 3%
CPU CPU usage: 97%
iowait: 0
простоев ожидания нет.
днс — opendns.
если разделить сбор и обработку я получу ненужный цикл сохранить между ними, при чем на hdd, который в 100 раз медленее чем рам
думаете? :)

тогда другой вопрос —

что быстрее — обойти 72млн страниц за 55 дней (включая обработку на лету)

или же на машине втрое слабее вашей, за 500руб в месяц — обойти 72млн страниц за 3 суток и потом их обсчитать?

со своим уставом в чужой монастырь не лезут конечно, но разница более чем в 10 раз — стоит призадуматься… к тому же — меньше времени на сбор-обработку больше времени на эксперименты ;)
за питона не скажу, но мне пыха хватает — на скорость более чем не жалуюсь ;)
Машина аналог Core2duo, сначала была на Amazon EC2 = 1 обход всей сети в сумме = $130 — траффик + аренда машины. Сейчас на анлимит 10мбит, опять же Core2duo = $162 в месяц [LayeredTech].
Что то за сайт? Очередная ссылочная ферма?
Стиль изложения какой-то запутанный, понимать тяжело.
Почитал комментарии к описанию и теперь даже не знаю кто сильнее «TechCrunch effect» или «Хабра эффект».
Кто нить напишите сервис для проверки этих аномалий ))) Пусть они подерутся!

По теме. Автор молодец, читая такие статьи — мои проекты становятся быстрее и надёжнее.
а что потом со всем этим делать планируется?
какое слово самое популярное?
UFO just landed and posted this here
Sign up to leave a comment.

Articles

Change theme settings