MySQL使用Limit關鍵字限制查詢結果的數量效率問題


MySQL使用Limit關鍵字限制查詢結果的數量

1、Limit關鍵字的使用
查詢數據時,可能會查詢出很多的記錄。而用戶需要的記錄可能只是很少的一部分。這樣就需要來限制查詢結果的數量。Limit是MySQL中的一個特殊關鍵字。Limit子句可以對查詢結果的記錄條數進行限定,控制它輸出的行數。

在MySQL數據庫中創建用戶信息表(tb_user),並添加數據用於測試使用。

-- 判斷數據表是否存在,存在則刪除
DROP TABLE IF EXISTS tb_user;

-- 創建“用戶信息”數據表
CREATE TABLE IF NOT EXISTS tb_user
(
user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用戶編號',
user_name VARCHAR(50) NOT NULL COMMENT '用戶姓名',
province VARCHAR(50) NOT NULL COMMENT '省份'
) COMMENT = '用戶信息表';

-- 添加數據
INSERT INTO tb_user(user_name,province) VALUES
('pan_junbiao的博客_01','廣東省'),('pan_junbiao的博客_02','黑龍江省'),('pan_junbiao的博客_03','山東省'),('pan_junbiao的博客_04','安徽省'),('pan_junbiao的博客_05','黑龍江省'),
('pan_junbiao的博客_06','江蘇省'),('pan_junbiao的博客_07','黑龍江省'),('pan_junbiao的博客_08','廣東省'),('pan_junbiao的博客_09','陝西省'),('pan_junbiao的博客_10','廣東省'),
('pan_junbiao的博客_11','廣東省'),('pan_junbiao的博客_12','江蘇省'),('pan_junbiao的博客_13','陝西省'),('pan_junbiao的博客_14','安徽省'),('pan_junbiao的博客_15','山東省'),
('pan_junbiao的博客_16','陝西省'),('pan_junbiao的博客_17','安徽省'),('pan_junbiao的博客_18','江蘇省'),('pan_junbiao的博客_19','黑龍江省'),('pan_junbiao的博客_20','安徽省'),
('pan_junbiao的博客_21','江蘇省'),('pan_junbiao的博客_22','廣東省'),('pan_junbiao的博客_23','安徽省'),('pan_junbiao的博客_24','陝西省'),('pan_junbiao的博客_25','廣東省'),
('pan_junbiao的博客_26','廣東省'),('pan_junbiao的博客_27','安徽省'),('pan_junbiao的博客_28','山東省'),('pan_junbiao的博客_29','山東省'),('pan_junbiao的博客_30','黑龍江省'),
('pan_junbiao的博客_31','廣東省'),('pan_junbiao的博客_32','江蘇省'),('pan_junbiao的博客_33','陝西省'),('pan_junbiao的博客_34','安徽省'),('pan_junbiao的博客_35','山東省');
1.1 語法格式1
LIMIT m;
m:表示查詢多少條記錄。

【示例】查詢用戶信息表(tb_user),按照 user_id 編號進行升序排列,顯示前5條記錄。

SELECT * FROM tb_user
ORDER BY user_id
LIMIT 5
執行結果:

1.2 語法格式2
LIMIT m , n;
m:表示開始查詢的第一條記錄的編號(注意:在查詢結果中,第一個結果的記錄編號是0,而不是1)。

n:表示查詢多少條記錄。

【示例】查詢用戶信息表(tb_user),按照 user_id 編號進行升序排列,從編號10開始,查詢后面5條記錄。

SELECT * FROM tb_user
ORDER BY user_id
LIMIT 10,5
執行結果:

2、使用Limit分頁查詢的性能優化
【示例】在存儲過程中使用Limit的優化查詢。

2.1 使用一般分頁查詢(不推薦)
DELIMITER $$

-- 方式一:使用一般分頁查詢(不推薦)
DROP PROCEDURE IF EXISTS proc_user_page$$
CREATE PROCEDURE proc_user_page(IN page_index INT,IN page_size INT)
BEGIN
DECLARE begin_no INT;
SET begin_no = (page_index-1)*page_size;

SELECT * FROM tb_user
ORDER BY user_id ASC
LIMIT begin_no,page_size;

END$$

