自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

慢查詢 MySQL 定位優(yōu)化技巧,從10s優(yōu)化到300ms

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
我們可以用force index強(qiáng)制指定索引,然后去分析執(zhí)行計(jì)劃看看哪個(gè)索引是更好的,因?yàn)椴樵儍?yōu)化器選擇索引不一定是百分百準(zhǔn)確的,具體情況可以根據(jù)實(shí)際場(chǎng)景分析來確定是否使用查詢優(yōu)化器選擇的索引。

今天分享一下如何快速定位慢查詢SQL以及優(yōu)化。

一、如何定位并優(yōu)化慢查詢SQL?

一般有3個(gè)思考方向:

  • 根據(jù)慢日志定位慢查詢sql。
  • 使用explain等工具分析sql執(zhí)行計(jì)劃。
  • 修改sql或者盡量讓sql走索引。

二、如何使用慢查詢?nèi)罩荆?/h3>

先給出步驟,后面說明,有3個(gè)步驟

1. 開啟慢查詢?nèi)罩?/h4>

首先開啟慢查詢?nèi)罩?,由參?shù)slow_query_log決定是否開啟,在MySQL命令行下輸入下面的命令:

set global slow_query_log=on;

默認(rèn)環(huán)境下,慢查詢?nèi)罩臼顷P(guān)閉的,所以這里開啟。

2. 設(shè)置慢查詢閾值

set global long_query_time=1;

只要你的SQL實(shí)際執(zhí)行時(shí)間超過了這個(gè)閾值,就會(huì)被記錄到慢查詢?nèi)罩纠锩妗_@個(gè)閾值默認(rèn)是10s,線上業(yè)務(wù)一般建議把long_query_time設(shè)置為1s,如果某個(gè)業(yè)務(wù)的MySQL要求比較高的QPS,可設(shè)置慢查詢?yōu)?.1s。

發(fā)現(xiàn)慢查詢及時(shí)優(yōu)化或者提醒開發(fā)改寫。一般測(cè)試環(huán)境建議long_query_time設(shè)置的閥值比生產(chǎn)環(huán)境的小,比如生產(chǎn)環(huán)境是1s,則測(cè)試環(huán)境建議配置成0.5s。便于在測(cè)試環(huán)境及時(shí)發(fā)現(xiàn)一些效率的SQL。

甚至某些重要業(yè)務(wù)測(cè)試環(huán)境long_query_time?可以設(shè)置為0,以便記錄所有語句。并留意慢查詢?nèi)罩镜妮敵觯暇€前的功能測(cè)試完成后,分析慢查詢?nèi)罩久款愓Z句的輸出,重點(diǎn)關(guān)注Rows_examined(語句執(zhí)行期間從存儲(chǔ)引擎讀取的行數(shù)),提前優(yōu)化。

3.確定慢查詢?nèi)罩镜奈募吐窂?/h4>
show global variables like 'slow_query_log_file'

圖片

結(jié)果會(huì)發(fā)現(xiàn)慢日志默認(rèn)路徑就是MySQL的數(shù)據(jù)目錄,我們可以來看一下MySQL數(shù)據(jù)目錄。

 show global variables like 'datadir';

圖片

不用關(guān)注這里為什么不是MySQL 8.0,這和版本沒什么關(guān)系的。

來,直接上菜,干巴巴的定義我自己都看不下去。

我們先來查看一下變量,我框出了需要注意的點(diǎn)。

查詢帶有quer的相關(guān)變量:

show global variables like '%quer%';

圖片

圖片

這里設(shè)置慢查詢閾值為1s:

set global long_query_time=1;

可以看到已經(jīng)修改過來了:

圖片

但是重啟mysql客戶端設(shè)置和統(tǒng)計(jì)慢查詢?nèi)罩緱l數(shù)就會(huì)清零,即所有配置修改會(huì)還原。

命令修改配置之后,在命令行net stop mysql?關(guān)閉MySQL服務(wù),再net start mysql?開啟MySQL服務(wù),接著執(zhí)行show global variables like '%quer%';會(huì)發(fā)現(xiàn)配置還原了。

在配置文件修改才能永久改變,否則重啟數(shù)據(jù)庫(kù)就還原了。

3.慢查詢例子演示,新手都能看懂

數(shù)據(jù)表結(jié)構(gòu),偷懶沒寫comment:

CREATE TABLE `person_info_large` (  
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`account` VARCHAR (10),
`name` VARCHAR (20),
`area` VARCHAR (20),
`title` VARCHAR (20),
`motto` VARCHAR (50),
PRIMARY KEY (`id`),
UNIQUE(`account`),
KEY `index_area_title`(`area`,`title`)
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8

這里的數(shù)據(jù)是200W條。請(qǐng)注意表結(jié)構(gòu),記住哪幾個(gè)字段有索引即可,后續(xù)圍繞這個(gè)表進(jìn)行分析。

圖片

這個(gè)3.36s并不是實(shí)際執(zhí)行時(shí)間,實(shí)際執(zhí)行時(shí)間得去慢查詢?nèi)罩救タ碤uery_time參數(shù)。

圖片

可以看到Query_time: 6.337729s,超過了1s,所以會(huì)被記錄,一個(gè)select語句查詢這么久,簡(jiǎn)直無法忍受。

圖中其他的參數(shù)解釋如下:

  • Time:慢查詢發(fā)生的時(shí)間
  • Query_time:查詢時(shí)間
  • Lock_time:等待鎖表的時(shí)間
  • Rows_sent:語句返回的行數(shù)
  • Rows_exanined:語句執(zhí)行期間從存儲(chǔ)引擎讀取的行數(shù)。

上面這種方式是用系統(tǒng)自帶的慢查詢?nèi)罩静榭吹?,如果覺得系統(tǒng)自帶的慢查詢?nèi)罩静环奖悴榭?,可以使用pt-query-digest?或者mysqldumpslow等工具對(duì)慢查詢?nèi)罩具M(jìn)行分析。

:有的慢查詢正在執(zhí)行,結(jié)果已經(jīng)導(dǎo)致數(shù)據(jù)庫(kù)負(fù)載過高,而由于慢查詢還沒執(zhí)行完,因此慢查詢?nèi)罩究床坏饺魏握Z句,此時(shí)可以使用show processlist?命令查看正在執(zhí)行的慢查詢。show processlist?顯示哪些線程正在運(yùn)行,如果有PROCESS權(quán)限,則可以看到所有線程。否則,只能看到當(dāng)前會(huì)話線程。

四、查詢語句慢怎么辦?explain帶你分析sql執(zhí)行計(jì)劃

根據(jù)上一節(jié)的表結(jié)構(gòu)可以知道,account是添加了唯一索引的字段。explain分析一下執(zhí)行計(jì)劃。

圖片

我們重點(diǎn)需要關(guān)注select_type、type、possible_keys、key、Extra?這些列,我們來一一說明,看到select_type?列,這里是SIMPLE簡(jiǎn)單查詢,其他值下面給大家列出。

圖片

type列,這里是index,表示全索引掃描。

圖片

表格從上到下代表了sql查詢性能從最優(yōu)到最差,如果是type類型是all,說明sql語句需要優(yōu)化。

注意:如果type = NULL?,則表明個(gè)MySQL不用訪問表或者索引,直接就能得到結(jié)果,比如explain select sum(1+2);

possible_keys代表可能用到的索引列,key表示實(shí)際用到的索引列,以實(shí)際用到的索引列為準(zhǔn),這是查詢優(yōu)化器優(yōu)化過后選擇的,然后我們也可以根據(jù)實(shí)際情況強(qiáng)制使用我們自己的索引列來查詢。

Extra列,這里是Using index

圖片

圖片

一定要注意,Extra中出現(xiàn)Using filesort、Using temporary代表MySQL根本不能使用索引,效率會(huì)受到嚴(yán)重影響,應(yīng)當(dāng)盡可能的去優(yōu)化。

出現(xiàn)Using filesort說明MySQL對(duì)結(jié)果使用一個(gè)外部索引排序,而不是從表里按索引次序讀到相關(guān)內(nèi)容,有索引就維護(hù)了B+樹,數(shù)據(jù)本來就已經(jīng)排好序了,這說明根本沒有用到索引,而是數(shù)據(jù)讀完之后再排序,可能在內(nèi)存或者磁盤上排序。也有人將MySQL中無法利用索引的排序操作稱為“文件排序”。

出現(xiàn)Using temporary?表示MySQL在對(duì)查詢結(jié)果排序時(shí)使用臨時(shí)表,常見于order by?和分組查詢group by。

回到上一個(gè)話題,我們看到account是添加了唯一索引的字段。explain分析了執(zhí)行計(jì)劃后。

圖片

直接按照account降序來查:

圖片

查看慢查詢?nèi)罩景l(fā)現(xiàn),使用索引之后,查詢200W條數(shù)據(jù)的速度快了2s。

