本帖最后由 chenhao392 于 2013-05-01 09:17 編輯
數(shù)據(jù)描述:
1. 700萬條長短不一的string,每一個(gè)都有uniq name。
2. 大多數(shù)比較短,有些很長 (1Mb+)3. 總共 4Gb +
生物信息注釋: 一個(gè)基因組,很多染色體片段。 sample:
seq1: AAAAAAAAAAA
seq2: BBBBBBBBBBB
需求:
用戶提供,
1) string name (如seq1)
2) 起始和結(jié)束的位置,如 (20, 60)
server快速返回substring,并在網(wǎng)頁上顯示。
硬件:
webserver: 2個(gè) CPU,2G內(nèi)存, FC18, LAMP 網(wǎng)站。
其他電腦支持: 16 CPU, 48Gb 內(nèi)存, linux.
我的嘗試:
mysql 直接存儲一個(gè)大表,通過內(nèi)建的length 計(jì)算原string長度,修改用戶的input,之后通過substr拿到substring。
現(xiàn)在是拿PHP寫的,結(jié)果需要等待1分鐘以上。因?yàn)榍岸耸茿JAX的,感覺不可忍。
設(shè)想方案:
由于webserver的內(nèi)存和CPU都比較一般。我想是不是可以寫一個(gè)perl 的CGI。用
Storable (http://search.cpan.org/~ams/Storable-2.24/Storable.pm), BerkeleyDB(http://search.cpan.org/~pmqs/BerkeleyDB-0.51/BerkeleyDB.pod.P)
這一類的module 將整個(gè)關(guān)聯(lián)數(shù)組/hash ,寫到硬盤上。再利用perl的substr 提取string 片段。
問題:
1. 請問這樣是否能提高效率呢?
用內(nèi)存時(shí),用hash搜索string的name,應(yīng)該是不耗時(shí)間的,substr似乎也夠快。問題在于,4G的數(shù)據(jù),寫了hash存硬盤,會影響效率么?
2. 或者有沒有更好的想法?
感謝閱讀和任何想法:)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 更新:問題已經(jīng)解決.
感謝樓上的朋友們的建議,測試訪問速度基本瞬時(shí)了,1s以內(nèi)。 然后,我并不要求并發(fā)數(shù).
to iamlimeng: 數(shù)據(jù)是相對固定的,分割小文件也絕對會加快速度,謝謝。只是現(xiàn)在的大文件已經(jīng)讓我滿足了。
to laputa73: 48G的電腦可以幫忙計(jì)算數(shù)據(jù),不能對外訪問。感謝告知redis的存在,我沒有用單純是不想花時(shí)間學(xué)redis,就寫了個(gè)perl. 事實(shí)上還是用DB_File 存儲hash來實(shí)現(xiàn)快速搜索,所以,一定意義上也算 “鍵值”數(shù)據(jù)庫吧 :)
to soul20040103: 感謝建議。其實(shí)昨天我面對的主要的問題是mysql中substr的效率問題,之后想到perl的substr,但是擔(dān)心perl里面大文件訪問也影響速度,抱歉沒有表達(dá)清楚。
to Perlvim: 事實(shí)證明通過結(jié)合Berkeley DB和Perl的substr,我實(shí)現(xiàn)了需求。 DB_File 是Berkeley DB的interface。 http://search.cpan.org/~pmqs/DB_File-1.827/DB_File.pm#Opening_a_Berkeley_DB_Database_File 然后,今天所有代碼都是通過vim 寫的:)
to anyevent: 其實(shí)就是花在計(jì)算string的長度和截取片段上了。那些短片段多為無用的junk,但是不好舍棄。一般來說,大的片段上才含有完整的基因,我其實(shí)想要實(shí)現(xiàn)的是,給出一個(gè)基因的位置,拿到基因本身,以及其左右一定長度的序列。感謝告知elasticsearch, 我也見過一個(gè)有趣的應(yīng)用,叫tableau. 圖像化data的。 http://www.tableausoftware.com/products
具體代碼:
Step 1. 我利用DB_File module 將整個(gè)大表寫成文件,代碼如下: - #!/usr/bin/perl
- #
- use strict;
- use warnings;
- use DB_File;
- my %hash;
- tie (%hash, "DB_File","wheatA_genome.db") or die "$!\n";
- open FILE, "<$ARGV[0]" or die "$!\n";
- while(<FILE>){
- chomp;
- my($id,$seq)=split(/\t/,$_);
- $hash{$id}=$seq;
- }
- close FILE;
復(fù)制代碼Step 2. 我在server端寫了個(gè)perl 的CGI - #!/usr/bin/perl
- use strict;
- use warnings;
- use DBI;
- use DB_File;
- use CGI qw/param/;
- #parameter
- my $str=param('q');
- my $flank=param('f');
- #mysql
- my $db = "DBI:mysql:wheat_database:localhost;mysql_socket=/var/lib/mysql/mysql.sock";
- my $user_name = "****";
- my $password = "****";
- my ($dbh,$sth,$scaf,$start,$end,$genome);
- my @result;
- $dbh=DBI->connect($db,$user_name,$password, {RaiseError => 1});
- &mysql($str,"A");
- &mysql($str,"D");
- $dbh->disconnect();
- #header
- print "Content-type:text/html\n\n";
- my %hash;
- tie(%hash,"DB_File","wheat".$genome."_genome.db" ) or print "$!\n";
- if(defined $hash{">".$scaf}){
- my $length=length($hash{">".$scaf});
- $start-=($flank+1);
- $end+=$flank;
- if($start <0 ){ $start=0;}
- if($end >=$length){ $end=$length;}
- my $seq_length=$end-$start;
- my $result=substr($hash{">".$scaf},$start,$seq_length);
- print " <textarea name='wheat_scaf_seq' rows='5' cols='120'>";
- print ">$scaf:$start-$end\n$result\n";
- print "</textarea>";
- }
- else{
- print "<h3>not found!</h3>";
- }
- sub mysql{
- my ($gene_id,$genome_guess)=@_;
- $sth=$dbh->prepare("SELECT * FROM wheat".$genome_guess."_gene_info WHERE wheat".$genome_guess."_id like '%".$gene_id."%'");
- $sth->execute();
- my @array=$sth->fetchrow_array();
- if (@array >0){
- $scaf=$array[3];
- $start=$array[4];
- $end=$array[5];
- $genome=$genome_guess;
- }
- $sth->finish();
- }
復(fù)制代碼
參考javascript- function show_wheat_scaf_seq(){
- var str=document.getElementById('q').value;
- var flank=document.getElementById('f').value;
- if (str=="" || flank ==""){
- document.getElementById("wheat_scaf").innerHTML="";
- return;
- }
- if (window.XMLHttpRequest){
- // code for IE7+, Firefox, Chrome, Opera, Safari
- xmlhttp=new XMLHttpRequest();
- }
- else{
- // code for IE6, IE5
- xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
- }
- xmlhttp.onreadystatechange=function(){
- if (xmlhttp.readyState==4 && xmlhttp.status==200){
- document.getElementById("wheat_scaf").innerHTML=xmlhttp.responseText;
- }
- }
- xmlhttp.open("GET","wheat_search.pl?q="+str+"&f="+flank,true);
- xmlhttp.send();
- }
復(fù)制代碼 |