DELIMITER ;
調用存儲過程:查詢第2頁,每頁5條記錄。

-- 調用存儲過程:查詢第2頁,每頁5條記錄
CALL proc_user_page(2,5);
執行結果:

弊端:方式一雖然實現了分頁功能,但隨着查詢偏移的增大,尤其查詢偏移大於10萬以后,查詢時間將急劇增加。這種分頁查詢方式會從數據庫第一條記錄開始掃描,所以越往后,查詢速度越慢,而且查詢的數據越多,也會拖慢總查詢速度。

2.2 使用子句優化查詢(推薦)
DELIMITER $$

-- 方式二:使用子句優化查詢(推薦)
DROP PROCEDURE IF EXISTS proc_optimize$$
CREATE PROCEDURE proc_optimize(IN page_index INT,IN page_size INT)
BEGIN
DECLARE begin_no INT;
SET begin_no = (page_index-1)*page_size;

SELECT * FROM tb_user
WHERE user_id >= (
	SELECT user_id FROM tb_user
	ORDER BY user_id ASC
	LIMIT begin_no,1
)
ORDER BY user_id ASC
LIMIT page_size;

END$$

DELIMITER ;
調用存儲過程:查詢第3頁,每頁5條記錄。

-- 調用存儲過程:查詢第3頁,每頁5條記錄
CALL proc_optimize(3,5);
執行結果:

優點:方式二適合數據表的id是連續遞增的,則可以根據查詢的頁數和查詢的記錄數可以算出查詢的id的范圍。這種查詢方式能夠極大地優化查詢速度,基本能夠在幾十毫秒之內完成。限制是只能使用於明確知道id的情況,不過一般建立表的時候,都會添加基本的自增的主鍵id字段,這為分頁查詢帶來很多便利。

3、Limit的效率問題
以下內容轉載至:https://www.cnblogs.com/acm-bingzi/p/msqlLimit.html

3.1 Limit的效率高?
常說的Limit的執行效率高,是對於一種特定條件下來說的:即數據庫的數量很大,但是只需要查詢一部分數據的情況。
高效率的原理是:避免全表掃描,提高查詢效率。

比如:每個用戶的email是唯一的,如果用戶使用email作為用戶名登陸的話,就需要查詢出email對應的一條記錄。
SELECT * FROM t_user WHERE email=?;
上面的語句實現了查詢email對應的一條用戶信息,但是由於email這一列沒有加索引,會導致全表掃描,效率會很低。
SELECT * FROM t_user WHERE email=? LIMIT 1;
加上LIMIT 1,只要找到了對應的一條記錄,就不會繼續向下掃描了,效率會大大提高。

3.2 Limit的效率低?
在一種情況下,使用limit效率低,那就是:只使用limit來查詢語句,並且偏移量特別大的情況

做以下實驗:
語句1:
select * from table limit 150000,1000;
語句2:
select * from table while id>=150000 limit 1000;
語句1為0.2077秒;語句2為0.0063秒
兩條語句的時間比是:語句1/語句2=32.968

比較以上的數據時,我們可以發現采用where...limit....性能基本穩定,受偏移量和行數的影響不大,而單純采用limit的話,受偏移量的影響很大,當偏移量大到一定后性能開始大幅下降。不過在數據量不大的情況下,兩者的區別不大。

所以應當先使用where等查詢語句,配合limit使用,效率才高

ps:在sql語句中,limt關鍵字是最后才用到的。以下條件的出現順序一般是:where->group by->having-order by->limit

附錄:OFFSET
為了與 PostgreSQL 兼容,MySQL 也支持句法: LIMIT # OFFSET #。
經常用到在數據庫中查詢中間幾條數據的需求
比如下面的sql語句:
selete * from testtable limit 2,1;
selete * from testtable limit 2 offset 1;
注意:
1.數據庫數據計算是從0開始的
2.offset X是跳過X個數據,limit Y是選取Y個數據
3.limit X,Y 中X表示跳過X個數據,讀取Y個數據
這兩個都是能完成需要,但是他們之間是有區別的:
(1)是從數據庫中第三條開始查詢,取一條數據,即第三條數據讀取,一二條跳過
(2)是從數據庫中的第二條數據開始查詢兩條數據,即第二條和第三條。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM