Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > медленная запись в файл


Автор: affendi 17.10.2011, 17:38
Доброго времени суток!

Следующая проблема с простейшей, вроде бы, операцией: есть таблица MySQL, в которой хранятся данные типа TEXT (размер поля = 10000, но на самом деле размер текста обычно не превышает 1000 символов) и их их идентификаторы (около 200 000 строк), а также  файл со списком идентификаторов (около 100 000 строк). Скрипт по идентификатору (регулярное выражение в коде возникло как попытка справиться с пробелами, возникшими при создании таблицы) вытаскивает из бд соответствующий текст и пишет его в файл. Первые 1.5 Мб записались за пару секунд, а далее скорость упала до 1Мб\час о_О. Последний факт навел на мысль, что проблема все-таки в записи, а не в БД.

Код

my $dbh = DBI->connect($dsn, $db_user_name, $db_password) or die "Can't connect";

my $sth = $dbh->prepare(q{select protein_sequence from cog where cog_id regexp ?
})or die "Failed to prepare selection: $!\n";

my @array;
my @seqarr;
my $regexp;
my $seq;

open FID, "cog_to_retrieve"
   or die "Failed to open cog_to_retrieve: $!\n";
open IN, ">cog_db.fasta"
   or die "Failed to open cog_db.fasta: $!\n";

while (my $line = <FID>){

    chomp($line);
    print IN ">gnl|COG|".$line."\n";
    $regexp = " *".$line." *";
    $sth->execute($regexp)or die "Failed to select $regexp from cog: $! at $line\n";
    @seqarr = $sth->fetchrow_array or die "Failed to fetch row $regexp from cog: $! at $line\n";
    
    if (length(@seqarr)>1){
        print "double!\n";
    }
    
              $seq = $seqarr[0];
    chomp($seq);
    print IN $seq."\n" or die "Failed to print: $! at $line\n";

}

close FID;
close IN;

print "done";
$dbh->disconnect;


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

Автор: vadiml 17.10.2011, 18:33
Если использование перла не является целью и есть доступ админа к базе, то можно поступить проще -- идентификаторы загнать в базу и выбрать всё одним запросом

mysql -u user tablespace -e 'select .... со всеми условиями и regexp-aми' > имя.файла

В большинстве случаев это работает быстрее, регулярки в mysql пишутся через REGEXP или RLIKE, и результат можно обработать как угодно.

Автор: affendi 17.10.2011, 20:20
vadiml: в этом конкретном скрипте использование перла самоцелью не является, но мне таки вскоре придется проводить запись многабукв в файл именно из перла, и хотелось бы сейчас понять, что же я делаю не так.. Впрочем, спасибо за совет, попробую.

Автор: dmitryk1 18.10.2011, 04:29
Я бы предложил тебе поотлаживать и посмотреть где именно происходят тормоза. 
Во первых сделай вывод не в файл, а на экран и посмотри, увеличится ли скорость. Во вторых расставь отладочные выводы на экран и посмотри, какие операции занимают много времени. 

Я могу предположить что у тебя тормозит регексп в запросе. Хотя может и винт дохнет smile

Автор: vivu 25.10.2011, 11:46
Странный у вас способ работы с БД. Всё равно что микроскопом гвозди забивать. Узкое место у вас в базе данных. Она не предназначена для полнотекстового поиска. 

У вас два варианта:
1. Выгрузить данные из таблицы в файл, а дальше работать с файлами, использую Tie::File. Крайне желательно ключи держать в памяти, чтобы минимизировать обращение к файлам.
2. Загрузить данные со списком идентификаторов в базу данных. Но это только если все ключи можно чётко идентифицировать с записями из первой таблицы.

Автор: affendi 31.10.2011, 12:36
Спасибо за наводки, проблема решилась простой индексацией поля, содержащего идентификатор)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)