Уменьшите вызовы DBI :: common :: Fetch (Perl) - PullRequest
1 голос
/ 28 марта 2012

Я пытался сократить время выполнения программы, которую я создал.

Я использовал Profiler, который сказал мне, что 63% времени было потрачено на DB :: st :: execute. Затем я запустил DBI Profiler и выяснил, какие из моих вызовов были самыми длинными:

+ 1 SELECT Gene FROM genotypegene WHERE Genotype like ?
= 754 0.163602352142334 0 0 0.0156009197235107 1332756184.24322 1332756184.74384

Я изменил количество звонков с 754 до 14:

+ 1 SELECT Gene FROM genotypegene WHERE Genotype like ?
= 14 0.00399994850158691 0 0 0.00100016593933105 1332923220.99416 1332923221.70477

Однако скорость программы значительно не увеличилась, и мой профилировщик теперь говорит, что 100% расходуется на DBI :: common :: FETCH. Я не уверен, к какому методу это относится.

До того, как я отредактировал свою программу, чтобы сократить количество вызовов «SELECT Gene», он сказал, что DBI :: common :: FETCH занимал 0,000003 с / вызов, тогда как теперь он принимает 4,467 ... с / вызов. Почему DBI :: common :: FETCH теперь занимает намного больше секунд / вызовов, чем раньше? (Единственное, что я заметил между двумя профилями, это то, что в исходном профиле был вызов, к которому новый профиль больше не имеет. Если я смотрю на Профиль во время работы программы, он вызывает только один вызов, но это увеличивает во время выполнения программы)

Спасибо!

Редактировать: вот таблица, из которой я выбираю (вставьте сюда для удобства чтения, чем в части комментариев):

CREATE TABLE genotypegene
(
Genotype VARCHAR(20),
Gene VARCHAR(20),
FOREIGN KEY (Genotype) REFERENCES genotype(Genotype),
FOREIGN KEY (Gene) REFERENCES gene(Gene)
)ENGINE=InnoDB;

Редактировать 2:

Поля для профиля DBI здесь: http://metacpan.org/pod/DBI::Profile#Report-Format

Причина, по которой я смог перейти с 700 ~ 14, заключается в моей неопытности программиста (самоучка, я начал использовать perl только 3 месяца назад). Первоначально я вызывал информацию из базы данных каждый раз, когда мне это было нужно (поэтому вызывал одну и ту же информацию более одного раза). Как только я увидел, что это замедляет работу программы, я изменил ее так, чтобы она вызывала необходимую мне информацию при запуске программы, а затем сохраняла ее в хеше. Я тогда ожидал, что это ускорит программу, которая у нее есть, но не так сильно, как ожидалось. Вот почему я был удивлен 4.4secs для DBI :: common :: Fetch, так как раньше он никогда не был таким медленным, и, насколько мне известно, я ничего не изменил в программе, которая должна сделать этот вызов таким медленным

Это Профиль развития для отредактированной программы:

%Time    Sec.     #calls   sec/call  F  name
100.00 386198925.3409  86442494   4.467698     DBI::common::FETCH
 0.00 15263.1450  21928855   0.000696     DBI::st::execute

(перечислены и многие другие функции, только некоторые из них, которые вас интересуют)

и вот до того, как его отредактировали:

%Time    Sec.     #calls   sec/call  F  name
65.01 8767.3435  21766318   0.000403     DBI::st::execute
2.29  309.2408  86510899   0.000004     DBI::common::FETCH
11.52 1554.1823        0  1554.182323  *  <other>

(расхождение между 65% и 63% связано с тем, что этот прогон программы отличается от того, который я упоминал в начале, но он примерно такой же)

1 Ответ

2 голосов
/ 28 марта 2012

После просмотра вашей базы данных я бы предложил 2 вещи на основе ваших запросов.

i) Вы используете запросы LIKE для сопоставления строк, поэтому создайте INDEX для столбца GENOTYPE, который даст повышение производительности.

ii) Попробуйте использовать механизм MyIsam и механизм FULL TEXT для столбца GENOTYPE, в зависимости от того, какие совпадения вы выполняете со строками столбца.

Ваши запросы как:

а) SELECT Gene FROM genotypegene WHERE Genotype like 'YYY%' (starts with )

или

б) SELECT Gene FROM genotypegene WHERE Genotype like '%YY%' (contains )

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

...