1、如何解決網站分頁導致的SEO問題?
一、網站分頁對SEO優化的影響
1、大量重復內容,頁面標題與URL意義多樣化。
2、頁面圖片ALT屬性的確定與添加,網頁載入伺服器可能加大負載。
3、增加用戶的無效點擊,頁面停留時間短,跳出率高。
4、頁面核心內容相關性與下一頁承載關系容易混亂,會導致索引擎抓取收錄出錯。
5、分頁會導致分散鏈接,錨文本,PageRank的目標頁面指向,讓搜索引擎不好判斷第幾頁作為權重傳遞頁面。
二、解決網站分頁SEO優化問題的方法技巧
1、由於分頁產生的大量重復內容,特別是在網頁標題上的重復是最明顯的,例如我們使用比較多的程序dedeCMS和wordpress都會遇到分頁的這個問題,雖然有不少朋友會注意到這個問題,但是還是有不少網站會忽略了這個問題。
當然,這一點可能有點吹毛求疵,但是要想為了網站的長遠發展,這些細節也是需要我們多加註意的,對於這個問題,其解決思路很簡單,那就是讓每個頁面標題產生差異性,在此,建議大家可以將標題可以書寫為「欄目標題+第幾頁+網站標題」,對於正在使用織夢CMS後台管理系統欄目列表分頁的解決方案就是修改成以下調用代碼:
{dede:field.title/}{dede:pagelist listitem=」pageno」 listsize=」0″ function=」html2text(@me)」 runphp=」yes」}if (strlen(@me)>10 || @me==1) @me=」";else @me=」 – 第」.str_replace(『 『,」,@me).」頁」;{/dede:pagelist} – {dede:global.cfg_indexname/}
而對於wordpress來說一個很好的解決方案就是使用All in One SEO Pack插件,至於其他的後台管理程序系統我還沒有發現更好的解決方案,等有了比較利於seo優化的方法,我會上跟大家再分享的。
2、針對「頁面圖片ALT屬性的確定與添加,網頁載入伺服器可能加大負載。」的問題。這就不得不說下一些圖片網站了。因為分頁用到最多的就是圖片資訊,這裡面涉及到兩個問題,一個分頁造成工作人員的工作量有可能增加,另外,雖然單頁的載入速度加快了,但是卻佔了網站伺服器的大量存儲,太多這樣的頁面必然會對網站的性能造成影響,而性能優化是對網站在硬體上的基本要求了,關於這方面我在此就不多說了,對於具體如何提高網站速度這塊。
3、通常,我們會希望用戶著陸頁在分頁的「第一頁」的頁面上,而不是在中間的第二頁第三頁上。實際情況是你可能會發現一些頁面關鍵詞排名良好的是分頁裡面的某一個頁面,而不是你選擇的那個著陸頁。如果這些目標排名網頁不能滿足用戶查詢需求,這將影響網站的點擊率和跳出率。
而針對用戶的無效點擊和停留時間,跳出率高的問題,由於完全需要根據用戶的喜好,而且搜索引擎對於這一部分的演算法也是非常模糊的,我們不知道度如何控制跳出率,讓網頁更符合搜索引擎的要求,這里的不可控性因素太強,所以我們在這一點上唯一可做的就是討好用戶,通過精美的內容來吸引用戶停留,個人覺得可以參考的有三點:
(1)、內容充實,排版清晰,為用戶減少閱讀負擔;
(2)、圖片精美,在圖片上吸引用戶點擊和停留;
(3)、站內的引導,避免流量直接跳出損失。
4、對於「頁面核心內容相關性與下一頁承載關系容易混亂,會導致索引擎抓取收錄出錯。」的問題,目前還都沒有比較好的方法來解決,尤其是頁面核心內容的分頁,其實是很難把控的,因為你不知道切分出來的哪個頁面真正能符合網頁核心主旨,也不知道搜索引擎會如何去抓取收錄這幾個頁面,而且更值得注意的是這些分頁的頁面必然會形成一定的內部競爭,最終展現給用戶在搜索引擎結果中的也可能會有一定的問題。四合裝飾
所以目前百度搜索引擎對此也是根據詞頻提取的演算法來展現內容的,這就像大家經常在百度搜索出來網站和文章標題,其展示的描述卻不定是站長和SEOer所填寫的那些。對此問題的解決方法,建議就是能不分頁的內容就盡量不要分頁,而對於核心內容的展示,盡量多注意一下核心關鍵詞的密度。
在一些情況下,如果文章內容確實太長,不方便閱讀,必須要分頁的話,可以使每一段都圍繞著一個核心點,可獨立支撐起一個頁面內容量的情況下可以考慮分頁使用。
5、對於「分頁會導致分散鏈接,錨文本,PageRank的目標頁面權重」的問題,我們就要先說一下網站的內鏈了,內鏈在網站內部的作用有兩大方面,一方面內部鏈接是為了搜索引擎蜘蛛抓取網頁一個入口,更多的入口帶來更多的抓取機會,只有網頁收錄了才有獲得排序的機會,不收錄的網頁都是資源的浪費,所以提高網站的收錄比例比單純做網站的收錄量提升更具優勢。
另一方面是基於pagerank的原理為其他的鏈接頁面做權重傳遞,如果這里分頁之後把一個頁面的權重分散給了這幾個頁面,而這幾個頁面中加起來的鏈接總數肯定要多很多,那麼最終傳遞的權重可能只有一小部分了,雖然這種理論的東西都只是猜測,但仔細思考也有點道理的。而且我們不能夠確定哪個頁面權重更高,最終像第4點中提到的一樣,百度確定不了網頁的核心主題,需要自己分析,那麼就可能和自己的初衷產生偏差。
對此問題的解決,有朋友說在網頁上加入canonical可以確定網頁的唯一性,但是我們在百度站長平台LEE的回答中發現百度其實目前不支持canonical的,希望如他所說,未來會加入canonical,這樣便於方便搜索引擎對於權重頁面抓取,從而更能集中鏈接,錨文本,PageRank的目標頁面指向。
寫在最後:對於網站分頁的問題,目前還很難絕對的說是好?還是壞?但筆者卻注意到在最近的一年內,對此問題解決的趨勢是利用滾動代替分頁了,目前許多互聯網內容服務展現樣式都在改變。如谷歌圖片搜索,Facebook和Twitter現在使用(AJAX)作為替代技術,來實現用戶向下滾動頁面自動快速載入更多其他新內容。相信在2014年內,此趨勢的發展將會更加的普遍。
2、php 分頁類怎麼用啊?
<?php
class Page {
private $total_rows;//資料庫總條數
private $per_page_rows;//每頁顯示條數
private $limit;
private $uri;
private $total_pages;//總頁數
private $config=array("header"=>"記錄條數","prev"=>"上一頁","next"=>"下一頁","first"=>"首 頁","last"=>"尾 頁");
private $list_length=8;
public function __construct($total_rows,$per_page_rows=10,$url_args){
$this->total_rows=$total_rows;
$this->per_page_rows=$per_page_rows;
$this->uri=$this->get_uri($url_args);
$this->page = !empty($_GET['page']) ? $_GET['page'] : 1;
$this->total_pages=ceil($this->total_rows/$this->per_page_rows);
$this->limit=$this->set_limit();
}
private function set_limit() {
return "limit ".($this->page-1)*$this->per_page_rows.",{$this->per_page_rows}";
}
private function get_uri($url_args) {
$url=$_SERVER["REQUEST_URI"].(strpos($_SERVER["REQUEST_URI"],"?") ? "" : "?").$url_args;
$parse=parse_url($url);
if (isset($parse['query'])) {
parse_str($parse['query'],$params);//把url字元串解析為數組
unset($params['page']);//刪除數組下標為page的值
$url=$parse['path'].'?'.http_build_query($params);//再次構建url
}
return $url;
}
public function __get($args) {
if ($args=="limit") {
return $this->limit;
}else{
return null;
}
}
private function start_page(){
if ($this->total_rows==0) {
return 0;
}else{
return (($this->page-1)*$this->per_page_rows)+1;
}
}
private function end_page(){
return min($this->page*$this->per_page_rows,$this->total_rows);
}
private function go_first() {
$html="";
if ($this->page==1) {
$html.=" {$this->config['first']} ";
}else{
$html.=" <a href='{$this->uri}&page=1'>{$this->config['first']}</a> ";
}
return $html;
}
private function go_prev() {
$html="";
if ($this->page==1) {
$html.=" {$this->config['prev']} ";
}else{
$html.=" <a href='{$this->uri}&page={$this->page}-1'>{$this->config['prev']}</a> ";
}
return $html;
}
private function go_next() {
$html="";
if ($this->page==$this->total_pages) {
$html.=" {$this->config['next']} ";
}else{
$html.=" <a href='{$this->uri}&page={$this->page}+1'>{$this->config['next']}</a> ";
}
return $html;
}
private function go_last() {
$html="";
if ($this->page==$this->total_pages) {
$html.=" {$this->config['last']} ";
}else{
$html.=" <a href='{$this->uri}&page={$this->total_pages}'>{$this->config['last']}</a> ";
}
return $html;
}
private function go_page() {
return ' <input type="text" onkeydown="javascript:if(event.keyCode==13){var page=(this.value>'.$this->total_pages.')?'.$this->total_pages.':this.value;location=''.$this->uri.'&page='+page+''}" value="'.$this->page.'" style="width:25px;" /><input type="button" onclick="javascript:var page=(this.previousSibling.value>'.$this->total_pages.')?'.$this->total_pages.':this.previousSibling.value;location=''.$this->uri.'&page='+page+''" value="GO" /> ';
}
private function page_list() {
$link_page="";
$i_num=floor($this->list_length/2);
for ($i = $i_num; $i >= 1; $i--) {
$page=$this->page-$i;
if ($page<1) {
continue;
}else{
$link_page.=" <a href='{$this->uri}&page={$page}'>{$page}</a> ";
}
}
$link_page.=" {$this->page} ";
for ($i = 1; $i < $i_num; $i++) {
$page=$this->page+$i;
if ($page<=$this->total_pages) {
$link_page.=" <a href='{$this->uri}&page={$page}'>{$page}</a> ";
}else{
break;
}
}
return $link_page;
}
public function out_page($display=array(0,1,2,3,4,5,6,7,8)) {
$display_html='';
$html[0]=" 共有<b>{$this->total_rows}</b>{$this->config['header']} ";
$html[1]=" 每頁顯示<b>".($this->end_page()-$this->start_page()+1)."</b>條,本頁顯示從<b>{$this->start_page()}</b>--<b>{$this->end_page()}</b>{$this->config['header']} ";
$html[2]=" <b>{$this->page}</b>/<b>{$this->total_pages}</b>頁 ";
$html[3]=$this->go_first();
$html[4]=$this->go_prev();
$html[5]=$this->page_list();
$html[6]=$this->go_next();
$html[7]=$this->go_last();
$html[8]=$this->go_page();
foreach ($display as $index){
$display_html.=$html[$index];
}
return $display_html;
}
}
?>
3、如何用php實現分頁效果
將原代碼(所有用到分頁的代碼我都加有注釋)和設計頁面和IE瀏覽後的頁面都傳給你,以方便你詳查。如果這里不好看,就將此代碼復制到Dreamweaver編輯器里,加上你自己的資料庫。我不知道你用的是什麼編輯器,我用的是Dreamweaver。 這里是原代碼頁面<?php
include("inc/conn.php"); //包含你的資料庫文件
?><body>
<?php
$sql="select * from book"; //sql語句我就不用多講了吧,其中book是我要連接的表,(可自己定義)後面將不作解釋
$result=mysql_query($sql);
$number=mysql_num_rows($result); //獲得總共多少條記錄
$pagesize=10; //定義每個頁面要顯示多少條記錄
$totalpage=ceil($number/$pagesize); //獲得總的頁數,ceil($number/$pagesize)總的記錄/每頁顯示的記錄
$pageno=$_GET['pageno'];
if($pageno==""){
$pageno=1; //設定,如果當前頁為空時就顯示為第1頁
}
$startno=$pagesize*($pageno-1); //得到每頁的起始頁。$pagesize*($pageno-1)用每頁多少條記錄*(當前頁-1),這是得到起始頁的規則
$sql2="select * from book limit ".$startno.",".$pagesize; //用sql2語句中limit得出每一頁的起始頁和每一頁要顯示多少條記錄
$result2=mysql_query($sql2);
?>
<table width="600" border="0" align="center" cellpadding="5" cellspacing="1" bgcolor="#0000FF">
<tr>
<th align="center" bgcolor="#FFFFFF">書名:</th>
<th align="center" bgcolor="#FFFFFF">作者:</th>
<th align="center" bgcolor="#FFFFFF">價格:</th>
</tr>
<?php
while($rows=mysql_fetch_array($result2)){ //這里是循環,不用講的吧,如果不懂再來問我
?>
<tr>
<td align="center" bgcolor="#FFFFFF"><?php echo $rows['Bookname']?></td>
<td align="center" bgcolor="#FFFFFF"><?php echo $rows['editor']?></td>
<td align="center" bgcolor="#FFFFFF"><?php echo $rows['price']?></td>
</tr>
<?php } ?>
<tr>
<td align="center" bgcolor="#FFFFFF">共<?php echo $number //顯示總共多少條記錄 ?>條記錄</td> <td align="center" bgcolor="#FFFFFF"><?php
if($pageno==1){
echo "[<a href=?pageno=".($pageno+1).">下一頁</a>][<a href=?pageno=".$totalpage.">末頁</a>]";
} //如果是第一頁時: 沒有首頁和上頁,只有下頁和末頁(後兩者有連接)
if($pageno<$totalpage && $pageno>1){
echo "[<a href=?pageno=1>首頁</a>][<a href=?pageno=".($pageno-1).">上一頁</a>][<a href=?pageno=".($pageno+1).">下一頁</a>][<a href=?pageno=".$totalpage.">末頁</a>]";
} //如果是第一頁和末頁之間的頁數:首頁,上頁,下頁,末頁都有(四者都有連接)
if($pageno==$totalpage){
echo "[<a href=?pageno=1>首頁</a>][<a href=?pageno=".($pageno-1).">上一頁</a>]";
} //如果是末頁時: 只有首頁和上頁,沒有下頁和末頁(前兩者有連接) (到此為止分布做完了,下面的是跳轉,順便也跟你說說吧,呵呵)
?></td>
<td align="center" bgcolor="#FFFFFF"><form id="form1" name="form1" method="get" action="">
<select name="pageno">
<option selected="selected">第<?php echo $pageno?>頁</option>
<?php
for($i=1;$i<=$totalpage;$i++){ //通過for定義變數i<=總頁數將總共有多少頁循環出來
?>
<option value="<?php echo $i?>">第<?php echo $i //顯示當前所看到的頁數?>頁</option>
<?php } ?>
</select>
<input type="submit" name="Submit" value="go" />
</form>
</td>
</tr>
</table>
</body> 這里是設計頁面 這里是IE瀏覽後看到的頁面
4、找個簡單實用的php分頁類30分
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>通訊錄</title>
<script type="text/javascript">
function onsure(url){
var sure = confirm("確定要刪除?");
if(sure){
location.href = url;
}else{
return false;
}
}
</script>
<style>
a{padding:5px 10px; border:1px solid #ccc; background-color:#EEE; text-decoration:none;}
a:hover{background-color:#ccc;}
</style>
</head>
<body>
<?php if(!empty($_SESSION['user'])){ ?>
<marquee>你好,歡迎"<?php echo $_SESSION['user'] //$_COOKIE['user'] ?>"回來!<a href="unset.php">安全退出</a></marquee>
<?php } ?>
<table width='100%' border=1>
<caption align="top"><h1>通訊錄</h1></caption>
<tr>
<th colspan=7>
<form action="index.php" method="get">
<input type="text" name="key" value="<?php echo $_GET['key'] ?>" />
<input type="submit" value="查詢" />
</form>
</th>
</tr>
<tr>
<th>用戶名</th>
<th>性別</th>
<th>愛好</th>
<th>地址</th>
<th>手機</th>
<th>座機</th>
<?php if(!empty($_SESSION['user'])){ ?>
<th>操作</th>
<?php } ?>
</tr>
<?php
include "connect.php";
/********查詢***********/
#獲取查詢關鍵字
$key = $_GET['key'];
#求記錄總數
$sql = "select count(*) from user where user like '%$key%'";
$query = mysql_query($sql);
$row = mysql_fetch_row($query);
$countnum = $row[0];
#每頁顯示的記錄數
$numrows = 3;
#總頁數
$countPage = ceil($countnum/$numrows);
#當前頁
$page = intval($_GET['page']) > 0 ? intval($_GET['page']) : 1;
#控制分欄頁碼
$sort = 5;
#求開始頁碼
$half = intval($sort/2);
if($countPage <= 5 || $page <= $half ){
$start = 1;
}else{
$start = $page - $half;
}
#求結束頁碼
if($countPage <= 5 || $page+$half > $countPage){
$end = $countPage;
}else{
$end = $start + $sort - 1;
}
#求出偏移量
$offset = ($page - 1) * $numrows;
$sql = "select * from user where user like '%$key%' limit $offset,$numrows";
$query = mysql_query($sql);
while($val = mysql_fetch_assoc($query)){
?>
<tr>
<td><?php echo str_replace($key,"<font color='red'>$key</font>",$val['user']) ?></td>
<td><?php echo $val['sex'] == 1 ? '先生' : '女士'; ?></td>
<td><?php echo $val['like'] ?></td>
<td><?php echo $val['address'] ?></td>
<td><?php echo $val['mobeil'] ?></td>
<td><?php echo $val['tel'] ?></td>
<?php if(!empty($_SESSION['user'])){ ?>
<td align="center"><a href="#" onclick="onsure('del.php?id=<?php echo $val['id'] ?>')">刪除</a> | <a href="show.php?id=<?php echo $val['id'] ?>">修改</a></td>
<?php } ?>
</tr>
<?php
}
?>
<tr height="50">
<th colspan=<?php if(!empty($_SESSION['user'])){ echo '"7"'; }else{ echo '"6"';} ?> align="center" >
總共<?php echo $countPage; ?>頁/當前第<?php echo $page ?>頁
<a href="index.php?page=1&key=<?php echo $key?>">首頁</a>
<a href="?page=<?php echo $page-1 ?>&key=<?php echo $key?>">上一頁</a>
<?php for($i = $start; $i<= $end; $i++){
if($i == $page){
echo $i . '';
}else{
?>
<a href="?page=<?php echo $i ?>&key=<?php echo $key?>"><?php echo $i ?></a>
<?php
}
} ?>
<!--a href="?page=<?php echo $page+1 ?>">...</a>
<a href="?page=<?php echo $countPage; ?>"><?php echo $countPage; ?></a> -->
<a href="?page=<?php echo $page+1 ?>&key=<?php echo $key?>">下一頁</a>
<a href="?page=<?php echo $countPage; ?>&key=<?php echo $key?>">尾頁</a>
</th>
</tr>
</table>
<a href="form.html">添加新聯系人</a>
<a href="login.html">管理員登陸</a>
</body>
</html>
5、php實現分頁功能
具體代碼如下:
/**
* 獲取分頁的HTML內容
* @param integer $page 當前頁
* @param integer $pages 總頁數
* @param string $url 跳轉url地址 最後的頁數以 '&page=x' 追加在url後面
*
* @return string HTML內容;
*/
public static function getPageHtml($page, $pages, $url){
//最多顯示多少個頁碼
$_pageNum = 5;
//當前頁面小於1 則為1
$page = $page<1?1:$page;
//當前頁大於總頁數 則為總頁數
$page = $page > $pages ? $pages : $page;
//頁數小當前頁 則為當前頁
$pages = $pages < $page ? $page : $pages;
//計算開始頁
$_start = $page - floor($_pageNum/2);
$_start = $_start<1 ? 1 : $_start;
//計算結束頁
$_end = $page + floor($_pageNum/2);
$_end = $_end>$pages? $pages : $_end;
//當前顯示的頁碼個數不夠最大頁碼數,在進行左右調整
$_curPageNum = $_end-$_start+1;
//左調整
if($_curPageNum<$_pageNum && $_start>1){
$_start = $_start - ($_pageNum-$_curPageNum);
$_start = $_start<1 ? 1 : $_start;
$_curPageNum = $_end-$_start+1;
}
//右邊調整
if($_curPageNum<$_pageNum && $_end<$pages){
$_end = $_end + ($_pageNum-$_curPageNum);
$_end = $_end>$pages? $pages : $_end;
}
$_pageHtml = '<ul class="pagination">';
/*if($_start == 1){
$_pageHtml .= '<li><a title="第一頁">«</a></li>';
}else{
$_pageHtml .= '<li><a title="第一頁" href="'.$url.'&page=1">«</a></li>';
}*/
if($page>1){
$_pageHtml .= '<li><a title="上一頁" href="'.$url.'&page='.($page-1).'">«</a></li>';
}
for ($i = $_start; $i <= $_end; $i++) {
if($i == $page){
$_pageHtml .= '<li class="active"><a>'.$i.'</a></li>';
}else{
$_pageHtml .= '<li><a href="'.$url.'&page='.$i.'">'.$i.'</a></li>';
}
}
/*if($_end == $pages){
$_pageHtml .= '<li><a title="最後一頁">»</a></li>';
}else{
$_pageHtml .= '<li><a title="最後一頁" href="'.$url.'&page='.$pages.'">»</a></li>';
}*/
if($page<$_end){
$_pageHtml .= '<li><a title="下一頁" href="'.$url.'&page='.($page+1).'">»</a></li>';
}
$_pageHtml .= '</ul>';
echo $_pageHtml;
}
6、這個簡單的PHP分頁類,該如何調用?感謝。~
0代表開始的下標,比如一頁顯示10條的話,那麼第一頁就是0,10,第二頁就是(2-1)*10,10,第三頁就是(3-1)*10,10
所以你那個0 就是寫 limit($page-1)*$pagenum,$pagenum
7、用PHP如何實現分頁並能夠實現上一頁,下一頁,跳轉到()頁的功能?
<html><head>
<title>分頁示例(php</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<?php
$pagesize=10; //設定每一頁顯示的記錄數
$conn=mysql_connect("localhost","root","jrq");
mysql_select_db("sj",$conn);
$rs = mysql_query( "select * from `dw_newsdata`",$conn); //這里有第二個可選參數,指定打開的連接
//-----------------------------------------------------------------------------------------------//
//分頁邏輯處理
//-----------------------------------------------------------------------------------------------
$tmpArr = mysql_fetch_array($rs);
$numAL = mysql_num_rows($rs); //取得記錄總數$rs
$pages=intval($numAL/$pagesize); //計算總頁數
if ($numAL % $pagesize) $pages++;
//設置預設頁碼
//↓判斷「當前頁碼」是否賦值過
if (isset($_GET['page'])){ $page=intval($_GET['page']); }else{ $page=1; }//否則,設置為第一頁
//↓計算記錄偏移量
$offset=$pagesize*($page - 1);
//↓讀取指定記錄數
$rs=mysql_query("select * from `dw_newsdata` limit $offset,$pagesize",$conn);//取得—當前頁—記錄集!
$curNum = mysql_num_rows($rs); //$curNum - 當前頁實際記錄數,for循環輸出用
?>
<table border="0" width="80%">
<tr>
<td width="50%" bgcolor="#E0E0E0">標題</td>
<td width="50%" bgcolor="#E0E0E0">發布時間</td>
</tr>
<?php
while ($tmpArr = mysql_fetch_array($rs)) //提取一行,並循環判斷
{
$i=0;
// for($a=0;$a<$ColNum;$a++) //==for結束==
?>
<tr>
<td width="50%"><?= $tmpArr[1]; //$tmpArr["news_title"] ; ?></td>
<td width="50%"><?php echo $tmpArr[2]; //$tmpArr["news_cont"]; ?></td>
</tr>
<?php
}//==while結束==
?>
</table>
<?php
//============================//
// 翻頁顯示 一
//============================//
echo "<p>"; // align=center
$first=1;
$prev=$page-1;
$next=$page+1;
$last=$pages;
if ($page > 1)
{
echo "<a href='?page=".$first."'>首頁</a> ";
echo "<a href='?page=".$prev."'>上一頁</a> ";
}
if ($page < $pages)
{
echo "<a href='?page=".$next."'>下一頁</a> ";
echo "<a href='?page=".$last."'>尾頁</a> ";
}
//============================//
// 翻頁顯示 二
//============================//
echo " | 共有".$pages."頁(".$page."/".$pages.")";
for ($i=1;$i< $page;$i++){echo "<a href='?page=".$i."'>[".$i ."]</a> ";} // 1-先輸出當前頁之前的
if ($page > 0) echo "[".$page."]";; // 2-再輸出當前頁
for ($i=$page+1;$i<=$pages;$i++){echo "<a href='?page=".$i."'>[".$i ."]</a> ";}// 3-接著輸出當前頁之後
echo "轉到第 <INPUT maxLength=3 size=3 value=".($page+1)." name=gotox> 頁 <INPUT hideFocus onclick=\"location.href='?page=gotox.value';\" type=button value=Go name=cmd_goto>";
echo "</p>";
?>
</body>
</html>
8、php+mysql優化,百萬至千萬級快速分頁mysql性能到底能有多高
php+Mysql 優化,百萬至千萬級快速分頁
MySql 性能到底能有多高?用了php半年多,真正如此深入的去思考這個問題還是從前天開始。有過痛苦有過絕望,到現在充滿信心!MySql 這個資料庫絕對是適合dba級的高手去玩的,一般做一點1萬篇新聞的小型系統怎麼寫都可以,用xx框架可以實現快速開發。可是數據量到了10萬,百萬至千萬,他的性能還能那麼高嗎?一點小小的失誤,可能造成整個系統的改寫,甚至更本系統無法正常運行!好了,不那麼多廢話了。用事實說話,看例子:
數據表 collect ( id, title ,info ,vtype) 就這4個欄位,其中 title 用定長,info 用text, id 是逐漸,vtype是tinyint,vtype是索引。這是一個基本的新聞系統的簡單模型。現在往裡面填充數據,填充10萬篇新聞。
最後collect 為 10萬條記錄,資料庫表佔用硬碟1.6G。OK ,看下面這條sql語句:
select id,title from collect limit 1000,10; 很快;基本上0.01秒就OK,再看下面的
select id,title from collect limit 90000,10; 從9萬條開始分頁,結果?
8-9秒完成,my god 哪出問題了????其實要優化這條數據,網上找得到答案。看下面一條語句:
select id from collect order by id limit 90000,10; 很快,0.04秒就OK。為什麼?因為用了id主鍵做索引當然快。網上的改法是:
select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;
這就是用了id做索引的結果。可是問題復雜那麼一點點,就完了。看下面的語句
select id from collect where vtype=1 order by id limit 90000,10; 很慢,用了8-9秒!
到了這里我相信很多人會和我一樣,有崩潰感覺!vtype 做了索引了啊?怎麼會慢呢?vtype做了索引是不錯,你直接 select id from collect where vtype=1 limit 1000,10; 是很快的,基本上0.05秒,可是提高90倍,從9萬開始,那就是0.05*90=4.5秒的速度了。和測試結果8-9秒到了一個數量級。從這里開始有人提出了分表的思路,這個和discuz 論壇是一樣的思路。思路如下:
建一個索引表: t (id,title,vtype) 並設置成定長,然後做分頁,分頁出結果再到 collect 裡面去找info 。 是否可行呢?實驗下就知道了。
10萬條記錄到 t(id,title,vtype) 里,數據表大小20M左右。用
select id from t where vtype=1 order by id limit 90000,10; 很快了。基本上0.1-0.2秒可以跑完。為什麼會這樣呢?我猜想是因為collect 數據太多,所以分頁要跑很長的路。limit 完全和數據表的大小有關的。其實這樣做還是全表掃描,只是因為數據量小,只有10萬才快。OK,來個瘋狂的實驗,加到100萬條,測試性能。
加了10倍的數據,馬上t表就到了200多M,而且是定長。還是剛才的查詢語句,時間是0.1-0.2秒完成!分表性能沒問題?錯!因為我們的limit還是9萬,所以快。給個大的,90萬開始
select id from t where vtype=1 order by id limit 900000,10; 看看結果,時間是1-2秒!
why 分表了時間還是這么長,非常之郁悶!有人說定長會提高limit的性能,開始我也以為,因為一條記錄的長度是固定的,mysql 應該可以算出90萬的位置才對啊? 可是我們高估了mysql 的智能,他不是商務資料庫,事實證明定長和非定長對limit影響不大?怪不得有人說 discuz到了100萬條記錄就會很慢,我相信這是真的,這個和資料庫設計有關!
難道MySQL 無法突破100萬的限制嗎???到了100萬的分頁就真的到了極限???
答案是: NO !!!! 為什麼突破不了100萬是因為不會設計mysql造成的。下面介紹非分表法,來個瘋狂的測試!一張表搞定100萬記錄,並且10G 資料庫,如何快速分頁!
好了,我們的測試又回到 collect表,開始測試結論是: 30萬數據,用分表法可行,超過30萬他的速度會慢道你無法忍受!當然如果用分表+我這種方法,那是絕對完美的。但是用了我這種方法後,不用分表也可以完美解決!
答案就是:復合索引!有一次設計mysql索引的時候,無意中發現索引名字可以任取,可以選擇幾個欄位進來,這有什麼用呢?開始的select id from collect order by id limit 90000,10; 這么快就是因為走了索引,可是如果加了where 就不走索引了。抱著試試看的想法加了 search(vtype,id) 這樣的索引。然後測試
select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!
再測試: select id ,title from collect where vtype=1 limit 90000,10; 非常遺憾,8-9秒,沒走search索引!
再測試:search(id,vtype),還是select id 這個語句,也非常遺憾,0.5秒。
綜上:如果對於有where 條件,又想走索引用limit的,必須設計一個索引,將where 放第一位,limit用到的主鍵放第2位,而且只能select 主鍵!
完美解決了分頁問題了。可以快速返回id就有希望優化limit , 按這樣的邏輯,百萬級的limit 應該在0.0x秒就可以分完。看來mysql 語句的優化和索引時非常重要的!
好了,回到原題,如何將上面的研究成功快速應用於開發呢?如果用復合查詢,我的輕量級框架就沒的用了。分頁字元串還得自己寫,那多麻煩?這里再看一個例子,思路就出來了:
select * from collect where id in (9000,12,50,7000); 竟然 0秒就可以查完!
mygod ,mysql 的索引竟然對於in語句同樣有效!看來網上說in無法用索引是錯誤的!
有了這個結論,就可以很簡單的應用於輕量級框架了:
代碼如下:
$db=dblink();
$db->pagesize=20;
$sql="select id from collect where vtype=$vtype";
$db->execute($sql);
$strpage=$db->strpage(); //將分頁字元串保存在臨時變數,方便輸出
while($rs=$db->fetch_array()){
$strid.=$rs['id'].',';
}
$strid=substr($strid,0,strlen($strid)-1); //構造出id字元串
$db->pagesize=0; //很關鍵,在不注銷類的情況下,將分頁清空,這樣只需要用一次資料庫連接,不需要再開;
$db->execute("select id,title,url,sTime,gTime,vtype,tag from collect where id in ($strid)");
< php while($rs=$db->fetch_array()): >
<tr>
<td$amp;>amp;$amp;nbsp;< php echo $rs['id']; $amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;< php echo $rs['url']; $amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;< php echo $rs['sTime']; $amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;< php echo $rs['gTime']; $amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;< php echo $rs['vtype']; $amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;<a act=show&id=< php echo $rs['id']; $amp;>quot;$ target="_blank"$amp;>amp;$lt; php echo $rs['title']; $amp;>amp;$lt;/a$amp;>amp;$lt;/td>
<td$amp;>amp;$amp;nbsp;< php echo $rs['tag']; $amp;>amp;$lt;/td>
</tr>
< php endwhile; >
</table>
< php
echo $strpage;
通過簡單的變換,其實思路很簡單:1)通過優化索引,找出id,並拼成 "123,90000,12000" 這樣的字元串。2)第2次查詢找出結果。
小小的索引+一點點的改動就使mysql 可以支持百萬甚至千萬級的高效分頁!
通過這里的例子,我反思了一點:對於大型系統,PHP千萬不能用框架,尤其是那種連sql語句都看不到的框架!因為開始對於我的輕量級框架都差點崩潰!只適合小型應用的快速開發,對於ERP,OA,大型網站,數據層包括邏輯層的東西都不能用框架。如果程序員失去了對sql語句的把控,那項目的風險將會成幾何級數增加!尤其是用mysql 的時候,mysql 一定需要專業的dba 才可以發揮他的最佳性能。一個索引所造成的性能差別可能是上千倍!
PS: 經過實際測試,到了100萬的數據,160萬數據,15G表,190M索引,就算走索引,limit都得0.49秒。所以分頁最好別讓別人看到10萬條以後的數據,要不然會很慢!就算用索引。經過這樣的優化,mysql到了百萬級分頁是個極限!但有這樣的成績已經很不錯,如果你是用sqlserver肯定卡死!而 160萬的數據用 id in (str) 很快,基本還是0秒。如果這樣,千萬級的數據,mysql應該也很容易應付。
9、怎麼解決wordpress分頁title標題重復不利於SEO的問題
我們都知道,wordpress分頁調用title標簽在header.php中,為此我們可以通過在header.php中title標簽上category加入分頁頁碼的調用標簽從而解決wordpress分頁頁面title標題重復的問題,告訴搜索引擎這是兩個頁面,最終達到SEO效果。
在這里,我主要講的是category,即分類目錄的標題重復,其他頁面也類似。
在沒有添加頁碼之前,我們可以在header.php中找到這行代碼:
<?php if (is_category() ) { ?><?php single_cat_title(); ?> - <? bloginfo('name'); ?><?php } ?>
此時,如果分類目錄文章超出一頁,我們可以看到所有分類目錄標題都是重復的,即「分類目錄標題-博客標題」,我們可以修改成下面這樣,
<?php if ( is_category() ) { ?><?php single_cat_title(); ?> - <? bloginfo('name'); $paged = get_query_var('paged'); if ( $paged > 1 ) printf('– 第 %s 頁 ',$paged); ?><?php } ?>
這段代碼就表示首先獲取頁數,如果不是第一頁那麼就加上頁碼,表示第幾頁,通過這個辦法可以有效的杜絕分頁頁面重復標題的問題。
從而實現分類目錄標題為 「分類目錄標題-博客標題-頁碼」,除第一頁之外。
同理,如果是首頁,則可以為
<?php if (is_home()) { ?><? bloginfo('name'); ?>$paged = get_query_var('paged'); if ( $paged > 1 ) printf('– 第 %s 頁 ',$paged);<?php } ?>
其他頁面也類似,只需將
$paged = get_query_var('paged'); if ($paged > 1 ) printf('– 第 %s 頁 ',$paged); 加入到適當位置即可。
謝謝採納