接著我們分析一下查詢name的sql執(zhí)行計(jì)劃。

圖片

然后給name字段加上索引:

圖片

加上索引之后,繼續(xù)看看查詢name的sql執(zhí)行計(jì)劃:

圖片

對(duì)比一下前面name不加索引時(shí)的執(zhí)行計(jì)劃就會(huì)發(fā)現(xiàn),加了索引后,type由ALL全表掃描變成index索引掃描。order by?并沒有 using filesort?,而是using index,這里B+樹已經(jīng)將這個(gè)非聚集索引的索引字段的值排好序了,而不是等到查詢的時(shí)候再去排序。

接著我們繼續(xù)執(zhí)行查詢語句,此時(shí)name已經(jīng)是添加了索引的。

圖片

結(jié)果發(fā)現(xiàn),name添加索引之前,降序查詢name是花費(fèi)6.337729s,添加索引之后,降序查詢name花費(fèi)了3.479827s,原因就是B+樹的結(jié)果集已經(jīng)是有序的了。

圖片

五、當(dāng)主鍵索引、唯一索引、普通索引都存在,查詢優(yōu)化器如何選擇?

查詢一下數(shù)據(jù)的條數(shù),這里count(id),分析一下sql執(zhí)行計(jì)劃:

圖片

這里實(shí)際使用的索引是account唯一索引。

分析一下:實(shí)際使用哪個(gè)索引是查詢優(yōu)化器決定的,B+樹的葉子結(jié)點(diǎn)就是鏈表結(jié)構(gòu),遍歷鏈表就可以統(tǒng)計(jì)數(shù)量,但是這張表,有主鍵索引、唯一索引、普通索引,優(yōu)化器選擇了account這個(gè)唯一索引,這肯定不會(huì)使用主鍵索引,因?yàn)橹麈I索引是聚集索引,每個(gè)葉子包含具體的一個(gè)行記錄(很多列的數(shù)據(jù)都在里面),而非聚集索引每個(gè)葉子只包含下一個(gè)主鍵索引的指針,很顯然葉子結(jié)點(diǎn)包含的數(shù)據(jù)是越少越好,查詢優(yōu)化器就不會(huì)選擇主鍵索引。

當(dāng)然,也可以強(qiáng)制使用主鍵索引,然后分析sql執(zhí)行計(jì)劃。

圖片

我們看一下優(yōu)化器默認(rèn)使用唯一索引大致執(zhí)行時(shí)間676ms:

圖片

強(qiáng)制使用主鍵索引大致執(zhí)行時(shí)間779ms:

圖片

我們可以用force index強(qiáng)制指定索引,然后去分析執(zhí)行計(jì)劃看看哪個(gè)索引是更好的,因?yàn)椴樵儍?yōu)化器選擇索引不一定是百分百準(zhǔn)確的,具體情況可以根據(jù)實(shí)際場(chǎng)景分析來確定是否使用查詢優(yōu)化器選擇的索引。

責(zé)任編輯:武曉燕 來源: 碼猿技術(shù)專欄
相關(guān)推薦

2022-07-05 10:50:31

數(shù)據(jù)庫(kù)查詢實(shí)戰(zhàn)

2020-02-23 17:15:29

SQL分析查詢

2022-09-19 08:41:02

數(shù)據(jù)查詢分離

2024-05-28 08:47:52

2023-09-27 08:21:00

查詢分離數(shù)據(jù)API

2019-06-20 11:20:25

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

2024-08-30 09:31:36

2025-02-14 09:30:42

2011-06-28 08:32:40

MySQL慢查詢?nèi)罩?/a>

2022-06-30 19:40:36

查詢接口索引優(yōu)化

2022-08-14 14:32:06

接口優(yōu)化

2019-05-08 14:02:52

MySQL索引查詢優(yōu)化數(shù)據(jù)庫(kù)

2021-04-07 10:38:43

MySQL數(shù)據(jù)庫(kù)命令

2020-06-05 09:21:20

MySQL慢查詢數(shù)據(jù)庫(kù)

2017-05-23 16:26:26

MySQL優(yōu)化處理

2010-06-12 15:31:04

MySQL查詢優(yōu)化

2020-09-01 11:10:39

數(shù)據(jù)庫(kù)鏈接池HikariCP

2024-10-28 07:00:00

分頁查詢優(yōu)化索引數(shù)據(jù)歸檔

2022-04-22 14:41:12

美團(tuán)慢查詢數(shù)據(jù)庫(kù)

2023-05-14 17:16:22

分類樹SpringBoot
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)