mysql資料庫頁
很多應用往往只展示最新或最熱門的幾條記錄,但為了舊記錄仍然可訪問,所以就需要個分頁的導航欄。然而,如何通過MySQL更好的實現分頁,始終是比較令人頭疼的問題。雖然沒有拿來就能用的解決辦法,但了解資料庫的底層或多或少有助於優化分頁查詢。
我們先從一個常用但性能很差的查詢來看一看。
SELECT *
FROM city
ORDER BY id DESC
LIMIT 0, 15
這個查詢耗時0.00sec。So,這個查詢有什麼問題呢?實際上,這個查詢語句和參數都沒有問題,因為它用到了下面表的主鍵,而且只讀取15條記錄。
CREATE TABLE city (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
city varchar(128) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
真正的問題在於offset(分頁偏移量)很大的時候,像下面這樣:
SELECT *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
上面的查詢在有2M行記錄時需要0.22sec,通過EXPLAIN查看SQL的執行計劃可以發現該SQL檢索了100015行,但最後只需要15行。大的分頁偏移量會增加使用的數據,MySQL會將大量最終不會使用的數據載入到內存中。就算我們假設大部分網站的用戶只訪問前幾頁數據,但少量的大的分頁偏移量的請求也會對整個系統造成危害。Facebook意識到了這一點,但Facebook並沒有為了每秒可以處理更多的請求而去優化資料庫,而是將重心放在將請求響應時間的方差變小。
對於分頁請求,還有一個信息也很重要,就是總共的記錄數。我們可以通過下面的查詢很容易的獲取總的記錄數。
SELECT COUNT(*)
FROM city;
然而,上面的SQL在採用InnoDB為存儲引擎時需要耗費9.28sec。一個不正確的優化是採用 SQL_CALC_FOUND_ROWS,SQL_CALC_FOUND_ROWS 可以在能夠在分頁查詢時事先准備好符合條件的記錄數,隨後只要執行一句 select FOUND_ROWS(); 就能獲得總記錄數。但是在大多數情況下,查詢語句簡短並不意味著性能的提高。不幸的是,這種分頁查詢方式在許多主流框架中都有用到,下面看看這個語句的查詢性能。
SELECT SQL_CALC_FOUND_ROWS *
FROM city
ORDER BY id DESC
LIMIT 100000, 15;
這個語句耗時20.02sec,是上一個的兩倍。事實證明使用 SQL_CALC_FOUND_ROWS 做分頁是很糟糕的想法。
下面來看看到底如何優化。文章分為兩部分,第一部分是如何獲取記錄的總數目,第二部分是獲取真正的記錄。
高效的計算行數
如果採用的引擎是MyISAM,可以直接執行COUNT(*)去獲取行數即可。相似的,在堆表中也會將行數存儲到表的元信息中。但如果引擎是InnoDB情況就會復雜一些,因為InnoDB不保存表的具體行數。
我們可以將行數緩存起來,然後可以通過一個守護進程定期更新或者用戶的某些操作導致緩存失效時,執行下面的語句:
SELECT COUNT(*)
FROM city
USE INDEX(PRIMARY);
獲取記錄
下面進入這篇文章最重要的部分,獲取分頁要展示的記錄。上面已經說過了,大的偏移量會影響性能,所以我們要重寫查詢語句。為了演示,我們創建一個新的表「news」,按照時事性排序(最新發布的在最前面),實現一個高性能的分頁。為了簡單,我們就假設最新發布的新聞的Id也是最大的。
CREATE TABLE news(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL
) ENGINE=InnoDB;
一個比較高效的方式是基於用戶展示的最後一個新聞Id。查詢下一頁的語句如下,需要傳入當前頁面展示的最後一個Id。
SELECT *
FROM news WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage
查詢上一頁的語句類似,只不過需要傳入當前頁的第一個Id,並且要逆序。
SELECT *
FROM news WHERE id > $last_id
ORDER BY id ASC
LIMIT $perpage
上面的查詢方式適合實現簡易的分頁,即不顯示具體的頁數導航,只顯示「上一頁」和「下一頁」,例如博客中頁腳顯示「上一頁」,「下一頁」的按鈕。但如果要實現真正的頁面導航還是很難的,下面看看另一種方式。
SELECT id
FROM (
SELECT id, ((@cnt:= @cnt + 1) + $perpage - 1) % $perpage cnt
FROM news
JOIN (SELECT @cnt:= 0)T
WHERE id < $last_id
ORDER BY id DESC
LIMIT $perpage * $buttons
)C
WHERE cnt = 0;
通過上面的語句可以為每一個分頁的按鈕計算出一個offset對應的id。這種方法還有一個好處。假設,網站上正在發布一片新的文章,那麼所有文章的位置都會往後移一位,所以如果用戶在發布文章時換頁,那麼他會看見一篇文章兩次。如果固定了每個按鈕的offset Id,這個問題就迎刃而解了。Mark Callaghan發表過一篇類似的博客,利用了組合索引和兩個位置變數,但是基本思想是一致的。
如果表中的記錄很少被刪除、修改,還可以將記錄對應的頁碼存儲到表中,並在該列上創建合適的索引。採用這種方式,當新增一個記錄的時候,需要執行下面的查詢重新生成對應的頁號。
SET p:= 0;
UPDATE news SET page=CEIL((p:= p + 1) / $perpage) ORDER BY id DESC;
當然,也可以新增一個專用於分頁的表,可以用個後台程序來維護。
UPDATE pagination T
JOIN (
SELECT id, CEIL((p:= p + 1) / $perpage) page
FROM news
ORDER BY id
)C
ON C.id = T.id
SET T.page = C.page;
現在想獲取任意一頁的元素就很簡單了:
SELECT *
FROM news A
JOIN pagination B ON A.id=B.ID
WHERE page=$offset;
還有另外一種與上種方法比較相似的方法來做分頁,這種方式比較試用於數據集相對小,並且沒有可用的索引的情況下—比如處理搜索結果時。在一個普通的伺服器上執行下面的查詢,當有2M條記錄時,要耗費2sec左右。這種方式比較簡單,創建一個用來存儲所有Id的臨時表即可(這也是最耗費性能的地方)。
CREATE TEMPORARY TABLE _tmp (KEY SORT(random))
SELECT id, FLOOR(RAND() * 0x8000000) random
FROM city;
ALTER TABLE _tmp ADD OFFSET INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, DROP INDEX SORT,ORDER BY random;
接下來就可以向下面一樣執行分頁查詢了。
SELECT *
FROM _tmp
WHERE OFFSET >= $offset
ORDER BY OFFSET
LIMIT $perpage;
簡單來說,對於分頁的優化就是。。。避免數據量大時掃描過多的記錄。
❷ Mysql 資料庫怎麼實現分頁,要說的通俗一點兒
每次取的數據集是有總條數的
數據集 有當前頁,總頁數的屬性
然後就可以分頁啦
rs.pagecount
rs.absolutepage
❸ Mysql 資料庫怎麼實現分頁,要說的通俗一點兒
一個不帶limit 一個帶limit。以php+mysql為例首先,連接資料庫,寫一條sql語句把你要查詢的信息總量查找出來sql = select count(*) from tb,$all_page ;設定每頁顯示條數, $display 。然後,當前頁為$page ;在寫一句sql = select * from tb limit $dispaly*($page - 1),$display;最後,在頁面顯示分頁信息把當前頁傳回給分頁處理頁,一定要把相關的條件一起傳回去,get 方式傳值,否則查詢條件改變查詢信息就不正確。 網上有好多封裝好的分頁類。我也有一個很好用的分頁類,如果請我吃肉就發給你一份哈。。\(^o^)/~ 追問: 這個$all_page用在哪兒,怎麼將當前頁傳回給分頁處理頁。顯示的時候那些「首頁」「上一頁」「下一頁」「末頁」是鏈接嗎、鏈到什麼地方,還是別的什麼 回答: $all_page是查詢總數,總是頁數等於查詢總數除以每頁顯示的信息。$num_page = ceil($all_page/$display); 用get方式把當前頁傳給分頁處理頁,就是標簽 別的我也想不起來,讓我自己寫分頁,我只會最簡單的那種,一般我都是調用一個現成的分頁類。只需傳個參數就Ok,連樣式都不用寫的。。。
❹ 怎麼用命令打開mysql資料庫操作頁面
使用命令行連接mysql資料庫:
windows操作系統下,開始——運行,打開"運行"對話框,輸入cmd,點擊「確定」即可進入dos窗口。
dos窗口輸入登錄mysql資料庫命令
mysql
-h
127.0.0.1
-u
root
-p
命令參數說明:
mysql是登錄資料庫的命令,-h
後面跟伺服器的ip,由於本示例mysql伺服器安裝在本地,因此ip地址為127.0.0.1;-u
後面跟用戶名,本示例採用
root用戶登錄;-p
後面跟登錄密碼。
輸入上述命令後回車,再輸入登錄密碼,在回車即可完成登錄mysql資料庫服務了。跟著可以運行use
databasename語句操作某個資料庫了
❺ 如何打開Mysql資料庫
1、安裝phpstudy伺服器,可以到官網下載這個伺服器,會有詳細的安裝步驟,安裝成功後,界面會下圖的圖標,如下圖
❻ mysql資料庫頁面輸入正常,到資料庫亂碼
考慮是軟體不兼容或者是系統問題導致的
如果是這樣那麼就首先卸載軟體
如果不行就需要系統重裝
如果還不行就考慮是硬體問題或者其他的設置問題
考慮是你的系統文件問題導致的
可能是由於系統文件錯誤導致的
個人建議如果能夠進入系統就用殺毒軟體進行修復
如果不能進入系統就進入安全模式
如果以上方法都不行就只能進行系統統重裝了
你所描述的問題解決方法差不多就是以上方法 最後所有方法都沒用記得只能請專業人員維修
❼ 急急急!!!請問怎麼在Java中每次讀取mysql資料庫的一頁數據
你好:
分頁需要用到3個變數,數據總條數、當前頁數、一頁條數;這3個變數一般從前台傳過來,根據這3個變數計算出資料庫改取第幾條數據到第幾條數據,就是limit m,n(m是第幾條數據開始,n是一頁條數) ;例如第二頁,一頁顯示20條,總條數是50;那就m=(2-1)*20,n=20;就是sql中limit 20,20; 表示取21條到40條數據
❽ php使用mysql資料庫分頁顯示100頁,怎麼只輸出前後5頁的超鏈接,中間的用省略號顯示
這個得用程序去判斷,根據每頁顯示的記錄條數和記錄總數做處理,給你個思路吧。
functiongetTotalPagesStr($total,$maxPageItems){
$totalPages=0;
if($total%$maxPageItems==0){
$totalPages=$total/$maxPageItems;
if($totalPages==0)
$totalPages=1;
}
else{
$totalPages=(int)($total/$maxPageItems)+1;
}
return'<span>共'.$total.'條記錄,'.$totalPages.'頁</span>';
}
functiongetTotalPages($total,$maxPageItems){
$totalPages=0;
if($total%$maxPageItems==0){
$totalPages=$total/$maxPageItems;
if($totalPages==0)
$totalPages=1;
}
else{
$totalPages=(int)($total/$maxPageItems)+1;
}
return$totalPages;
}
functiongetPageUrl($page){
$url=$_SERVER['PHP_SELF'];
$i=0;
$queryStr='';
foreach($_GETas$key=>$value)
{
if($key!='page'){
if($i==0){
if(is_array($value)){
$j=0;
foreach($valueas$simpleValue){
if($j==0){
$queryStr=$queryStr.'?'.$key.'[]='.$simpleValue;
}
else{
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
$j++;
}
}
else{
$queryStr=$queryStr.'?'.$key.'='.$value;
}
}
else{
if(is_array($value)){
foreach($valueas$simpleValue){
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
}
else{
$queryStr=$queryStr.'&'.$key.'='.$value;
}
}
$i++;
}
}
foreach($_POSTas$key=>$value)
{
if($key!='page'&&$key!='submit'){
if($i==0){
if(is_array($value)){
$j=0;
foreach($valueas$simpleValue){
if($j==0){
$queryStr=$queryStr.'?'.$key.'[]='.$simpleValue;
}
else{
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
$j++;
}
}
else{
$queryStr=$queryStr.'?'.$key.'='.$value;
}
}
else{
if(is_array($value)){
foreach($valueas$simpleValue){
$queryStr=$queryStr.'&'.$key.'[]='.$simpleValue;
}
}
else{
$queryStr=$queryStr.'&'.$key.'='.$value;
}
}
$i++;
}
}
if($i!=0){
return$url.$queryStr.'&page='.$page;
}
return$url.'?page='.$page;
}
functiongetPageDisplay($total,$maxPageItems,$currentPage,$maxShowPages,
$pageSeparator){
$totalPages=getTotalPages($total,$maxPageItems);
$pageDispayStr='';
$ppage=0;
$startPage=0;
$endPage=0;
if($currentPage%$maxShowPages==0)
$ppage=(int)($currentPage/$maxShowPages)-1;
else
$ppage=(int)($currentPage/$maxShowPages);
$startPage=$ppage*$maxShowPages+1;
if($totalPages<=($ppage+1)*$maxShowPages){
$endPage=$totalPages;
}
else{
$endPage=($ppage+1)*$maxShowPages;
}
if($totalPages>$maxShowPages){
if($currentPage==1){
$pageDispayStr=$pageDispayStr.'<span>[第一頁/上一頁]</span>';
}
else{
$pageDispayStr=$pageDispayStr.'[<ahref=''.getPageUrl(1).''>第一頁</a>/';
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($currentPage-1).''>上一頁</a>]';
}
}
if($startPage==1){
$pageDispayStr=$pageDispayStr.'<span><</span>';
}
else{
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($startPage-1).''><<</a>';
}
for($i=$startPage;$i<=$endPage;$i++){
if($i!=$currentPage){
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($i).''>'.$i.'</a>';
if($i!=$endPage){
$pageDispayStr=$pageDispayStr.$pageSeparator;
}
$pageDispayStr=$pageDispayStr.'';
}
else{
$pageDispayStr=$pageDispayStr.'<spanclass="current">'.$i.'</span>';
if($i!=$endPage){
$pageDispayStr=$pageDispayStr.$pageSeparator;
}
$pageDispayStr=$pageDispayStr.'';
}
}
if($endPage==$totalPages){
$pageDispayStr=$pageDispayStr.'<span>>></span>';
}
else{
$pageDispayStr=$pageDispayStr.'<ahref=''.getPageUrl($endPage+1).''>>></a>';
}
if($totalPages>$maxShowPages){
if($currentPage==$totalPages){
$pageDispayStr=$pageDispayStr.'<span>[下一頁/最後一頁]</span>';
}
else{
$pageDispayStr=$pageDispayStr.'[<ahref=''.getPageUrl($currentPage+1).''>下一頁</a>';
$pageDispayStr=$pageDispayStr.'/<ahref=''.getPageUrl($totalPages).''>最後一頁</a>]';
}
}
returngetTotalPagesStr($total,$maxPageItems).$pageDispayStr;
}
❾ mysql資料庫頁面渲染正常,可資料庫里中文部分顯示是亂碼是怎麼回事
看起來是編碼不對,資料庫定義的欄位編碼、網頁的編碼、以及查詢之前mysql_query("set names xxx")的編碼,三個一致就不會亂碼。
❿ mysql資料庫動態分頁的sql語句
sql語句是通用的
select * from mytable1 where 1 order by id desc limit 0,10
作用是倒序,取最前10條記錄,也就是第一頁
取第二頁可以是這樣的limit 10,10
自已修改著用吧