欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql大數(shù)據(jù)量查詢優(yōu)化思路詳析

 更新時(shí)間:2022年01月26日 11:03:02   作者:老司機(jī)張師傅?  
這篇文章主要介紹了Mysql大數(shù)據(jù)量查詢優(yōu)化思路,Mysql大表查詢優(yōu)化,理論上千萬級(jí)別以下的數(shù)據(jù)量Mysql單表查詢性能處理都是可以的。下文我們就來看看具體得思路解析

項(xiàng)目場(chǎng)景:

Mysql大表查詢優(yōu)化,理論上千萬級(jí)別以下的數(shù)據(jù)量Mysql單表查詢性能處理都是可以的。

問題描述:

在我們線上環(huán)境中,出現(xiàn)了mysql幾千萬級(jí)別的日志查詢、幾百萬級(jí)別的黑名單庫查詢分頁查詢及條件查詢都慢的問題,針對(duì)Mysql表優(yōu)化做了一些優(yōu)化處理。

原因分析:
首先說一下日志查詢,在Mysql中如果索引加的比較合適,走索引情況下千萬級(jí)別查詢不會(huì)超過一秒,Mysql查詢的速度和檢索的數(shù)據(jù)條數(shù)有關(guān)。在Mybatis中,分頁查詢是先執(zhí)行Count記錄總數(shù),再執(zhí)行l(wèi)imit a,b 的方式來進(jìn)行的,而Mysql的Count計(jì)數(shù)方式是將所有的數(shù)據(jù)過濾一遍進(jìn)行累加,因此當(dāng)日志表數(shù)據(jù)過千萬時(shí),統(tǒng)計(jì)一次就是十幾秒鐘的時(shí)間(這里是服務(wù)器環(huán)境,本地情況下甚至是幾分鐘)。
limit a,b的方式也一樣,Mysql查詢時(shí)會(huì)先一條一條數(shù)到第a條,然后向后再數(shù)b條作為查詢結(jié)果,因此當(dāng)起始行數(shù)越來越大時(shí)查詢同樣會(huì)變得很慢,也就是當(dāng)你點(diǎn)第一頁時(shí)可能一下就查出來了,當(dāng)你點(diǎn)最后一頁的時(shí)候可能幾十秒才能查出來。
黑名單庫查詢優(yōu)化同理,也是需要通過條件優(yōu)化。
在進(jìn)行大批量數(shù)據(jù)落庫時(shí),使用的Mybatis批量插入,發(fā)現(xiàn)當(dāng)批次數(shù)據(jù)超過3000時(shí)速度會(huì)急劇變慢,這是一個(gè)Mybatis娘胎里自帶的問題,也需要進(jìn)行解決。

解決方案:

這里只簡(jiǎn)單說明優(yōu)化的幾個(gè)方向。

1. 千萬級(jí)別日志查詢的優(yōu)化

  1. 首先說下日志查詢,重點(diǎn)是優(yōu)化無條件是分頁查詢,在無條件時(shí),不使用MyBatis的分頁插件,而是自己手寫一個(gè)分頁查詢,由于MySql的count耗時(shí)過長(zhǎng),我們先優(yōu)化他。
  2. 優(yōu)化Count:日志表的數(shù)據(jù)只增,不會(huì)出現(xiàn)中間某條刪除,所以他的數(shù)據(jù)可以理解成是連續(xù)的,我們可以在內(nèi)存中直接進(jìn)行計(jì)數(shù),記錄count總數(shù),或者給表添加一個(gè)自增的ID字段,直接select max(id)就是總數(shù)量,這樣count查詢的效率會(huì)提升到毫秒級(jí)別。
  3. 自定義分頁查詢:分頁查詢中使用優(yōu)化后的count記錄總數(shù),然后使用(page - 1)* pageSize + 1公式計(jì)算出當(dāng)前頁的最小ID,然后將limit a,b 的Sql語句改為where ID > 最小ID limit b的方式,這樣查詢就會(huì)走索引先將小于最小ID的數(shù)據(jù)過濾掉,再進(jìn)行查詢,經(jīng)過第二步和第三步的優(yōu)化后分頁查詢效率縮短到了一秒內(nèi),并且不會(huì)隨著頁數(shù)的增長(zhǎng)而變慢。
  4. 條件查詢:條件查詢只能設(shè)置合適的索引,另外慎用like '%條件%‘的方式進(jìn)行匹配查詢,這樣會(huì)導(dǎo)致索引失效全局檢索,模糊查詢盡量使用like '條件%' 的方式進(jìn)行最左匹配,也可以使用explain+sql語句 的方式來查看sql語句的執(zhí)行效率,是否走了所有啥的來針對(duì)性的優(yōu)化,加好合適的索引、優(yōu)化查詢語句后通常一千萬以內(nèi)的數(shù)據(jù)查詢效率會(huì)在3秒內(nèi)。

