在MySQL中使用LIMIT進行分頁的方法
今天看一個水友說他的MySQL現(xiàn)在變的很慢。問什么情況時。說單表超過2個G的一個MyISAM。真垃圾的回答方式。
簡單答復(fù):換一個強勁的服務(wù)器。換服務(wù)器很管用的:)
………
最終讓取到慢查詢:
SELECT * FROM pw_gbook WHERE uid='N' ORDER BY postdate DESC LIMIT N,N; SELECT * FROM pw_gbook WHERE uid='N' ORDER BY postdate DESC LIMIT N,N;
如:
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20; SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;
看到這個語句我都吐血了(BT的PHPWIND分頁啊,這個語句是PHP初學(xué)者寫出來的還正常,但PHPWIND那么成熟的社區(qū)了還有這樣的問題)。
我這里簡單說一下LIMIT的原理。這里以LIMIT N,M為基礎(chǔ):LIMIT首先要找查N+M行,然后從N行處,取M行。那么這樣的SQL對一次查詢1275500一個操作應(yīng)該是一個昂貴的開銷。對于LIMIT這類的優(yōu)化,第一個目標(biāo)就是讓N變的盡可能的小或是不用。
怎么才能使這個N盡可能小呢。我們能做的其實就是用相對的值,給分頁一個提示。如現(xiàn)在我們看的是第5頁,看完看想看第6頁,第6頁同樣顯示是20條記錄。我們就可以想到,以這個例子為準(zhǔn):我們可以肯定的是第6頁的日值應(yīng)小于第5頁的,如果第5頁的最小日值為:2009-11-4,那我們就可以用:
SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-1' ORDER BY postdate DESC LIMIT 20; SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-1' ORDER BY postdate DESC LIMIT 20;
這樣來查詢第6頁的內(nèi)容。同樣對于查看第4頁的內(nèi)容(假設(shè)第5頁的最大日期為:2009-11-3)則第4頁的內(nèi)容為:
SELECT * FROM pw_gbook WHERE uid='48' and postdate>'2009-11-3' ORDER BY postdate DESC LIMIT 20; SELECT * FROM pw_gbook WHERE uid='48' and postdate>'2009-11-3' ORDER BY postdate DESC LIMIT 20;
這是一個基本的思想。接下來討論一下怎么展現(xiàn)的問題。
再說一下這種業(yè)務(wù)的SQL怎么實現(xiàn):對于分頁的展示可以用多用類型。這里說三種常用的類型:
第一種:顯示“上一頁” “下一頁”這種類型
這種方式相對簡單也就出現(xiàn)了我們看到那種SQL不思考的寫法。合理的做法:
第一頁:
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20; SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;
第二頁:根據(jù)第一頁的postdate進行查詢?nèi)纾?br />
SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 20;
SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 20;
為什么說這個簡單呢,這個不存在跳頁的問題。接下來這種就存在一個跳頁的問題了。
第二種:顯示 “ 1,2,3,4,5…”
第一頁: 還是以第一頁的方式實現(xiàn):
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20; SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 20;
第二頁:和原來一樣。如果跳頁,如從第二頁跳到第5頁,這里有一個第二頁的最小日期為:2009-11-3(假設(shè)值,可以由第二頁的程序查詢得到),第二到第5,差2頁,每頁20條記錄,那么就可以用:
SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 40,20; SELECT * FROM pw_gbook WHERE uid='48' and postdate<'2009-11-3' ORDER BY postdate DESC LIMIT 40,20;
看到這里明白為什么大型網(wǎng)站的分頁不是一下標(biāo)識出來完了,讓都能點了吧。也不會給你一個框讓你輸入一個頁跳過去了。如果跳的頁面過多,也就存在N值過大的問題了。所以要想辦法必免。
第三種:顯示 “1,2,3,4,5,…. 末頁” 或是 “首頁,<<100,101,102,103 >>末頁”
這里有一個特殊的一地方:
別的頁面的跳轉(zhuǎn)的上面一樣。這里就加一個末頁,這里又分兩種情況,如果知道最后一頁是多少頁,也就知道了前一頁的最小日期(分頁提示值),這樣就可以用上面的方法查看最后一頁的內(nèi)容(會出現(xiàn)不足20條的現(xiàn)象),另一種,我就不知道最后是第幾頁,我就是想看看最后什么樣子,那么就可以用(一定是顯示20條):
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate ASC limit 20; SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate ASC limit 20;
首頁這里就不在說了。
具體怎么實現(xiàn)搞明白了,就可以做PHP代碼的修改了。稍稍修改一下,就會帶來意想不到的效果。
這里只是一個通用的分頁處理方法。不同的業(yè)務(wù)有可能還有不同的方法處理。如果在條件可能和情況可以考用:between … and .. 帶代替limit分頁操作。
第三種方法:
簡單的邏輯轉(zhuǎn)換。
SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20; SELECT * FROM pw_gbook WHERE uid='48' ORDER BY postdate DESC LIMIT 1275480,20;
轉(zhuǎn)換成:
SELECT * FROM pw_gbook WHERE id>1275480 and uid='48' ORDER BY postdate DESC LIMIT 20; SELECT * FROM pw_gbook WHERE id>1275480 and uid='48' ORDER BY postdate DESC LIMIT 20;
相關(guān)文章
全面分析MySQL?ERROR?1045出現(xiàn)的原因及解決
這篇文章主要介紹了全面分析MySQL?ERROR?1045出現(xiàn)的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07使用MySQL的LAST_INSERT_ID來確定各分表的唯一ID值
MySQL數(shù)據(jù)表結(jié)構(gòu)中,一般情況下,都會定義一個具有‘AUTO_INCREMENT’擴展屬性的‘ID’字段,以確保數(shù)據(jù)表的每一條記錄都可以用這個ID唯一確定2011-08-08mysql 日期和時間格式轉(zhuǎn)換實現(xiàn)語句
對于每個類型擁有的值范圍以及并且指定日期何時間值的有效格式的描述見7.3.6 日期和時間類型。2009-10-10解決mysql不能插入中文Incorrect string value
首先我的配置文件的設(shè)置的默認字符集是utf8即2009-05-05