0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

QPS提升10倍的sql優(yōu)化

京東云 ? 來源:jf_75140285 ? 作者:jf_75140285 ? 2024-08-21 11:12 ? 次閱讀

本次慢sql優(yōu)化是大促準(zhǔn)備時(shí)的一個(gè)優(yōu)化,優(yōu)化4c16g單實(shí)例mysql支持QPS從437到4610,今天發(fā)文時(shí)618大促已經(jīng)順利結(jié)束,該mysql庫和應(yīng)用在整個(gè)大促期間運(yùn)行也非常穩(wěn)定。本文復(fù)盤一下當(dāng)時(shí)的sql優(yōu)化過程

1. 問題背景

大促準(zhǔn)備期間發(fā)現(xiàn)4c16G的單實(shí)例mysql數(shù)據(jù)庫,每逢流量高峰都會(huì)有cpu 100%的問題,集中在0點(diǎn)和12點(diǎn)。

但也存在相近大小的流量cpu利用率相差很大的情況:從圖中可見在5.12日0點(diǎn)查詢437QPS時(shí)cpu利用率達(dá)到100%,而5.12日15:02分時(shí) 625QPS時(shí)CPU利用率不到20%

可見應(yīng)該是查詢語句有差異造成CPU利用率高,而此時(shí)并沒有慢sql出現(xiàn)。

wKgaombFWxCAYtW-AADyzYog65Q806.png


2. 問題分析

2.1 分析應(yīng)用請(qǐng)求及日志

通過應(yīng)用監(jiān)控看到0點(diǎn)時(shí)流量大,很多路由排班表的本地緩存沒有命中,導(dǎo)致查詢較多。所以想到是否可以通過提高緩存命中率,減少sql查詢,以降低CPU利用率。調(diào)整緩存大小,和緩存的有效期。經(jīng)過測(cè)試驗(yàn)證仍然沒有解決問題

2.2 分析sql

雖然沒有慢sql出現(xiàn),但還是分析了下sql。經(jīng)分析sql 查詢是不是用了索引,發(fā)現(xiàn)查詢字段也是“走了idx_road_site索引”的(注意這里是引號(hào),其實(shí)索引并未完全生效)

表結(jié)構(gòu)及索引如下

CREATE TABLE `road_schedule` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵', `courier_id` VARCHAR(240) DEFAULT NULL COMMENT 'courier_id', `courier_name` VARCHAR(240) DEFAULT NULL COMMENT 'courier_name', `road_id` VARCHAR(240) DEFAULT NULL COMMENT 'road_id', `site_id` VARCHAR(240) DEFAULT NULL COMMENT 'site_id', `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間', `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新時(shí)間', `ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '時(shí)間戳', PRIMARY KEY (`id`), KEY `idx_road_site` (`road_id` , `site_id`) ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8

代碼sql如下:

@Select("select courier_id,courier_name,road_id,site_id from road_schedule where road_id = #{roadId} and site_id = #{siteId} order by id desc limit 1") RoadScheduleDto getRoadScheduleById(@Param("roadId")String roadId, @Param("siteId")Integer siteId);

2.3 分析mysql連接數(shù)指標(biāo)

前兩步都沒定位到原因,繼續(xù)分析mysql其他監(jiān)控指標(biāo)。

wKgZombFWxOAbrwiAAEjWW8783c244.png


從上圖mysql監(jiān)控發(fā)現(xiàn)0點(diǎn)時(shí)連接數(shù)突增,所以分析是不是有沒有提前創(chuàng)建數(shù)據(jù)庫連接。修改應(yīng)用連接池配置,單應(yīng)用最少空閑連接為50,應(yīng)用有4個(gè)實(shí)例,這樣整個(gè)數(shù)據(jù)庫連接數(shù)在4*50=200個(gè)以上,大于圖中突增后的總連接數(shù)100

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.initial-size=50 spring.datasource.druid.min-idle=50 spring.datasource.druid.max-active=200 spring.datasource.druid.keep-alive=true spring.datasource.druid.validation-query=select 1 spring.datasource.druid.filters=stat,log4j2

但是驗(yàn)證后仍然沒有解決問題,就犯難了。但是思考原因可能就上面這三點(diǎn),卻沒有解決問題。所以又回過來繼續(xù)從新分析檢查,同時(shí)也做好了升級(jí)CPU為8核再試的心理準(zhǔn)備。

2.4 sql優(yōu)化--誤入歧途--意外暴露問題

再次分析查詢語句,懷疑是不是排序的字段沒有走索引,所以將sql做了如下調(diào)整,并分析了執(zhí)行計(jì)劃

#應(yīng)用中sql select * from road_schedule where site_id = '19275xxx' and road_id = '02xx' order by ts desc limit 1; #認(rèn)為的按id排序更好的sql select * from road_schedule where site_id = '19275xxx' and road_id = '02xx' order by id desc limit 1;

從執(zhí)行計(jì)劃看按ts排序 Extra 信息為 Using index condition; Using filesort 猜測(cè)按文件排序是不是影響查詢的原因

wKgaombFWxWAcXKOAAFrjfz_U9I331.png


按id排序的執(zhí)行計(jì)劃如下,Extra信息為 Using where

對(duì)比兩個(gè)執(zhí)行計(jì)劃又都用到了idx_road_site索引,所以猜測(cè)按id排序肯定會(huì)快一點(diǎn)

wKgZombFWxaAImluAAFf9VTGl_4698.png


事與愿違,慢sql出現(xiàn)了

從優(yōu)化建議可以看出按id排序時(shí),優(yōu)先使用了主鍵索引,并沒有使用idx_road_site索引,所以造成了慢sql。但同時(shí)原始sql也顯而易見的展現(xiàn)在了眼前,發(fā)現(xiàn)組合索引idx_road_site的第二個(gè)字段site_id 和表中`site_id` VARCHAR(240) DEFAULT NULL COMMENT '站點(diǎn)id',字段類型并不一致

sql中site_id傳參為整型,表中字段為字符串類型,所以斷定是字段類型不一致造成的索引失效

select courier_id,courier_name,road_id,site_id from road_schedule where road_id = 'xxx' and site_id = xxxxx order by id desc limit 1;

wKgaombFWxeAVTgBAAUk3sCfShY546.png

2.5 sql修復(fù)驗(yàn)證

上一步已經(jīng)定位到原因,修復(fù)sql如下,siteId傳參類型為字符串類型

@Select("select courier_id,courier_name,road_id,site_id from road_schedule where road_id = #{roadId} and site_id = #{siteId} order by ts desc limit 1") RoadScheduleDto getRoadScheduleById(@Param("roadId")String roadId, @Param("siteId")String siteId);

經(jīng)驗(yàn)證完成,完美解決CPu利用率在0點(diǎn)高的問題。在0點(diǎn)時(shí)4c16g數(shù)據(jù)庫實(shí)例輕松支持1420QPS 的查詢,CPU利用率在20%以下

wKgZombFWxqAaGdFAAC79g-SpkE465.png


后又觀測(cè)到4c16g支持4610QPS都沒有問題,至此不但優(yōu)化了SQL,還節(jié)約了實(shí)例升級(jí)帶來的機(jī)器成本。

wKgaombFWxqAeMkxAADAA9mZFRQ074.png


3. 總結(jié)

總結(jié)本次優(yōu)化經(jīng)歷

?慢sql 往往是影響數(shù)據(jù)庫性能的大瓶頸,sql寫好了不但可以優(yōu)化性能,還能節(jié)約機(jī)器成本,降本增效。

?最好能看到sql語句執(zhí)行的第一現(xiàn)場(chǎng),本次主要是由于查看代碼時(shí)沒有及時(shí)注意到索引字段的傳參類型不對(duì)這一細(xì)節(jié),造成花了很多時(shí)間分析問題

?雖然整個(gè)問題分析過程比較曲折,但問題分析的方向應(yīng)該還是對(duì)的,過程中學(xué)到不少知識(shí)。

?表結(jié)構(gòu)的設(shè)計(jì)也有一些歷史遺留原因,site_id 字段在表中定義為整型可能比較符合業(yè)務(wù)含義。表字段定義和業(yè)務(wù)含義一致,寫sql也不容易犯錯(cuò)


歡迎大家評(píng)論交流!

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    750

    瀏覽量

    43900
  • QPS
    QPS
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    8777
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    數(shù)據(jù)庫SQL優(yōu)化

    數(shù)據(jù)庫執(zhí)行SQL都會(huì)先進(jìn)行語義解析,然后將SQL分成一步一步可執(zhí)行的計(jì)劃,然后逐步執(zhí)行。通過分析執(zhí)行計(jì)劃,我們可以清晰的看到數(shù)據(jù)庫執(zhí)行的操作,這對(duì)于數(shù)據(jù)庫SQL優(yōu)化具有重大意義。 1
    的頭像 發(fā)表于 10-09 15:43 ?940次閱讀
    數(shù)據(jù)庫<b class='flag-5'>SQL</b>的<b class='flag-5'>優(yōu)化</b>

    MySQL的執(zhí)行過程 SQL語句性能優(yōu)化常用策略

    回顧 MySQL 的執(zhí)行過程,幫助介紹如何進(jìn)行 sql 優(yōu)化
    的頭像 發(fā)表于 12-12 10:26 ?536次閱讀
    MySQL的執(zhí)行過程 <b class='flag-5'>SQL</b>語句性能<b class='flag-5'>優(yōu)化</b>常用策略

    2017雙11技術(shù)揭秘—TDDL/DRDS 的類 KV 查詢優(yōu)化實(shí)踐

    能做到大幅度提升,是因?yàn)椴樵兺耆@開了 SQL 在 MySQL Server 層的各項(xiàng)開銷,查詢鏈路被極致縮短,事實(shí)上,這樣的優(yōu)化思路對(duì) TDDL/DRDS 也同樣適用。TDDL/DRDS 目前
    發(fā)表于 12-29 14:29

    第三代DRDS分布式SQL引擎全新發(fā)布

    SQL 優(yōu)化策略,一些重要的例如:對(duì) Filter 的上拉、下壓、推導(dǎo)等優(yōu)化,確保 DRDS 可以準(zhǔn)確的識(shí)別出 SQL 中可以下推的部分,這個(gè)能很大程度上
    發(fā)表于 05-28 20:35

    Spark SQL的工作原理和性能優(yōu)化

    Spark SQL(九):工作原理和性能優(yōu)化
    發(fā)表于 06-12 16:21

    30種SQL語句優(yōu)化總結(jié)

    必須掌握的30種SQL語句優(yōu)化
    發(fā)表于 04-21 11:38

    數(shù)據(jù)庫設(shè)計(jì)及開發(fā)規(guī)范之sql性能優(yōu)化

    數(shù)據(jù)庫設(shè)計(jì)及開發(fā)規(guī)范,sql性能優(yōu)化
    發(fā)表于 05-08 10:58

    SQL語句怎么優(yōu)化

    SQL語句優(yōu)化——結(jié)合書籍論壇小結(jié)
    發(fā)表于 06-14 14:46

    內(nèi)存條配置優(yōu)化SQL Server服務(wù)器性能

    內(nèi)存條配置優(yōu)化SQL Server服務(wù)器性能  Microsoft SQL Server 2000 的 內(nèi)存管理組件消除了對(duì) SQL Server 可用的內(nèi)存進(jìn)行手工管理的需要。
    發(fā)表于 01-11 11:00 ?864次閱讀

    基于SQL Server的中文分詞系統(tǒng)設(shè)計(jì)及應(yīng)用

    隨著當(dāng)前信息化技術(shù)的發(fā)展,優(yōu)化設(shè)計(jì)中文分析系統(tǒng)已成為必然趨勢(shì),有助于提升網(wǎng)絡(luò)索引擎面對(duì)中文信息的檢索能力,本篇中將分析基于SQL Server的中文分詞系統(tǒng)設(shè)計(jì)需求,從而優(yōu)化設(shè)計(jì)中文分
    發(fā)表于 11-14 17:46 ?2708次下載
    基于<b class='flag-5'>SQL</b> Server的中文分詞系統(tǒng)設(shè)計(jì)及應(yīng)用

    SQL后悔藥,SQL性能優(yōu)化SQL規(guī)范優(yōu)雅

    每一個(gè)好習(xí)慣都是一筆財(cái)富,本文基于MySQL,分SQL后悔藥, SQL性能優(yōu)化,SQL規(guī)范優(yōu)雅三個(gè)方向,分享寫SQL的21個(gè)好習(xí)慣,謝謝閱讀
    的頭像 發(fā)表于 11-14 09:54 ?1738次閱讀

    SQL子查詢優(yōu)化是怎么回事

    子查詢 (Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點(diǎn)之一。 關(guān)聯(lián)子查詢的基本執(zhí)行方式類似于 Nested-Loop,但是這種執(zhí)行方式的效率常常低到難以忍受。 當(dāng)數(shù)據(jù)量稍大時(shí),必須
    的頭像 發(fā)表于 02-01 13:55 ?1956次閱讀
    <b class='flag-5'>SQL</b>子查詢<b class='flag-5'>優(yōu)化</b>是怎么回事

    SQL優(yōu)化技巧分享

    一、查詢SQL盡量不要使用select *,而是具體字段
    的頭像 發(fā)表于 09-06 10:24 ?1296次閱讀

    一文終結(jié)SQL子查詢優(yōu)化

    子查詢(Subquery)的優(yōu)化一直以來都是 SQL 查詢優(yōu)化中的難點(diǎn)之一。關(guān)聯(lián)子查詢的基本執(zhí)行方式類似于 Nested-Loop,但是這種執(zhí)行方式的效率常常低到難以忍受。
    的頭像 發(fā)表于 04-28 14:19 ?632次閱讀
    一文終結(jié)<b class='flag-5'>SQL</b>子查詢<b class='flag-5'>優(yōu)化</b>

    Oracle長耗時(shí)SQL優(yōu)化案例

    最近在生產(chǎn)客服平臺(tái),運(yùn)營崗老師反饋,一個(gè)2w人的企業(yè),在信息詳情查詢時(shí),加載時(shí)間過長,越70s左右出結(jié)果,需要后臺(tái)優(yōu)化SQL。
    的頭像 發(fā)表于 05-19 15:02 ?928次閱讀