粘出自定義分頁查詢結(jié)果封裝:

?// 手動(dòng)count
? ? ? ? ? ? ? ? Integer total = logPushService.queryBackCount(resMap);//查詢數(shù)量
? ? ? ? ? ? ? ? // 手動(dòng)查詢結(jié)果
? ? ? ? ? ? ? ? List<InterceptInfo> ls = logPushService.queryBackByPage(resMap);
? ? ? ? ? ? ? ? PageInfo pageInfo = new PageInfo();
? ? ? ? ? ? ? ? pageInfo.setTotal(total);
? ? ? ? ? ? ? ? pageInfo.setPageSize(limit);
? ? ? ? ? ? ? ? pageInfo.setList(ls);
? ? ? ? ? ? ? ? pageInfo.setPageNum(pn);

2. 幾百萬黑名單庫的查詢優(yōu)化

  • 黑名單庫查詢優(yōu)化只能通過加合適的索引和優(yōu)化SQL語句來優(yōu)化,百萬級(jí)別數(shù)據(jù)松松的在Mysql和Mybatis的承受范圍內(nèi),這里是由于黑名單庫不是使用遞增的,有可能會(huì)增加也有可能會(huì)刪除,所以只能使用優(yōu)化索引和SQL的方式進(jìn)行優(yōu)化。
  • 另外,Mybatis框架提供了重寫分頁查詢count統(tǒng)計(jì)語句的方法,只需要將count語句命名為查詢方法_COUNT即可,例如分頁查詢的語句方法是query,那么重寫的統(tǒng)計(jì)方法即為query_COUNT

 <select id="query_COUNT" parameterType="java.util.Map" resultType="java.lang.Long">
? ? ? ? SELECT
? ? ? ? count(0)
? ? ? ? from nms_intercept_info${map.week}
? ? ? ? where 1=1
? ? ? ? <if test="map.id!=null and map.id!='' ">
? ? ? ? ? ? AND id>#{map.id}
? ? ? ? </if>
? ? ? ? <if test="map.url!=null and map.url!='' ">
? ? ? ? ? ? AND spliturl=#{map.url}
? ? ? ? </if>
? ? ? ? <if test="map.startTime!=null and map.startTime!='' ">
? ? ? ? ? ? AND time <![CDATA[>=]]> #{map.startTime}
? ? ? ? </if>
? ? ? ? <if test="map.endTime!=null and map.endTime!='' ">
? ? ? ? ? ? AND time <![CDATA[<=]]> #{map.endTime}
? ? ? ? </if>
? ? ? ? <if test="map.type!=null and map.type!='' ">
? ? ? ? ? ? AND bigType = #{map.type}
? ? ? ? </if>
? ? </select>

3. Mybatis批量插入處理問題

Mybatis批量插入語句中的類集合大小不能超過五千,三千是最佳,這是測(cè)試出來的結(jié)果,考慮到的原因是Mybatis會(huì)將類做反射,這個(gè)太影響效率,因此批量插入時(shí)要注意這個(gè),如果你能夠三千三千的批量處理就限制一下,不要讓每批數(shù)據(jù)超過3000,數(shù)據(jù)量過大時(shí)也可以使用異步非阻塞的方式來插入。
異步非阻塞代碼(只是步驟樣例,存在代碼缺失):

