Я Paginator::Lite использовал, работает. Хочу только обратить внимание на возможную проблему производительности. Если у вас 1 млн элементов, которые вы разбиваете на 100 000 страниц по 10 элементов, то ваш сайтик может ощутимо тормозить за счет LIMIT-запросов. Эффективнее писать "Перейти к следующей/предыдущей странице", используя для выборки primary key или иное проиндексированное поле первого элемента выборки. Тогда ваши запросы превращаются в быстрые SELECT ... WHERE key >= $key LIMIT 10
Кстати, может кто-нибудь пробовал оптимизировать такие запросы? Удавалось найти хорошее решение? Ну, например, если данные обновляются редко, можно раз в сутки рассчитывать по крону, на какой странице какие элементы отображать. 23 апреля 2012 г. 20:26 пользователь Alessandro Gorohovski < [email protected]> написал: > oleg alexeenkov <[email protected]> писал(а) в своём письме Mon, 23 Apr > 2012 19:11:11 +0300: > > > Alessandro Gorohovski <[email protected]> писал(а) в своём письме >> Mon, 23 Apr 2012 19:58:41 +0400: >> >> Andrew Shitov <[email protected]> писал(а) в своём письме Mon, 23 Apr 2012 >>> 18:49:39 +0300: >>> >>> http://search.cpan.org/search?query=pagination&mode=all >>>> ? >>>> >>> >>> > Олег, > Спасибо большое! > :) > > Любопытный код. Буду ковыряться. > > > > >> [вброс] давным давно наковырял такую штуку, работает с миллиардами >> страниц 8) причем скорее всего путь перехода со страницы X на страницу Y >> будет наименьшим среди аналогов (особенно если подкрутить параметры) >> >> sub gotopage { >> my ($fparam) = @_; >> my (%ret); >> #$fparam->{'total'} : total results, usually COUNT(*) as total >> #-----------size -- : size of one page in rows (LIMIT x,size) >> #current : current page number >> #actual : usually $DBI::rows, if total unknown >> #last : last page number (auto calculated from total/size if 0) >> #total_max = 1000 : maximum db results >> #printlog('dmp', 'gotopage start:', Dumper($fparam)); >> $fparam->{'size'} = 100 unless defined $fparam->{'size'}; >> return {} unless $fparam->{'size'}; >> $fparam->{'actual'} = $fparam->{'size'} unless defined >> $fparam->{'actual'}; >> $fparam->{'current'} ||= 1; >> $fparam->{'last'} ||= >> $fparam->{'size'} < 1 >> ? undef >> : ( int( $fparam->{'total'} / ( $fparam->{'size'} || 1 ) ) + ( >> $fparam->{'total'} % ( $fparam->{'size'} || 1 ) ? 1 : 0 ) ); >> $fparam->{'buttonsb'} ||= $config{'gotopage_bb'} || 5; #before >> $fparam->{'buttonsa'} ||= $config{'gotopage_ba'} || 5; #after >> $fparam->{'align'} = 1 unless defined $fparam->{'align'}; >> $fparam->{'jumpten'} = 1 unless defined $fparam->{'jumpten'}; >> $fparam->{'power'} = 2 unless defined $fparam->{'power'}; >> my $fromto = sub { >> my ($n) = @_; >> return ( >> ( ( ( $n - 1 ) * $fparam->{'size'} ) + 1 ) . '-' >> . ( >> ( $fparam->{'total'} and ( $fparam->{'total'} < $n * >> $fparam->{'size'} ) ) ? $fparam->{'total'} : $n * $fparam->{'size'} >> ) >> ); >> }; >> my $align = sub { >> my $a = int(shift); >> my $len = shift || $fparam->{'align'}; >> substr( $a, $len, length($a) - $len ) = '0' x ( length($a) - $len ) >> if $len > 0 and length($a) > $len; >> return $a; >> }; >> #printlog('dmp', 'gotopage calc:'," <br\n/>" .Dumper($fparam) . >> "<br\n/>"); >> my $next = $fparam->{'actual'} >= $fparam->{'size'}; >> if ( ( !$fparam->{'total'} and $fparam->{'actual'} > 0 ) >> or $fparam->{'total'} >= $fparam->{'size'} >> or $fparam->{'current'} > 1 ) >> { >> $ret{'prev'}{ $fparam->{'current'} - 1 } = $fromto->( >> $fparam->{'current'} - 1 ) if $fparam->{'current'} > 1; >> for my $n ( ( $fparam->{'current'} > $fparam->{'buttonsb'} ? >> $fparam->{'current'} - $fparam->{'buttonsb'} : 2 ) >> .. $fparam->{'current'} + ( $next ? $fparam->{'buttonsa'} : 0 ) ) >> { >> last if $fparam->{'total'} and $n > $fparam->{'last'}; >> last if $fparam->{'total_max'} and $n * $fparam->{'size'} > >> $fparam->{'total_max'}; >> ( ( !$fparam->{'total'} and $n > $fparam->{'current'} + 1 ) ? ( \%{ >> $ret{'small'} } ) : ( \%{ $ret{'big'} } ) )->{$n} = >> $fromto->($n); >> } >> if ( $fparam->{'jumpten'} ) { >> $fparam->{'jumpfrom'} ||= '1' . ( 0 x ( length( >> $fparam->{'current'} - $fparam->{'buttonsb'} ) - 1 ) ); >> $fparam->{'jumpto'} ||= '1' . ( 0 x length( $fparam->{'current'} + >> $fparam->{'buttonsa'} ) ); >> $ret{'big'}{$_} = $fromto->($_) >> for grep { !$fparam->{'last'} or $_ <= $fparam->{'last'} } >> map { '1' . ( 0 x $_ ) } 1 .. length( $fparam->{'current'} ) - 1; >> if ($next) { >> $ret{'big'}{$_} = $fromto->($_) >> for map { '1' . ( 0 x $_ ) } length( $fparam->{'current'} ) .. >> length( $fparam->{'last'} ) - 1; >> } >> } >> $fparam->{'jumpfrom'} ||= 1; >> $fparam->{'jumpto'} ||= $fparam->{'last'}; >> #$fparam->{'jumpto'} = psmisc::min( $fparam->{'jumpto'}, >> $fparam->{'last'} ); >> $fparam->{'jumpto'} = $fparam->{'last'} if $fparam->{'last'} < >> $fparam->{'jumpto'}; >> if ( $fparam->{'power'} > 1 ) { >> my ($n); >> $n = $fparam->{'current'} - $fparam->{'buttonsb'} * >> $fparam->{'power'}; >> for ( >> $_ = $fparam->{'buttonsb'} ; >> $fparam->{'jumpfrom'} >= 1 and $n > $fparam->{'jumpfrom'} and $n >> < $fparam->{'last'} ; >> $n -= ( $_ *= $fparam->{'power'} ) >> ) >> { >> $ret{'big'}{ $align->($n) } = $fromto->( $align->($n) ); >> } >> $n = $fparam->{'current'} + $fparam->{'buttonsa'} * >> $fparam->{'power'}; >> for ( $_ = $fparam->{'buttonsa'} ; $next and $n < >> $fparam->{'jumpto'} ; $n += ( $_ *= $fparam->{'power'} ) ) { >> $ret{'big'}{ $align->($n) } = $fromto->( $align->($n) ); >> } >> } >> $ret{'big'}{ $fparam->{'last'} } = $fromto->( $fparam->{'last'} ) if >> $fparam->{'last'} > 1 and $next; >> $ret{'big'}{1} ||= $fromto->(1) >> if ( $fparam->{'last'} > 1 or !$fparam->{'total'} ) >> and $fparam->{'actual'} >= $fparam->{'size'}; >> $ret{'next'}{ $fparam->{'current'} + 1 } = $fromto->( >> $fparam->{'current'} + 1 ) >> if $next and !$fparam->{'last'} >> or $fparam->{'current'} < $fparam->{'last'}; >> } >> #printlog('dmp', 'gotopage ret:', Dumper(\%ret)); >> return wantarray ? ( sort { $a <=> $b } keys %{ $ret{'big'} }, keys %{ >> $ret{'small'} } ) : \%ret; >> } >> > -- > Moscow.pm mailing list > [email protected] | http://moscow.pm.org > -- С уважением, Александр Личный блог: http://eax.me/ Мой форум: http://it-talk.org/ Мой Twitter: http://twitter.com/afiskon
-- Moscow.pm mailing list [email protected] | http://moscow.pm.org
