Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Быстро прочитать и удерживать в памяти 180Мб файл, как? 
V
    Опции темы
yorc
Дата 26.12.2009, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 26.12.2009

Репутация: нет
Всего: нет



всем привет!

взялся тут за text mining, приходится работать с большими объёмами текстовой инфы... а потом выяснилась, что лучшая на сегодня библиотека для извлечения информации из текстов написана на Perl, с которым у меня было ну уж очень короткое знакомство... поэтому обращаюсь к уважаемым гуру, дабы заинтересовать их проблемой и попросить помощи!

итак. есть текстовый файл ~180 Мб
в нём 7.500.000 строк, каждая из них в таком формате:

Код

2    6    THAILAND NATIONAL NANOTECHNOLOGY CENTER
8    14    DHIFFUSHI
16    28    DHIFFUSHI (KAAFU ATOLL)
93    508    CATHOLIC APOSTOLIC CHURCH
1    94    APOSTOLIC CHURCHES
93    508    IRVINGISM
93    508    IRVINGITE
93    508    IRVINGITES


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

мне просто кажется, что стандартный код типа

Код

$FILE1 = "t.txt";
open FILE1;
my @arr = <FILE1>;


не есть самое эффективное решение в данном случае...

заранее признателен за любую помощь/идеи/советы/предложения!



Это сообщение отредактировал(а) yorc - 26.12.2009, 23:23
PM MAIL   Вверх
sir_nuf_nuf
Дата 27.12.2009, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



Цитата(yorc @  26.12.2009,  23:19 Найти цитируемый пост)
организовать данные в памяти так, чтобы можно было как можно быстрее осуществить поиск в них

поиск по _чему_ ?

Если по номеру строки - оптимально хранить  в массиве.
Если полнотекстовый - нужно строить инверсный индекс.

P.S.
А еще совет - попробуйте для начала использовать обычный grep (unix) -  180 МБ хорошо ложаться в кеш операционки, поэтому это может быть довольно таки быстрый поиск.


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
yorc
Дата 27.12.2009, 00:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 26.12.2009

Репутация: нет
Всего: нет



поиск самый примитивный: если среди записей из файла ЕСТЬ слово из текста, то нужно вернуть две цифры, которые соответствуют этому слову в файле. я бы не сказал, что это полнотекстовый поиск, т.к. разделять слова не нужно. будет ли в этом случае оптимальным решением обычная операция проверки существования элемента массива с заданным ключом и извлечение данных при положительной проверке?

насчёт grep не понял?..  вы предлагаете делать системный вызов? и как это связано с кешем системы?
PM MAIL   Вверх
sir_nuf_nuf
Дата 27.12.2009, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



если вы 180 метров засунете в perl - хэш - это будут все 300. которые будут висеть у вас в памяти. 
Доступ по ключу в хэше конечно быстрый.. вот только вопрос - вам точно нужна такая скорость ?

если да.. то

Код

open my $file, "< file.txt" or die "nafig";
my %index = ();
while (<$file>) {
    my ($x, $y, @words) = split /\s+/, $_;
    foreach (@words) {
        $index{$_} = [$x, $y];
    }
}


P.S. как вы планируете использовать этот файл ? опишите полностью задачу, плиз

Это сообщение отредактировал(а) sir_nuf_nuf - 27.12.2009, 11:50


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
amg
Дата 27.12.2009, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: 38
Всего: 50



Цитата(sir_nuf_nuf @  27.12.2009,  11:50 Найти цитируемый пост)
если вы 180 метров засунете в perl - хэш - это будут все 300. которые будут висеть у вас в памяти. 
Больше (гораздо) smile

yorc, совет sir_nuf_nuf про grep, IMHO, хорош. В самом деле, попробуйте, если у Вас *nix. После первого поиска файл закешируется (будет в памяти) и при следующих поисках система фактически уже не будет читать его с диска, возьмет из памяти, а 180 М grep прошерстит быстро.

Вот еще, нашел у себя скриптик и переделал его немного под Вашу задачу. На диске будет храниться БД, надеюсь, поиск в ней будет быстрым.
Код
#!/usr/bin/perl -ws

our ($create, $DB);
use DB_File;

die "
Usage: $0 [-DB=DB_File.db] -create t.txt
       $0 [-DB=DB_File.db] word1 word2 ...
" unless @ARGV || $create; 

my $db = $DB || 'DB_File.db';