? ? // 執(zhí)行全量HMD導(dǎo)入任務(wù)的線程池
? ? public final static ExecutorService importHasPool = Executors.newFixedThreadPool(10);
? ? public final static CompletionService<DoExcelResult> importHasPoolService = new ExecutorCompletionService<>(importHasPool);
? ??
? ?public synchronized DoExcelResult example() {
? ? ? ? ? ? // 開始執(zhí)行導(dǎo)入
? ? ? ? ? ? // 寫到這里面方法最后會(huì)自動(dòng)關(guān)閉
? ? ? ? ? ? long startTime = System.currentTimeMillis();
? ? ? ? ? ? // 定義一個(gè)集合,記錄Callable的執(zhí)行結(jié)果,Callable是帶返回值的Runable
? ? ? ? ? ? List<Future<DoExcelResult>> futures = new ArrayList<>();
? ? ? ? ? ? while ((str = reader.readLine()) != null) {
? ? ? ? ? ? ? ? if (list.size() > 5000) { // 5000插入一次
? ? ? ? ? ? ? ? ? ? List<String> list1 = CollectionUtil.copyDepth(list);
? ? ? ? ? ? ? ? ? ? list.clear();
? ? ? ? ? ? ? ? ? ? // BlackInfoHasImportlCallable是實(shí)現(xiàn)了Callable接口的實(shí)現(xiàn)類,Callable是帶返回值的Runable
? ? ? ? ? ? ? ? ? ? Future submit = SysThreadPoolCenter.importHasPoolService.submit(new BlackInfoHasImportlCallable(list1, blacklistInfoMapper));
? ? ? ? ? ? ? ? ? ? futures.add(submit);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? // 等待執(zhí)行結(jié)果
? ? ? ? ? ? for (Future<DoExcelResult> future : futures) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 2. futrue.get時(shí)會(huì)獲取返回值,線程沒執(zhí)行完畢就等待等待執(zhí)行結(jié)果
? ? ? ? ? ? ? ? ? ? DoExcelResult doExcelResult = future.get();
? ? ? ? ? ? ? ? ? ? result.setSuccessNum(result.getSuccessNum() + doExcelResult.getSuccessNum());
? ? ? ? ? ? ? ? ? ? result.setContinueNum(result.getContinueNum() + doExcelResult.getContinueNum());
? ? ? ? ? ? ? ? ? ? result.setErrorNum(result.getErrorNum() + doExcelResult.getErrorNum());
? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? log.error(e);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? // 循環(huán)結(jié)束代表所有線程執(zhí)行完畢
? ? ? ? ? ? result.setTimeCon((System.currentTimeMillis() - startTime)/1000.0);
? ? ? ? ? ? BlacklistService.isDoing = false;
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? BlacklistService.isDoing = false;
? ? ? ? ? ? log.error(e);
? ? ? ? }
? ? ? ? BlacklistService.isDoing = false;
? ? ? ? return result;
? ? }

限制每批3000條:

 if (ls.size() >= 3000) {
? ? ? ? ? ? //每次保存3000
? ? ? ? ? ? double sum = Math.ceil(ls.size() / 3000f);
? ? ? ? ? ? for (int i = 0; i < sum; i++) {
? ? ? ? ? ? ? ? total += blacklistDao.saveBatch(ls.subList(i * 3000, ((i + 1) * 3000) > ls.size() ? ls.size() : (i + 1) * 3000));
? ? ? ? ? ? }
? ? ? ? } else {
? ? ? ? ? ? total = blacklistDao.saveBatch(ls);
? ? ? ? }

如果你數(shù)據(jù)庫用的不是mysql,而是CK或者其他的大數(shù)據(jù)處理數(shù)據(jù)庫,批量插入可能要求每秒幾萬條幾十萬條,這時(shí)就不再適合使用Myabtis框架了,建議使用JDBC連接的方式,自己寫代碼拼接sql語句,再使用jdbc連接執(zhí)行(使用線程池),效率上會(huì)快很多。

到此這篇關(guān)于Mysql大數(shù)據(jù)量查詢優(yōu)化思路詳析的文章就介紹到這了,更多相關(guān)Mysql大數(shù)據(jù)量查詢優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Linux環(huán)境下安裝MySQL8.0的完整步驟

    Linux環(huán)境下安裝MySQL8.0的完整步驟

    數(shù)據(jù)庫想必大家都很熟悉,但是要在服務(wù)器上自己來安裝數(shù)據(jù)庫,還是會(huì)出現(xiàn)不少的問題,下面這篇文章主要給大家介紹了關(guān)于在Linux環(huán)境下安裝MySQL8.0的完整步驟,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • MySQL group by對(duì)單字分組序和多字段分組的方法講解

    MySQL group by對(duì)單字分組序和多字段分組的方法講解

    今天小編就為大家分享一篇關(guān)于MySQL group by對(duì)單字分組序和多字段分組的方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • Mysql優(yōu)化order by語句的方法詳解

    Mysql優(yōu)化order by語句的方法詳解

    本篇文章我們將了解ORDER BY語句的優(yōu)化,在文中給大家提到了mysql中的兩種排序方式,需要的朋友參考下吧
    2018-08-08
  • MySQL自動(dòng)安裝腳本代碼實(shí)例分享

    MySQL自動(dòng)安裝腳本代碼實(shí)例分享

    這篇文章主要介紹了MySQL自動(dòng)安裝腳本代碼實(shí)例分享的相關(guān)資料,需要的朋友可以參考下
    2023-07-07
  • mysql 查看版本的方法圖文演示

    mysql 查看版本的方法圖文演示

    今天打算升級(jí)下mysql數(shù)據(jù)庫,可不知道現(xiàn)在的版本是多少,從網(wǎng)上找了一些資料,發(fā)現(xiàn)還是這些好用。
    2010-04-04
  • mysql8.0.11數(shù)據(jù)目錄遷移的實(shí)現(xiàn)

    mysql8.0.11數(shù)據(jù)目錄遷移的實(shí)現(xiàn)

    這篇文章主要介紹了mysql8.0.11數(shù)據(jù)目錄遷移的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • MySQL如何利用DCL管理用戶和控制權(quán)限

    MySQL如何利用DCL管理用戶和控制權(quán)限

    這篇文章主要介紹了MySQL如何利用DCL管理用戶和控制權(quán)限,幫助大家更好的理解和學(xué)習(xí)MySQL的使用,感興趣的朋友可以了解下
    2020-11-11
  • SQL實(shí)戰(zhàn)演練之網(wǎng)上商城數(shù)據(jù)庫用戶信息數(shù)據(jù)操作

    SQL實(shí)戰(zhàn)演練之網(wǎng)上商城數(shù)據(jù)庫用戶信息數(shù)據(jù)操作

    一直認(rèn)為,扎實(shí)的SQL功底是一名數(shù)據(jù)分析師的安身立命之本,甚至可以稱得上是所有數(shù)據(jù)從業(yè)者的基本功。當(dāng)然,這里的SQL絕不單單是寫幾條查詢語句那么簡(jiǎn)單,接下來請(qǐng)跟著小編通過案例項(xiàng)目進(jìn)一步提高SQL的能力吧
    2021-10-10
  • MySQL中Stmt 預(yù)處理提高效率問題的小研究

    MySQL中Stmt 預(yù)處理提高效率問題的小研究

    在oracle數(shù)據(jù)庫中,有一個(gè)變量綁定的用法,很多人都比較熟悉,可以調(diào)高數(shù)據(jù)庫效率,應(yīng)對(duì)高并發(fā)等,好吧,這其中并不包括我,當(dāng)同事問我MySQL中有沒有類似的寫法時(shí),我是很茫然的,于是就上網(wǎng)查,找到了如下一種寫法
    2011-08-08
  • MySQL8.0.23免安裝版配置詳細(xì)教程

    MySQL8.0.23免安裝版配置詳細(xì)教程

    這篇文章主要介紹了MySQL8.0.23免安裝版配置教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03

最新評(píng)論