如何解決mysql深度分頁問題
mysql深度分頁問題
數(shù)據(jù):單表數(shù)據(jù)25萬條。
1.基本分頁:耗時0.019秒
select * from cf_qb_info limit 0,20
2.深度分頁:耗時10.236秒
select * from cf_qb_info limit 200000,20
3.深度ID分頁:耗時0.052秒
提示:如果這一步很慢,count(1) 查詢總數(shù)應(yīng)該也會很慢-解決方式:請為主鍵加上unique索引。
-- 主鍵ID字段:NUMID select NUMID from cf_qb_info limit 200000,20
4.兩步走深度分頁:耗時0.049秒+0.017秒
基于第三步的缺陷(只能查出ID信息),我們可以先查出分頁數(shù)據(jù)的ID,在根據(jù)ID查詢數(shù)據(jù)。
select NUMID from cf_qb_info LIMIT 200000,20
select * from cf_qb_info where NUMID in ( '330681650000202108180227345510', '330681650000202108171031534500', '330681650000202108190251532141', '330681650000202108200246376830', '330681650000202108210229398665', '330681650000202108220236113895', '330681650000202108230230034133', '330681650000202108231017279739', '330681650000202108231043456276', '330681650000202108231051404340', '330681650000202108240237397251', '330681650000202108250221489228', '330681650000202108250241536726', '330681650000202108260253039326', '330681650000202108270216016138', '330681650000202108280234013754', '330681650000202108290230029720', '330681650000202108300255579204', '330681650000202108310234184991', '330681650000202109010237315937' );
兩步合成一步SQL耗時:11.9秒;這一步著實出乎了我的意料。
select * from cf_qb_info where NUMID in ( select NUMID from (select NUMID from cf_qb_info LIMIT 200000,20) as t );
鑒于這個結(jié)果:我們可以在程序里分成兩步進行分頁查詢。
5.一步走深度分頁:耗時0.05秒
這一步是對第四步的優(yōu)化,畢竟兩條SQL還需要碼代碼。利用join 兩條SQL合成一條。
SELECT * FROM cf_qb_info a JOIN ( SELECT NUMID FROM cf_qb_info LIMIT 200000, 20 ) b ON a.NUMID = b.NUMID
6.集成BeanSearcher框架
原理是使用了BeanSearcher的sql攔截器對SQL進行攔截改造。
①改造Bean
②注入Sql攔截器
package com.ciih.qbbs.config; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.annotation.TableId; import com.ejlchina.searcher.SearchSql; import com.ejlchina.searcher.SqlInterceptor; import com.ejlchina.searcher.SqlSnippet; import com.ejlchina.searcher.param.FetchType; import org.springframework.stereotype.Component; import java.lang.reflect.Field; import java.util.List; import java.util.Map; /** * BeanSearcher的Sql攔截器:優(yōu)化深度分頁 * * @author sunziwen */ @Component public class SqlInterceptorImpl implements SqlInterceptor { @Override public <T> SearchSql<T> intercept(SearchSql<T> searchSql, Map<String, Object> paraMap, FetchType fetchType) { /** * 改造思路 * * <> * 前:SELECT * FROM table1 t1 LIMIT 200000,20; * 后:SELECT * FROM table1 t1 JOIN ( SELECT id FROM table1 LIMIT 200000, 20 ) t99 ON t1.id = t99.id; * </> */ Field[] fields = searchSql.getBeanMeta().getBeanClass().getDeclaredFields(); String primaryColumnName = null; for (Field field : fields) { //這里使用了mybatis_plus的注解作為主鍵標(biāo)識 TableId tableId = field.getAnnotation(TableId.class); if (tableId != null) { if (!"".equals(tableId.value())) { primaryColumnName = tableId.value(); } else { //駝峰轉(zhuǎn)下劃線 primaryColumnName = StrUtil.toUnderlineCase(field.getName()); } } } //如果沒有主鍵標(biāo)識,則不能進行SQL優(yōu)化。 if (primaryColumnName == null) { return searchSql; } //正則表達式獲取where之后語句 List<String> limits = ReUtil.findAll("where[\\s\\S]*limit[ ]+[?]{1}[ ]*,[ ]+[?]{1}", searchSql.getListSqlString(), 0); //如果不分頁,則不進行SQL優(yōu)化,即語句中沒有l(wèi)imit關(guān)鍵字不優(yōu)化。 if (limits.size() == 0) { return searchSql; } //表名小片段 SqlSnippet tableSnippet = searchSql.getBeanMeta().getTableSnippet(); //合成子查詢SQL String inSql = "JOIN ( SELECT " + primaryColumnName + " FROM " + tableSnippet.getSql() + " " + limits.get(0) + " ) t99 ON t1." + primaryColumnName + " = t99." + primaryColumnName + ";"; //合成整條SQL String replace = searchSql.getListSqlString().replace(limits.get(0), inSql); //替換 searchSql.setListSqlString(replace); return searchSql; } }
7.萬能優(yōu)化技巧:索引
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
DBeaver如何實現(xiàn)導(dǎo)入excel中的大量數(shù)據(jù)
使用DBeaver導(dǎo)入Excel數(shù)據(jù)需先將文件轉(zhuǎn)換為CSV格式,詳細步驟包括:將Excel文件另存為CSV,確保列名與數(shù)據(jù)庫表字段對應(yīng),然后在DBeaver中創(chuàng)建表和導(dǎo)入CSV文件,注意選擇正確的編碼格式以防中文亂碼2024-10-10MySQL數(shù)據(jù)庫表的合并與分區(qū)實現(xiàn)介紹
今天我們來聊聊處理大數(shù)據(jù)時Mysql的存儲優(yōu)化。當(dāng)數(shù)據(jù)達到一定量時,一般的存儲方式就無法解決高并發(fā)問題了。最直接的MySQL優(yōu)化就是分區(qū)分表,以下是我個人對分區(qū)分表的筆記2022-09-09MySQL中的常用樹形結(jié)構(gòu)設(shè)計總結(jié)
這篇文章主要介紹了MySQL中的常用樹形結(jié)構(gòu)設(shè)計總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03mysql-connector-java與Mysql、Java的對應(yīng)版本問題
這篇文章主要介紹了mysql-connector-java與Mysql、Java的對應(yīng)版本問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11mysql數(shù)據(jù)庫備份命令分享(mysql壓縮數(shù)據(jù)庫備份)
這篇文章主要介紹了mysql數(shù)據(jù)庫備份常用語句,包括數(shù)據(jù)庫壓縮備份、備份多個MySQL數(shù)據(jù)庫、備份多個MySQL數(shù)據(jù)庫、將數(shù)據(jù)庫轉(zhuǎn)移到新服務(wù)器等語句2014-01-01MySQL同步數(shù)據(jù)Replication的實現(xiàn)步驟
本文主要介紹了MySQL同步數(shù)據(jù)Replication的實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03集群運維自動化工具ansible使用playbook安裝mysql
本文主要介紹了如何使用playbook安裝mysql,需要的朋友可以參考下2014-07-07