RM新时代网站-首页

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

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

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

你會(huì)從哪些維度進(jìn)行MySQL性能優(yōu)化?2

jf_78858299 ? 來源:蟬沐風(fēng)的碼場(chǎng) ? 作者:蟬沐風(fēng) ? 2023-03-03 10:23 ? 次閱讀

3. 優(yōu)化器——SQL分析與優(yōu)化

處理完連接、優(yōu)化完緩存等架構(gòu)的事情,SQL查詢語(yǔ)句來到了解析器和優(yōu)化器的地盤了。在這一步如果出了任何問題,那就只能是SQL語(yǔ)句的問題了。

只要你的語(yǔ)法不出問題,解析器就不會(huì)有問題。此外,為了防止你寫的SQL運(yùn)行效率低,優(yōu)化器會(huì)自動(dòng)做一些優(yōu)化,但如果實(shí)在是太爛,優(yōu)化器也救不了你了,只能眼睜睜地看著你的SQL查詢淪為 慢查詢 。

3.1 慢查詢

慢查詢就是執(zhí)行地很慢的查詢(這句話說得跟廢話似的。。。),只有知道MySQL中有哪些慢查詢我們才能針對(duì)性地進(jìn)行優(yōu)化。

因?yàn)殚_啟慢查詢?nèi)罩臼怯行阅艽鷥r(jià)的,因此MySQL默認(rèn)是關(guān)閉慢查詢?nèi)罩竟δ?,使用以下命令查看?dāng)前慢查詢狀態(tài)

mysql> show variables like 'slow_query%';
+---------------------+--------------------------------------+
| Variable_name       | Value                                |
+---------------------+--------------------------------------+
| slow_query_log      | OFF                                  |
| slow_query_log_file | /var/lib/mysql/9e74f9251f6c-slow.log |
+---------------------+--------------------------------------+
2 rows in set (0.00 sec)

slow_query_log表示當(dāng)前慢查詢?nèi)罩臼欠耖_啟,slow_query_log_file表示慢查詢?nèi)罩镜谋4嫖恢谩?/p>

除了上面兩個(gè)變量,我們還需要確定“慢”的指標(biāo)是什么,即執(zhí)行超過多長(zhǎng)時(shí)間才算是慢查詢,默認(rèn)是10S,如果改成0的話就是記錄所有的SQL。

mysql> show variables like '%long_query%';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

3.1.1 打開慢日志

有兩種打開慢日志的方式

  1. 修改配置文件my.cnf

此種修改方式系統(tǒng)重啟后依然有效

# 是否開啟慢查詢?nèi)罩?/span>
slow_query_log=ON
# 
long_query_time=2
slow_query_log_file=/var/lib/mysql/slow.log
  1. 動(dòng)態(tài)修改參數(shù)(重啟后失效)
mysql> set @@global.slow_query_log=1;
Query OK, 0 rows affected (0.06 sec)

mysql> set @@global.long_query_time=2;
Query OK, 0 rows affected (0.00 sec)

3.1.2 慢日志分析

MySQL不僅為我們保存了慢日志文件,還為我們提供了慢日志查詢的工具mysqldumpslow,為了演示這個(gè)工具,我們先構(gòu)造一條慢查詢:

mysql> SELECT sleep(5);

然后我們查詢用時(shí)最多的1條慢查詢:

[root@iZ2zejfuakcnnq2pgqyzowZ ~]# mysqldumpslow -s t -t 1 -g 'select' /var/lib/mysql/9e74f9251f6c-slow.log

Reading mysql slow query log from /var/lib/mysql/9e74f9251f6c-slow.log
Count: 1  Time=10.00s (10s)  Lock=0.00s (0s)  Rows=1.0 (1), root[root]@localhost
  SELECT sleep(N)

其中,

  • Count :表示這個(gè)SQL執(zhí)行的次數(shù)
  • Time :表示執(zhí)行的時(shí)間,括號(hào)中的是累積時(shí)間
  • Locks :表示鎖定的時(shí)間,括號(hào)中的是累積時(shí)間
  • Rows :表示返回的記錄數(shù),括號(hào)中的是累積數(shù)

更多關(guān)于mysqldumpslow的使用方式,可以查閱官方文檔,或者執(zhí)行mysqldumpslow --help尋求幫助。

3.2 查看運(yùn)行中的線程

我們可以運(yùn)行show full processlist查看MySQL中運(yùn)行的所有線程,查看其狀態(tài)和運(yùn)行時(shí)間,找到不順眼的,直接kill。