die "No $db. Try\n$0 -create t.txt\n" if ! $create && ! -f $db;
unlink $db if $create;

tie %hash, "DB_File", $db or die "Can't open $db: $!\n";

if ($create) {
  while (<>) {
    if (s/^\s*(\d+\s+\d+)\s+//) {
      my $two_numbers = $1;
      while (m/\b(\w+)\b/g) {
        print "\r$.";
        $hash{$1} .= "$two_numbers|";
      }
    }
  }
  print "\nCreation $db done\n";
}
else {
  while (@ARGV) {
    my $key = shift;
    my $numbers = $hash{$key} || "";
    $numbers =~ s/\|/\n/g;
    print "$key\n$numbers\n";
  }
}
untie %hash;


PM MAIL   Вверх
yorc
Дата 27.12.2009, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 26.12.2009

Репутация: нет
Всего: нет



sir_nuf_nuf : спасибо за помощь!

запустил код на VDS с 800 MHz ядром + 1 Гб памяти
загрузка занимает в среднем 2,5 минуты

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

заметил только 3 момента, когда тестировал:

1. print $index{"DHIFFUSHI"}[1]."\n"; выдало 28 вместо 14. как видим:

Код

8    14    DHIFFUSHI
16    28    DHIFFUSHI (KAAFU ATOLL)


2. print $index{"CATHOLIC APOSTOLIC CHURCH"}[0]."\n"; выдало

Код

Use of uninitialized value in concatenation (.) or string at db.pl line 16, <$file> line 7482719.


В строке 16 при этом как раз:

Код

print $index{"CATHOLIC APOSTOLIC CHURCH"}[0]."\n";


3. print scalar (keys %index); выдаёт каждый раз разные результаты, далёкие от истины: 1930032, 1930033 и т.д.
это может быть связано с ограничением памяти на 1 процесс, я думаю...

вывод: чем заморачиваться с хэшами, лучше залью всё в БД!
была ещё мысль использовать биндинг memcached для перла
но это только если тесты на БД будут неудовлетворительными

задача же моя крайне критична по времени и ресурсам: обрабатываю текст, извлекаю слова, считаю определённые параметры исходя из данных таблицы. при этом всё делается на лету, планируется онлайн-сервис. скорость должна быть максимальной!

и тогда такой вопрос: что, по Вашему, будет быстрее, MySQL или, может, BerkeleyDB ? или PostgreSQL ?
PM MAIL   Вверх
Vaneska
Дата 28.12.2009, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 141
Регистрация: 15.3.2005
Где: Москва

Репутация: 3
Всего: 4



Цитата(yorc @  27.12.2009,  12:58 Найти цитируемый пост)
и тогда такой вопрос: что, по Вашему, будет быстрее, MySQL или, может, BerkeleyDB ? или PostgreSQL ? 

Быстрее всего будет BerkleyDB / memcachedb
Но если нужна нормальная сортировка, выборка, то лучще юзать какую-нибудь реляционную бд. ( mysql или postgresql )

Если нужно очень быстро, то использовать для этого списка BerkleyDB/memcached(b), а для хранения юзеров и т.д. реляционную.

Добавлено через 2 минуты и 46 секунд
Цитата(yorc @  27.12.2009,  12:58 Найти цитируемый пост)
заметил только 3 момента, когда тестировал:

Фразы эти лучше хешировать ( md5, sha1 ), тогда проблем не будет



--------------------
http://isokolov.blogspot.com/
PM MAIL ICQ   Вверх
sir_nuf_nuf
Дата 28.12.2009, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: 14
Всего: 31



Цитата(Vaneska @  28.12.2009,  19:28 Найти цитируемый пост)
Быстрее всего будет BerkleyDB / memcachedb
Но если нужна нормальная сортировка, выборка, то лучще юзать какую-нибудь реляционную бд. ( mysql или postgresql )

сдается мне - быстрее всего будет может быть grep. А если и не быстре - то проще всего.


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
Bulat
Дата 29.12.2009, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: 5
Всего: 57



yorc, я бы еще посоветовал почитать как ведут себя такие функции как substring, index.. регулярные выражения с текстовыми строками большого объема.. Ибо в перле есть не самое хорошее поведение, при работе с большими данными, когда окажется что памяти расходуется много больше чем предполагалось. smile


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
yorc
Дата 13.1.2010, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 26.12.2009

Репутация: нет
Всего: нет



решил проблему установкой Redis-сервера с Перл-биндингом

всем спасибо!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0957 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.