使用子查詢優(yōu)化
這種方式先定位偏移位置的 id议泵,然后往后查詢,這種方式適用于 id 遞增的情況鬓催。
select * from orders_history where type=8 limit 100000,1;
select id from orders_history where type=8 limit 100000,1;
select * from orders_history where type=8 and
id>=(select id from orders_history where type=8 limit 100000,1)
limit 100;
select * from orders_history where type=8 limit 100000,100;
4條語句的查詢時(shí)間如下:
第1條語句:3674ms
第2條語句:1315ms
第3條語句:1327ms
第4條語句:3710ms
針對上面的查詢需要注意:
比較第1條語句和第2條語句:使用 select id 代替 select * 速度增加了3倍
比較第2條語句和第3條語句:速度相差幾十毫秒
比較第3條語句和第4條語句:得益于 select id 速度增加肺素,第3條語句查詢速度增加了3倍
這種方式相較于原始一般的查詢方法,將會增快數(shù)倍宇驾。
使用 id 限定優(yōu)化
這種方式假設(shè)數(shù)據(jù)表的id是連續(xù)遞增的倍靡,則我們根據(jù)查詢的頁數(shù)和查詢的記錄數(shù)可以算出查詢的id的范圍,可以使用 id between and 來查詢:
select * from orders_history where type=2 and id between 1000000 and 1000100 limit 100;
--OR
select * from orders_history where id >= 1000001 limit 100;
當(dāng)然還可以使用 in 的方式來進(jìn)行查詢课舍,這種方式經(jīng)常用在多表關(guān)聯(lián)的時(shí)候進(jìn)行查詢塌西,使用其他表查詢的id集合,來進(jìn)行查詢:
select * from orders_history where id in (select order_id from trade_2 where goods = 'pen') limit 100;
這種 in 查詢的方式要注意:某些 mysql 版本不支持在 in 子句中使用 limit筝尾。
使用臨時(shí)表優(yōu)化
這種方式已經(jīng)不屬于查詢優(yōu)化捡需,這兒附帶提一下。
對于使用 id 限定優(yōu)化中的問題筹淫,需要 id 是連續(xù)遞增的站辉,但是在一些場景下,比如使用歷史表的時(shí)候,或者出現(xiàn)過數(shù)據(jù)缺失問題時(shí)饰剥,可以考慮使用臨時(shí)存儲的表來記錄分頁的id殊霞,使用分頁的id來進(jìn)行 in 查詢。這樣能夠極大的提高傳統(tǒng)的分頁查詢速度汰蓉,尤其是數(shù)據(jù)量上千萬的時(shí)候绷蹲。
關(guān)于數(shù)據(jù)表的id說明
一般情況下,在數(shù)據(jù)庫中建立表的時(shí)候古沥,強(qiáng)制為每一張表添加 id 遞增字段瘸右,這樣方便查詢。
如果像是訂單庫等數(shù)據(jù)量非常龐大岩齿,一般會進(jìn)行分庫分表。這個(gè)時(shí)候不建議使用數(shù)據(jù)庫的 id 作為唯一標(biāo)識苞俘,而應(yīng)該使用分布式的高并發(fā)唯一 id 生成器來生成盹沈,并在數(shù)據(jù)表中使用另外的字段來存儲這個(gè)唯一標(biāo)識。
使用先使用范圍查詢定位 id (或者索引)吃谣,然后再使用索引進(jìn)行定位數(shù)據(jù)乞封,能夠提高好幾倍查詢速度。即先 select id岗憋,然后再 select *肃晚;
文章轉(zhuǎn)載自:
MySQL分頁查詢優(yōu)化