圖片

image-20220405182328247

其中,

  • Id :線程的唯一標(biāo)志,可以使用Id殺死指定線程
  • User :?jiǎn)?dòng)這個(gè)線程的用戶,普通賬戶只能查看自己的線程
  • Host :哪個(gè)ip和端口發(fā)起的連接
  • db :線程操作的數(shù)據(jù)庫(kù)
  • Command :線程的命令
  • Time :操作持續(xù)時(shí)間,單位秒
  • State :線程的狀態(tài)
  • Info :SQL語(yǔ)句的前100個(gè)字符

3.3 查看服務(wù)器運(yùn)行狀態(tài)

使用SHOW STATUS查看MySQL服務(wù)器的運(yùn)行狀態(tài),有sessionglobal兩種作用域,一般使用like+通配符進(jìn)行過濾。

-- 查看select的次數(shù)
mysql> SHOW GLOBAL STATUS LIKE 'com_select';
+---------------+--------+
| Variable_name | Value  |
+---------------+--------+
| Com_select    | 168241 |
+---------------+--------+
1 row in set (0.05 sec)

3.4 查看存儲(chǔ)引擎運(yùn)行信息

SHOW ENGINE用來展示存儲(chǔ)引擎的當(dāng)前運(yùn)行信息,包括事務(wù)持有的表鎖、行鎖信息;事務(wù)的鎖等待情況;線程信號(hào)量等待;文件IO請(qǐng)求;Buffer pool統(tǒng)計(jì)信息等等數(shù)據(jù)。

例如:

SHOW ENGINE INNODB STATUS;

上面這條語(yǔ)句可以展示innodb存儲(chǔ)引擎的當(dāng)前運(yùn)行的各種信息,大家可以據(jù)此找到MySQL當(dāng)前的問題,限于篇幅不在此意義說明其中信息的含義,大家只要知道MySQL提供了這樣一個(gè)監(jiān)控工具就行了,等到需要的時(shí)候再來用就好。

3.5 EXPLAIN執(zhí)行計(jì)劃

通過慢查詢?nèi)罩疚覀兛梢灾滥男㏒QL語(yǔ)句執(zhí)行慢了,可是為什么慢?慢在哪里呢?

MySQL提供了一個(gè)執(zhí)行計(jì)劃的查詢命令EXPLAIN,通過此命令我們可以查看SQL執(zhí)行的計(jì)劃,所謂執(zhí)行計(jì)劃就是:優(yōu)化器會(huì)不會(huì)優(yōu)化我們自己書寫的SQL語(yǔ)句(比如外連接改內(nèi)連接查詢,子查詢優(yōu)化為連接查詢...)、優(yōu)化器針對(duì)此條SQL的執(zhí)行對(duì)哪些索引進(jìn)行了成本估算,并最終決定采用哪個(gè)索引(或者最終選擇不用索引,而是全表掃描)、優(yōu)化器對(duì)單表執(zhí)行的策略是什么,等等等等。

EXPLAIN在MySQL5.6.3之后也可以針對(duì)UPDATE、DELETE和INSERT語(yǔ)句進(jìn)行分析,但是通常情況下我們還是用在SELECT查詢上。

這篇文章主要是從宏觀上多個(gè)角度介紹MySQL的優(yōu)化策略,因此這里不詳細(xì)說明EXPLAIN的細(xì)節(jié),之后單獨(dú)成篇。

3.6 SQL與索引優(yōu)化

3.6.1 SQL優(yōu)化

SQL優(yōu)化指的是SQL本身語(yǔ)法沒有問題,但是有實(shí)現(xiàn)相同目的的更好的寫法。比如:

  • 使用小表驅(qū)動(dòng)大表;用join改寫子查詢;or改成union
  • 連接查詢中,盡量減少驅(qū)動(dòng)表的扇出(記錄數(shù)),訪問被驅(qū)動(dòng)表的成本要盡量低,盡量在被驅(qū)動(dòng)表的連接列上建立索引,降低訪問成本;被驅(qū)動(dòng)表的連接列最好是該表的主鍵或者是唯一二級(jí)索引列,這樣被驅(qū)動(dòng)表的成本會(huì)降到更低
  • 大偏移量的limit,先過濾再排序

針對(duì)最后一條舉個(gè)簡(jiǎn)單的例子,下面兩條語(yǔ)句能實(shí)現(xiàn)同樣的目的,但是第二條的執(zhí)行效率比第一條執(zhí)行效率要高得多(存儲(chǔ)引擎使用的是InnoDB),大家感受一下:

-- 1. 大偏移量的查詢
mysql> SELECT * FROM user_innodb LIMIT 9000000,10;
Empty set (8.18 sec)

-- 2.先過濾ID(因?yàn)镮D使用的是索引),再limit
mysql> SELECT * FROM user_innodb WHERE id > 9000000 LIMIT 10;
Empty set (0.02 sec)

3.6.2 索引優(yōu)化

為慢查詢創(chuàng)建適當(dāng)?shù)乃饕莻€(gè)非常常見并且非常有效的方法,但是索引是否會(huì)被高效使用又是另一門學(xué)問了。

4. 存儲(chǔ)引擎與表結(jié)構(gòu)

4.1 選擇存儲(chǔ)引擎

一般情況下,我們會(huì)選擇MySQL默認(rèn)的存儲(chǔ)引擎存儲(chǔ)引擎InnoDB,但是當(dāng)對(duì)數(shù)據(jù)庫(kù)性能要求精益求精的時(shí)候,存儲(chǔ)引擎的選擇也成為一個(gè)關(guān)鍵的影響因素。

建議根據(jù)不同的業(yè)務(wù)選擇不同的存儲(chǔ)引擎,例如:

  • 查詢操作、插入操作多的業(yè)務(wù)表,推薦使用MyISAM
  • 臨時(shí)表使用Memory;
  • 并發(fā)數(shù)量大、更新多的業(yè)務(wù)選擇使用InnoDB;
  • 不知道選啥直接默認(rèn)。

4.2 優(yōu)化字段

字段優(yōu)化的最終原則是: 使用可以正確存儲(chǔ)數(shù)據(jù)的最小的數(shù)據(jù)類型 。

4.2.1 整數(shù)類型

MySQL提供了6種整數(shù)類型,分別是

  • tinyint
  • smallint
  • mediumint
  • int
  • integer
  • bigint

不同的存儲(chǔ)類型的最大存儲(chǔ)范圍不同,占用的存儲(chǔ)的空間自然也不同。

例如,是否被刪除的標(biāo)識(shí),建議選用tinyint,而不是bigint。

4.2.2 字符類型

你是不是直接把所有字符串的字段都設(shè)置為varchar格式了?甚至怕不夠,還會(huì)直接設(shè)置成varchar(1024)的長(zhǎng)度?

如果不確定字段的長(zhǎng)度,肯定是要選擇varchar,但是varchar需要額外的空間來記錄該字段目前占用的長(zhǎng)度;因此如果字段的長(zhǎng)度是固定的,盡量選用char,這會(huì)給你節(jié)約不少的內(nèi)存空間。

4.2.3 非空

非空字段盡量設(shè)置成NOT NULL,并提供默認(rèn)值,或者使用特殊值代替NULL。

因?yàn)?code>NULL類型的存儲(chǔ)和優(yōu)化都會(huì)存在性能不佳的問題,具體原因在這里就不展開了。

4.2.4 不要用外鍵、觸發(fā)器和視圖功能

這也是「阿里巴巴開發(fā)手冊(cè)」中提到的原則。原因有三個(gè):

  1. 降低了可讀性,檢查代碼的同時(shí)還得查看數(shù)據(jù)庫(kù)的代碼;
  2. 把計(jì)算的工作交給程序,數(shù)據(jù)庫(kù)只做好存儲(chǔ)的工作,并把這件事情做好;
  3. 數(shù)據(jù)的完整性校驗(yàn)的工作應(yīng)該由開發(fā)者完成,而不是依賴于外鍵,一旦用了外鍵,你會(huì)發(fā)現(xiàn)測(cè)試的時(shí)候隨便刪點(diǎn)垃圾數(shù)據(jù)都變得異常艱難。

4.2.5 圖片、音頻、視頻存儲(chǔ)

不要直接存儲(chǔ)大文件,而是要存儲(chǔ)大文件的訪問地址。

4.2.6 大字段拆分和數(shù)據(jù)冗余

大字段拆分其實(shí)就是前面說過的垂直分表,把不常用的字段或者數(shù)據(jù)量較大的字段拆分出去,避免列數(shù)過多和數(shù)據(jù)量過大,尤其是習(xí)慣編寫SELECT *的情況下,列數(shù)多和數(shù)據(jù)量大導(dǎo)致的問題會(huì)被嚴(yán)重放大!

