日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

两个sql交集_如何使用性能分析工具定位SQL执行慢的原因?

發(fā)布時(shí)間:2023/12/20 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 两个sql交集_如何使用性能分析工具定位SQL执行慢的原因? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在前面的文章中就講過(guò)了查詢(xún)優(yōu)化器,知道在查詢(xún)優(yōu)化器中會(huì)經(jīng)歷邏輯查詢(xún)優(yōu)化和物理查詢(xún)優(yōu)化。需要注意的是,查詢(xún)優(yōu)化器只能在已經(jīng)確定的情況下(SQL 語(yǔ)句、索引設(shè)計(jì)、緩沖池大小、查詢(xún)優(yōu)化器參數(shù)等)決定最優(yōu)的查詢(xún)執(zhí)行計(jì)劃。

但實(shí)際上 SQL 執(zhí)行起來(lái)可能還是很慢,那么到底從哪里定位 SQL 查詢(xún)慢的問(wèn)題呢?是索引設(shè)計(jì)的問(wèn)題?服務(wù)器參數(shù)配置的問(wèn)題?還是需要增加緩存的問(wèn)題呢?今天我們就從性能分析來(lái)入手,定位導(dǎo)致 SQL 執(zhí)行慢的原因。

今天的內(nèi)容主要包括以下幾個(gè)部分:

  • 數(shù)據(jù)庫(kù)服務(wù)器的優(yōu)化分析的步驟是怎樣的?中間有哪些需要注意的地方?
  • 如何使用慢查詢(xún)?nèi)罩静檎覉?zhí)行慢的 SQL 語(yǔ)句? 3.如何使用 EXPLAIN 查看 SQL 執(zhí)行計(jì)劃? 4.如何使用 SHOW PROFILING 分析 SQL 執(zhí)行步驟中的每一步的執(zhí)行時(shí)間?
  • 一、數(shù)據(jù)庫(kù)服務(wù)器的優(yōu)化步驟

    當(dāng)我們遇到數(shù)據(jù)庫(kù)調(diào)優(yōu)問(wèn)題的時(shí)候,該如何思考呢?我把思考的流程整理成了下面這張圖。

    整個(gè)流程劃分成了觀察(Show status)和行動(dòng)(Action)兩個(gè)部分。字母 S 的部分代表觀察(會(huì)使用相應(yīng)的分析工具),字母 A 代表的部分是行動(dòng)(對(duì)應(yīng)分析可以采取的行動(dòng))。

    我們可以通過(guò)觀察了解數(shù)據(jù)庫(kù)整體的運(yùn)行狀態(tài),通過(guò)性能分析工具可以讓我們了解執(zhí)行慢的SQL 都有哪些,查看具體的 SQL 執(zhí)行計(jì)劃,甚至是 SQL 執(zhí)行中的每一步的成本代價(jià),這樣才能定位問(wèn)題所在,找到了問(wèn)題,再采取相應(yīng)的行動(dòng)。

    我來(lái)詳細(xì)解釋一下這張圖。

    首先在 S1 部分,我們需要觀察服務(wù)器的狀態(tài)是否存在周期性的波動(dòng)。如果存在周期性波動(dòng),有可能是周期性節(jié)點(diǎn)的原因,比如雙十一、促銷(xiāo)活動(dòng)等。這樣的話(huà),我們可以通過(guò) A1這一步驟解決,也就是加緩存,或者更改緩存失效策略。

    如果緩存策略沒(méi)有解決,或者不是周期性波動(dòng)的原因,我們就需要進(jìn)一步分析查詢(xún)延遲和卡頓的原因。接下來(lái)進(jìn)入 S2 這一步,我們需要開(kāi)啟慢查詢(xún)。慢查詢(xún)可以幫我們定位執(zhí)行慢的SQL 語(yǔ)句。我們可以通過(guò)設(shè)置 long_query_time 參數(shù)定義“慢”的閾值,如果 SQL 執(zhí)行時(shí)間超過(guò)了 long_query_time,則會(huì)認(rèn)為是慢查詢(xún)。當(dāng)收集上來(lái)這些慢查詢(xún)之后,我們就可以通過(guò)分析工具對(duì)慢查詢(xún)?nèi)罩具M(jìn)行分析。

    在 S3 這一步驟中,我們就知道了執(zhí)行慢的 SQL,這樣就可以針對(duì)性地用 EXPLAIN 查看對(duì)應(yīng) SQL 語(yǔ)句的執(zhí)行計(jì)劃,或者使用 show profile 查看 SQL 中每一個(gè)步驟的時(shí)間成本。這樣我們就可以了解 SQL 查詢(xún)慢是因?yàn)閳?zhí)行時(shí)間長(zhǎng),還是等待時(shí)間長(zhǎng)。

    如果是 SQL 等待時(shí)間長(zhǎng),我們進(jìn)入 A2 步驟。在這一步驟中,我們可以調(diào)優(yōu)服務(wù)器的參數(shù),比如適當(dāng)增加數(shù)據(jù)庫(kù)緩沖池等。如果是 SQL 執(zhí)行時(shí)間長(zhǎng),就進(jìn)入 A3 步驟,這一步中我們需要考慮是索引設(shè)計(jì)的問(wèn)題?還是查詢(xún)關(guān)聯(lián)的數(shù)據(jù)表過(guò)多?還是因?yàn)閿?shù)據(jù)表的字段設(shè)計(jì)問(wèn)題導(dǎo)致了這一現(xiàn)象。然后在這些維度上進(jìn)行對(duì)應(yīng)的調(diào)整。

    如果 A2 和 A3 都不能解決問(wèn)題,我們需要考慮數(shù)據(jù)庫(kù)自身的 SQL 查詢(xún)性能是否已經(jīng)達(dá)到了瓶頸,如果確認(rèn)沒(méi)有達(dá)到性能瓶頸,就需要重新檢查,重復(fù)以上的步驟。如果已經(jīng)達(dá)到了性能瓶頸,進(jìn)入 A4 階段,需要考慮增加服務(wù)器,采用讀寫(xiě)分離的架構(gòu),或者考慮對(duì)數(shù)據(jù)庫(kù)進(jìn)行分庫(kù)分表,比如垂直分庫(kù)、垂直分表和水平分表等。

    以上就是數(shù)據(jù)庫(kù)調(diào)優(yōu)的流程思路。如果我們發(fā)現(xiàn)執(zhí)行 SQL 時(shí)存在不規(guī)則延遲或卡頓的時(shí)候,就可以采用分析工具幫我們定位有問(wèn)題的 SQL,這三種分析工具你可以理解是 SQL 調(diào)優(yōu)的三個(gè)步驟:慢查詢(xún)、EXPLAIN 和 SHOW PROFILING。

    二、使用慢查詢(xún)定位執(zhí)行慢的SQL

    好慢詢(xún)可以幫我們找到執(zhí)行慢的 SQL,在使用前,我們需要先看下慢查詢(xún)是否已經(jīng)開(kāi)啟,使用下面這條命令即可:

    mysql > show variables like '%slow_query_log';

    我們能看到 slow_query_log=OFF,也就是說(shuō)慢查詢(xún)?nèi)罩敬藭r(shí)是關(guān)上的。我們可以把慢查詢(xún)?nèi)罩敬蜷_(kāi),注意設(shè)置變量值的時(shí)候需要使用 global,否則會(huì)報(bào)錯(cuò):

    mysql > set global slow_query_log='ON';

    然后我們?cè)賮?lái)查看下慢查詢(xún)?nèi)罩臼欠耖_(kāi)啟,以及慢查詢(xún)?nèi)罩疚募奈恢?#xff1a;

    你能看到這時(shí)慢查詢(xún)分析已經(jīng)開(kāi)啟,同時(shí)文件保存在 DESKTOP-4BK02RP-slow 文件中。

    接下來(lái)我們來(lái)看下慢查詢(xún)的時(shí)間閾值設(shè)置,使用如下命令:

    mysql > show variables like '%long_query_time%';

    這里如果我們想把時(shí)間縮短,比如設(shè)置為 3 秒,可以這樣設(shè)置:

    mysql > set global long_query_time = 3;

    我們可以使用 MySQL 自帶的 mysqldumpslow 工具統(tǒng)計(jì)慢查詢(xún)?nèi)罩?這個(gè)工具是個(gè) Perl腳本,你需要先安裝好 Perl)。

    mysqldumpslow 命令的具體參數(shù)如下:

    • -s:采用 order 排序的方式,排序方式可以有以下幾種。分別是 c(訪問(wèn)次數(shù))、t(查詢(xún)時(shí)間)、l(鎖定時(shí)間)、r(返回記錄)、ac(平均查詢(xún)次數(shù))、al(平均鎖定時(shí)間)、ar(平均返回記錄數(shù))和 at(平均查詢(xún)時(shí)間)。其中 at 為默認(rèn)排序方式。
    • -t:返回前 N 條數(shù)據(jù) 。
    • -g:后面可以是正則表達(dá)式,對(duì)大小寫(xiě)不敏感。

    比如我們想要按照查詢(xún)時(shí)間排序,查看前兩條 SQL 語(yǔ)句,這樣寫(xiě)即可:

    perl mysqldumpslow.pl -s t -t 2 "C:ProgramDataMySQLMySQL Server 8.0DataDESKTOP-4BK0

    你能看到開(kāi)啟了慢查詢(xún)?nèi)罩?#xff0c;并設(shè)置了相應(yīng)的慢查詢(xún)時(shí)間閾值之后,只要大于這個(gè)閾值的SQL 語(yǔ)句都會(huì)保存在慢查詢(xún)?nèi)罩局?#xff0c;然后我們就可以通過(guò) mysqldumpslow 工具提取想要查找的 SQL 語(yǔ)句了。

    三、如何使用EXPLAIN查看執(zhí)行計(jì)劃

    定位了查詢(xún)慢的 SQL 之后,我們就可以使用 EXPLAIN 工具做針對(duì)性的分析,比如我們想要了解 product_comment 和 user 表進(jìn)行聯(lián)查的時(shí)候所采用的的執(zhí)行計(jì)劃,可以使用下面這條語(yǔ)句:

    EXPLAIN SELECT comment_id, product_id, comment_text, product_comment.user_id, user_name

    EXPLAIN 可以幫助我們了解數(shù)據(jù)表的讀取順序、SELECT 子句的類(lèi)型、數(shù)據(jù)表的訪問(wèn)類(lèi)型、可使用的索引、實(shí)際使用的索引、使用的索引長(zhǎng)度、上一個(gè)表的連接匹配條件、被優(yōu)化器查詢(xún)的行的數(shù)量以及額外的信息(比如是否使用了外部排序,是否使用了臨時(shí)表等)等。

    SQL 執(zhí)行的順序是根據(jù) id 從大到小執(zhí)行的,也就是 id 越大越先執(zhí)行,當(dāng) id 相同時(shí),從上到下執(zhí)行。

    數(shù)據(jù)表的訪問(wèn)類(lèi)型所對(duì)應(yīng)的 type 列是我們比較關(guān)注的信息。type 可能有以下幾種情況:

    在這些情況里,all 是最壞的情況,因?yàn)椴捎昧巳頀呙璧姆绞健ndex 和 all 差不多,只不過(guò) index 對(duì)索引表進(jìn)行全掃描,這樣做的好處是不再需要對(duì)數(shù)據(jù)進(jìn)行排序,但是開(kāi)銷(xiāo)依然很大。如果我們?cè)?extra 列中看到 Using index,說(shuō)明采用了索引覆蓋,也就是索引可以覆蓋所需的 SELECT 字段,就不需要進(jìn)行回表,這樣就減少了數(shù)據(jù)查找的開(kāi)銷(xiāo)。

    比如我們對(duì) product_comment 數(shù)據(jù)表進(jìn)行查詢(xún),設(shè)計(jì)了聯(lián)合索引 composite_index(user_id, comment_text),然后對(duì)數(shù)據(jù)表中的 comment_id、comment_text、user_id這三個(gè)字段進(jìn)行查詢(xún),最后用 EXPLAIN 看下執(zhí)行計(jì)劃:

    EXPLAIN SELECT comment_id, comment_text, user_id FROM product_comment

    你能看到這里的訪問(wèn)方式采用了 index 的方式,key 列采用了聯(lián)合索引,進(jìn)行掃描。Extral列為 Using index,告訴我們索引可以覆蓋 SELECT 中的字段,也就不需要回表查詢(xún)了。

    range 表示采用了索引范圍掃描,這里不進(jìn)行舉例,從這一級(jí)別開(kāi)始,索引的作用會(huì)越來(lái)越明顯,因此我們需要盡量讓 SQL 查詢(xún)可以使用到 range 這一級(jí)別及以上的 type 訪問(wèn)方式。

    index_merge 說(shuō)明查詢(xún)同時(shí)使用了兩個(gè)或以上的索引,最后取了交集或者并集。比如想要對(duì) comment_id=500000 或者 user_id=500000 的數(shù)據(jù)進(jìn)行查詢(xún),數(shù)據(jù)表中comment_id 為主鍵,user_id 是普通索引,我們可以查看下執(zhí)行計(jì)劃:

    EXPLAIN SELECT comment_id, product_id, comment_text, user_id FROM product_comment WHERE

    你能看到這里同時(shí)使用到了兩個(gè)索引,分別是主鍵和 user_id,采用的數(shù)據(jù)表訪問(wèn)類(lèi)型是index_merge,通過(guò) union 的方式對(duì)兩個(gè)索引檢索的數(shù)據(jù)進(jìn)行合并。

    ref 類(lèi)型表示采用了非唯一索引,或者是唯一索引的非唯一性前綴。比如我們想要對(duì)user_id=500000 的評(píng)論進(jìn)行查詢(xún),使用 EXPLAIN 查看執(zhí)行計(jì)劃:

    EXPLAIN SELECT comment_id, comment_text, user_id FROM product_comment WHERE user_id = 50

    這里 user_id 為普通索引(因?yàn)?user_id 在商品評(píng)論表中可能是重復(fù)的),因此采用的訪問(wèn)類(lèi)型是 ref,同時(shí)在 ref 列中顯示 const,表示連接匹配條件是常量,用于索引列的查找。

    eq_ref 類(lèi)型是使用主鍵或唯一索引時(shí)產(chǎn)生的訪問(wèn)方式,通常使用在多表聯(lián)查中。假設(shè)我們對(duì) product_comment 表和 usre 表進(jìn)行聯(lián)查,關(guān)聯(lián)條件是兩張表的 user_id 相等,使用EXPLAIN 進(jìn)行執(zhí)行計(jì)劃查看:

    EXPLAIN SELECT * FROM product_comment JOIN user WHERE product_comment.user_id = user.use

    const 類(lèi)型表示我們使用了主鍵或者唯一索引(所有的部分)與常量值進(jìn)行比較,比如我們想要查看 comment_id=500000,查看執(zhí)行計(jì)劃:

    EXPLAIN SELECT comment_id, comment_text, user_id FROM product_comment WHERE comment_id =

    需要說(shuō)明的是 const 類(lèi)型和 eq_ref 都使用了主鍵或唯一索引,不過(guò)這兩個(gè)類(lèi)型有所區(qū)別,const 是與常量進(jìn)行比較,查詢(xún)效率會(huì)更快,而 eq_ref 通常用于多表聯(lián)查中。

    system 類(lèi)型一般用于 MyISAM 或 Memory 表,屬于 const 類(lèi)型的特例,當(dāng)表只有一行時(shí)連接類(lèi)型為 system。我們查看下執(zhí)行計(jì)劃:

    EXPLAIN SELECT * FROM test_myisam

    你能看到除了 all 類(lèi)型外,其他類(lèi)型都可以使用到索引,但是不同的連接方式的效率也會(huì)有所不同,效率從低到高依次為 all < index < range < index_merge < ref < eq_ref

    四、使用SHOW PROFILE查看SQL的具體執(zhí)行成本

    SHOW PROFILE 相比 EXPLAIN 能看到更進(jìn)一步的執(zhí)行解析,包括 SQL 都做了什么、所花費(fèi)的時(shí)間等。默認(rèn)情況下,profiling 是關(guān)閉的,我們可以在會(huì)話(huà)級(jí)別開(kāi)啟這個(gè)功能。

    mysql > show variables like 'profiling';

    通過(guò)設(shè)置 profiling='ON’來(lái)開(kāi)啟 show profile:

    mysql > set profiling = 'ON';

    我們可以看下當(dāng)前會(huì)話(huà)都有哪些 profiles,使用下面這條命令:

    mysql > show profiles;

    你能看到當(dāng)前會(huì)話(huà)一共有 2 個(gè)查詢(xún),如果我們想要查看上一個(gè)查詢(xún)的開(kāi)銷(xiāo),可以使用:

    mysql > show profile;

    我們也可以查看指定的 Query ID 的開(kāi)銷(xiāo),比如 show profile for query 2 查詢(xún)結(jié)果是一樣的。在 SHOW PROFILE 中我們可以查看不同部分的開(kāi)銷(xiāo),比如 cpu、block.io 等:

    通過(guò)上面的結(jié)果,我們可以弄清楚每一步驟的耗時(shí),以及在不同部分,比如 CPU、block.io 的執(zhí)行時(shí)間,這樣我們就可以判斷出來(lái) SQL 到底慢在哪里。

    不過(guò) SHOW PROFILE 命令將被棄用,我們可以從 information_schema 中的 profiling 數(shù)據(jù)表進(jìn)行查看。

    五、總結(jié)

    本文梳理了 SQL 優(yōu)化的思路,從步驟上看,我們需要先進(jìn)行觀察和分析,分析工具的使用在日常工作中還是很重要的。今天只介紹了常用的三種分析工具,實(shí)際上可以使用的分析工具還有很多。

    在這里總結(jié)一下今天文章里提到的三種分析工具。我們可以通過(guò)慢查詢(xún)?nèi)罩径ㄎ粓?zhí)行慢的SQL,然后通過(guò) EXPLAIN 分析該 SQL 語(yǔ)句是否使用到了索引,以及具體的數(shù)據(jù)表訪問(wèn)方式是怎樣的。我們也可以使用 SHOW PROFILE 進(jìn)一步了解 SQL 每一步的執(zhí)行時(shí)間,包括I/O 和 CPU 等資源的使用情況。

    推薦閱讀

    盤(pán)點(diǎn):2020年最新、最全、最實(shí)用的Java崗面試真題,已收錄GitHub

    絕對(duì)干貨,掌握這27個(gè)知識(shí)點(diǎn),輕松拿下80%的技術(shù)面試(Java崗)

    一線大廠為什么面試必問(wèn)分布式?

    在一次又一次的失敗中,我總結(jié)了這份萬(wàn)字的《MySQL性能調(diào)優(yōu)筆記》

    并發(fā)編程詳解:十三個(gè)工具類(lèi),十大設(shè)計(jì)模式,從理論基礎(chǔ)到案例實(shí)戰(zhàn)

    如何高效部署分布式消息隊(duì)列?這份《RabbitMQ實(shí)戰(zhàn)》絕對(duì)可以幫到你

    總結(jié)

    以上是生活随笔為你收集整理的两个sql交集_如何使用性能分析工具定位SQL执行慢的原因?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。