字段冗余原則上不符合數(shù)據(jù)庫(kù)設(shè)計(jì)范式,但是卻非常有利于快速檢索。比如,合同表中存儲(chǔ)客戶id的同時(shí)可以冗余存儲(chǔ)客戶姓名,這樣查詢時(shí)就不需要再根據(jù)客戶id獲取用戶姓名了。因此針對(duì)業(yè)務(wù)邏輯適當(dāng)做一定程度的冗余也是一種比較好的優(yōu)化技巧。

5. 業(yè)務(wù)優(yōu)化

嚴(yán)格來說,業(yè)務(wù)方面的優(yōu)化已經(jīng)不算是MySQL調(diào)優(yōu)的手段了,但是業(yè)務(wù)的優(yōu)化卻能非常有效地減輕數(shù)據(jù)庫(kù)訪問壓力,這方面一個(gè)典型例子就是淘寶,下面舉幾個(gè)簡(jiǎn)單例子給大家提供一下思路:

  1. 以往都是雙11當(dāng)晚開始買買買的模式,最近幾年雙11的預(yù)售戰(zhàn)線越拉越長(zhǎng),提前半個(gè)多月就開始了,而且各種定金紅包模式叢出不窮,這種方式叫做 預(yù)售分流 。這樣做可以分流客戶的服務(wù)請(qǐng)求,不必等到雙十一的凌晨一股腦地集體下單;
  2. 雙十一的凌晨你或許想查詢當(dāng)天之外的訂單,但是卻查詢失敗;甚至支付寶里的小雞的口糧都被延遲發(fā)放了,這是一種 降級(jí)策略 ,集結(jié)不重要的服務(wù)的計(jì)算資源,用來保證當(dāng)前最核心的業(yè)務(wù);
  3. 雙十一的時(shí)候支付寶極力推薦使用花唄支付,而不是銀行卡支付,雖然一部分考量是提高軟件粘性,但是另一方面,使用余額寶實(shí)際使用的阿里內(nèi)部服務(wù)器,訪問速度快,而使用銀行卡,需要調(diào)用銀行接口,相比之下操作要慢了許多。
聲明:本文內(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)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    7002

    瀏覽量

    88938
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9123

    瀏覽量

    85322
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    804

    瀏覽量

    26526
  • 服務(wù)端
    +關(guān)注

    關(guān)注

    0

    文章

    66

    瀏覽量

    7004
收藏 人收藏

    評(píng)論

    相關(guān)推薦

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

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

    MySQL性能優(yōu)化淺析及線上案例

    手段則會(huì)對(duì)用戶的使用體驗(yàn)造成影響,嚴(yán)重的則會(huì)直接導(dǎo)致訂單、金額直接受損,因而就需要時(shí)刻關(guān)注數(shù)據(jù)庫(kù)的性能問題。 2、 性能優(yōu)化的幾個(gè)常見措施 數(shù)據(jù)庫(kù)
    的頭像 發(fā)表于 10-22 15:17 ?677次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>性能</b><b class='flag-5'>優(yōu)化</b>淺析及線上案例

    mysql的查詢優(yōu)化

    mysql查詢優(yōu)化
    發(fā)表于 03-12 11:06

    MySQL優(yōu)化之查詢性能優(yōu)化之查詢優(yōu)化器的局限性與提示

    MySQL優(yōu)化三:查詢性能優(yōu)化之查詢優(yōu)化器的局限性與提示
    發(fā)表于 06-02 06:34

    MySQL索引使用優(yōu)化和規(guī)范

    MySQL - 索引使用優(yōu)化和規(guī)范
    發(fā)表于 06-15 16:01

    MySql5.6性能優(yōu)化最佳實(shí)踐

    MySql5.6性能優(yōu)化最佳實(shí)踐
    發(fā)表于 09-08 08:47 ?13次下載
    <b class='flag-5'>MySql</b>5.6<b class='flag-5'>性能</b><b class='flag-5'>優(yōu)化</b>最佳實(shí)踐

    幫助優(yōu)化MySQL數(shù)據(jù)庫(kù)性能的7個(gè)技巧

    隨著尺寸和負(fù)載的增長(zhǎng),MySQL性能會(huì)趨于下降。記住這些訣竅,便可保持MySQL的流暢運(yùn)行。 測(cè)量應(yīng)用程序的方法之一是看性能。而
    發(fā)表于 11-30 15:03 ?798次閱讀
    幫助<b class='flag-5'>優(yōu)化</b><b class='flag-5'>MySQL</b>數(shù)據(jù)庫(kù)<b class='flag-5'>性能</b>的7個(gè)技巧

    詳解MySQL的查詢優(yōu)化 MySQL邏輯架構(gòu)分析

    說起MySQL的查詢優(yōu)化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *、不使用NULL字段、合理創(chuàng)建索引、為字段選擇合適的數(shù)據(jù)類型..... 是否真的理解這些優(yōu)化技巧?是否理
    的頭像 發(fā)表于 05-28 16:43 ?4340次閱讀
    詳解<b class='flag-5'>MySQL</b>的查詢<b class='flag-5'>優(yōu)化</b> <b class='flag-5'>MySQL</b>邏輯架構(gòu)分析

    MySQL數(shù)據(jù)庫(kù):理解MySQL性能優(yōu)化、優(yōu)化查詢

    最近一直在為大家更新MySQL相關(guān)學(xué)習(xí)內(nèi)容,可能有朋友不懂MySQL的重要性。在程序,語(yǔ)言,架構(gòu)更新?lián)Q代頻繁的今天,MySQL 恐怕是大家使用最多的存儲(chǔ)數(shù)據(jù)庫(kù)了。由于MySQL
    的頭像 發(fā)表于 07-02 17:18 ?3090次閱讀
    <b class='flag-5'>MySQL</b>數(shù)據(jù)庫(kù):理解<b class='flag-5'>MySQL</b>的<b class='flag-5'>性能</b><b class='flag-5'>優(yōu)化</b>、<b class='flag-5'>優(yōu)化</b>查詢

    MySQL索引的使用問題

    一、前言 在MySQL進(jìn)行SQL優(yōu)化的時(shí)候,經(jīng)常會(huì)在一些情況下,對(duì)MySQL能否利用索引有一些迷惑。譬如:1、MySQL 在遇到范圍查詢條
    的頭像 發(fā)表于 01-06 16:13 ?1601次閱讀

    利用MySQL進(jìn)行一主一的主從復(fù)制

    本文講述了如何使用MyBatisPlus+ShardingSphereJDBC進(jìn)行讀寫分離,以及利用MySQL進(jìn)行一主一的主從復(fù)制。
    的頭像 發(fā)表于 07-28 09:47 ?1030次閱讀

    會(huì)哪些維度進(jìn)行MySQL性能優(yōu)化?1

    會(huì)哪些維度進(jìn)行MySQL性能
    的頭像 發(fā)表于 03-03 10:23 ?506次閱讀
    <b class='flag-5'>你</b><b class='flag-5'>會(huì)</b><b class='flag-5'>從</b>哪些<b class='flag-5'>維度</b><b class='flag-5'>進(jìn)行</b><b class='flag-5'>MySQL</b><b class='flag-5'>性能</b><b class='flag-5'>優(yōu)化</b>?1

    如何將數(shù)據(jù)MySQL遷移到Influxdb中

    如果以前是將時(shí)序數(shù)據(jù)存放在MySQL,現(xiàn)在為了獲取更好的性能和使用可視化工具,我們需要將數(shù)據(jù)MySQL遷移到Influxdb中。 這看起來是一個(gè)常見場(chǎng)景,經(jīng)過一番查閱,發(fā)現(xiàn)了
    的頭像 發(fā)表于 11-02 10:54 ?1228次閱讀

    MySQL性能優(yōu)化方法

    MySQL 性能優(yōu)化是一項(xiàng)關(guān)鍵的任務(wù),可以提高數(shù)據(jù)庫(kù)的運(yùn)行速度和效率。以下是一些優(yōu)化方法,包括具體代碼和詳細(xì)優(yōu)化方案。
    的頭像 發(fā)表于 11-22 09:59 ?595次閱讀

    MySQL執(zhí)行過程:如何進(jìn)行sql 優(yōu)化

    (1)客戶端發(fā)送一條查詢語(yǔ)句到服務(wù)器; (2)服務(wù)器先查詢緩存,如果命中緩存,則立即返回存儲(chǔ)在緩存中的數(shù)據(jù); (3)未命中緩存后,MySQL 通過關(guān)鍵字將 SQL 語(yǔ)句進(jìn)行解析,并生成一顆對(duì)應(yīng)的解析樹,
    的頭像 發(fā)表于 12-12 10:19 ?399次閱讀
    <b class='flag-5'>MySQL</b>執(zhí)行過程:如何<b class='flag-5'>進(jìn)行</b>sql <b class='flag-5'>優(yōu)化</b>
    RM新时代网站-首页