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

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

生活随笔

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

数据库

MySQL 性能优化一

發(fā)布時(shí)間:2023/12/14 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 性能优化一 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

優(yōu)化方向

  硬件和OS調(diào)優(yōu) 、MySql調(diào)優(yōu) 、架構(gòu)優(yōu)化。對(duì)架構(gòu)的優(yōu)化對(duì)mysql的性能優(yōu)化收益最高。本文主要討論架構(gòu)優(yōu)化。

架構(gòu)優(yōu)化

  在系統(tǒng)設(shè)計(jì)時(shí)首先需要充分考慮業(yè)務(wù)的實(shí)際情況,例如排行榜的相關(guān)業(yè)務(wù)可以考慮遷移到redis中去做, 地理位置相關(guān)的需求放到mongodb中去做,有搜索需求放到ElasticSearch中去做,大數(shù)據(jù)相關(guān)的放到HBase中去做, 對(duì)數(shù)據(jù)一致性和事物有要求的,優(yōu)先選擇MySql。采用更適合業(yè)務(wù)場(chǎng)景的架構(gòu)能最大程度地提 升系統(tǒng)的擴(kuò)展性和可用性。

MySql調(diào)優(yōu)流程

  • ????????確認(rèn)業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)是否合理,SQL 語(yǔ)句優(yōu)化是否足 夠,該添加的索引是否都添加了,是否可以剔除多余的索引等等。
  • ????????確定系統(tǒng)、硬件有哪些地方需要優(yōu)化,系統(tǒng)瓶頸在哪里,哪些系統(tǒng)參數(shù) 需要調(diào)整優(yōu)化,進(jìn)程資源限制是否提到足夠高;在硬件方面是否需要更換為具有 更高 I/O 性能的存儲(chǔ)硬件,是否需要升級(jí)內(nèi)存、CPU、網(wǎng)絡(luò)等。

查詢性能優(yōu)化

????????線上環(huán)境發(fā)現(xiàn)數(shù)據(jù)庫(kù)卡頓,需要首先分析慢查詢log, 定位慢查詢的sql, 優(yōu)化對(duì)應(yīng)的sql。

  • 什么是慢查詢??

????????????????顧名思義,就是查詢花費(fèi)大量時(shí)間的日志,是指 mysql 記錄所 有執(zhí)行超過(guò) long_query_time 參數(shù)設(shè)定的時(shí)間閾值的 SQL 語(yǔ)句的日志。

????????該日志能 為 SQL 語(yǔ)句的優(yōu)化帶來(lái)很好的幫助。

  • 慢查詢?nèi)罩?/h3>

  ????????默認(rèn)情況下,慢查詢?nèi)罩臼顷P(guān)閉的,要使用 慢查詢?nèi)罩竟δ?#xff0c;首先要開啟慢查詢?nèi)罩竟δ堋?/p>

  • 慢查詢基礎(chǔ)-優(yōu)化數(shù)據(jù)訪問(wèn)

????????????????查詢性能低下最基本的原因是訪問(wèn)的數(shù)據(jù)太多。大部分性能低下的查詢都可 以通過(guò)減少訪問(wèn)的數(shù)據(jù)量的方式進(jìn)行優(yōu)化。對(duì)于低效的查詢,

????????一般通過(guò)下面兩個(gè) 步驟來(lái)分析總是很有效:

????????????????確認(rèn)應(yīng)用程序是否在檢索大量超過(guò)需要的數(shù)據(jù)。這通常意味著訪問(wèn)了太 多的行,但有時(shí)候也可能是訪問(wèn)了太多的列。

????????????????確認(rèn) MySQL 服務(wù)器層是否在分析大量超過(guò)需要的數(shù)據(jù)行。

  • 請(qǐng)求了不需要的數(shù)據(jù)

  ????????有些查詢會(huì)請(qǐng)求超過(guò)實(shí)際需要的數(shù)據(jù),然后這些多余的數(shù)據(jù)會(huì)被應(yīng)用程序丟 棄。這會(huì)給 MySQL 服務(wù)器帶來(lái)額外的負(fù)擔(dān),并增加網(wǎng)絡(luò)開銷,

????????另外也會(huì)消耗應(yīng) 用服務(wù)器的 CPU 和內(nèi)存資源。

  • 查詢不需要的記錄

    一個(gè)常見的錯(cuò)誤是常常會(huì)誤以為 MySQL 會(huì)只返回需要的數(shù)據(jù),實(shí)際上 MySQL 卻是先返回全部結(jié)果集再進(jìn)行計(jì)算。我們經(jīng)常會(huì)看到一些了解其他數(shù)據(jù)庫(kù)系統(tǒng)的人會(huì)設(shè)計(jì)

????????出這類應(yīng)用程序。這些開發(fā)者習(xí)慣使用這樣的技術(shù),先使用 SELECT 語(yǔ)句查詢大量的結(jié)果,然后獲取前面的 N 行后關(guān)閉結(jié)果集(例如在新聞 網(wǎng)站中取出 100 條記錄,

????????但是只是在頁(yè)面上顯示前面 10 條)。他們認(rèn)為 MySQL 會(huì)執(zhí)行查詢,并只返回他們需要的 10 條數(shù)據(jù),然后停止查詢。實(shí)際情況是 MySQL 會(huì)查詢出全部的結(jié)果集,

????????客戶端的應(yīng)用程序會(huì)接收全部的結(jié)果集數(shù)據(jù),然后拋棄 其中大部分?jǐn)?shù)據(jù)。最簡(jiǎn)單有效的解決方法就是在這樣的查詢后面加上 LIMIT。.

  • 總是取出全部列

    每次看到 SELECT*的時(shí)候都需要用懷疑的眼光審視,是不是真的需要返回全 部的列?很可能不是必需的。取出全部列,會(huì)讓優(yōu)化器無(wú)法完成索引覆蓋掃描這 類優(yōu)化,

????????還會(huì)為服務(wù)器帶來(lái)額外的 I/O、內(nèi)存和 CPU 的消耗。因此,一些 DBA 是 嚴(yán)格禁止 SELECT *的寫法的,這樣做有時(shí)候還能避免某些列被修改帶來(lái)的問(wèn)題。 什么時(shí)候應(yīng)該允許

????????查詢返回超過(guò)需要的數(shù)據(jù)?如果這種有點(diǎn)浪費(fèi)數(shù)據(jù)庫(kù)資 源的方式可以簡(jiǎn)化開發(fā),因?yàn)槟芴岣呦嗤a片段的復(fù)用性,如果清楚這樣做的 性能影響,那么這種做法也是值得

????????考慮的。如果應(yīng)用程序使用了某種緩存機(jī)制, 或者有其他考慮,獲取超過(guò)需要的數(shù)據(jù)也可能有其好處,但不要忘記這樣做的代 價(jià)是什么。獲取并緩存所有的列的查詢,相比

????????多個(gè)獨(dú)立的只獲取部分列的查詢可 能就更有好處。

  • 重復(fù)查詢相同的數(shù)據(jù)

 ????????不斷地重復(fù)執(zhí)行相同的查詢,然后每次都返回完全相同的數(shù)據(jù)。比較好的方 案是,當(dāng)初次查詢的時(shí)候?qū)⑦@個(gè)數(shù)據(jù)緩存起來(lái),需要的時(shí)候從緩存中取出,這樣 性能顯然會(huì)更好。

  • 是否在掃描額外的記錄

????????????在確定查詢只返回需要的數(shù)據(jù)以后,接下來(lái)應(yīng)該看看查詢?yōu)榱朔祷亟Y(jié)果是否 掃描了過(guò)多的數(shù)據(jù)。對(duì)于 MySQL,最簡(jiǎn)單的衡量查詢開銷的三個(gè)指標(biāo)如下: 響應(yīng)時(shí)間、

???????掃描的行數(shù)、返回的行

  • 響應(yīng)時(shí)間

  ????????響應(yīng)時(shí)間是兩個(gè)部分之和:服務(wù)時(shí)間和排隊(duì)時(shí)間。 服務(wù)時(shí)間是指數(shù)據(jù)庫(kù)處理這個(gè)查詢真正花了多長(zhǎng)時(shí)間。 排隊(duì)時(shí)間是指服務(wù)器因?yàn)榈却承┵Y源而沒有真正執(zhí)行查詢的時(shí)間

????????—-可能 是等 I/O 操作完成,也可能是等待行鎖,等等。當(dāng)你看到?一個(gè)查詢的響應(yīng)時(shí)間的時(shí)候,首先需要問(wèn)問(wèn)自己,這個(gè)響應(yīng)時(shí)間是 否是一個(gè)合理的值。概括地說(shuō),了解這個(gè)

????????查詢需要哪些索引以及它的執(zhí)行計(jì)劃是 什么,然后計(jì)算大概需要多少個(gè)順序和隨機(jī) I/O,再用其乘以在具體硬件條件下一次 I/O 的消耗時(shí)間。最后把這些消耗都加起來(lái),就可以

????????獲得一個(gè)大概參考值來(lái)判 斷當(dāng)前響應(yīng)時(shí)間是不是一個(gè)合理的值。

  • 掃描的行數(shù)和返回的行數(shù)

  ????????分析查詢時(shí),查看該查詢掃描的行數(shù)是非常有幫助的。這在一定程度上能夠 說(shuō)明該查詢找到需要的數(shù)據(jù)的效率高不高。 理想情況下掃描的行數(shù)和返回的行數(shù)應(yīng)該是相同的。

????????但實(shí)際情況中這種“美 事”并不多。例如在做一個(gè)關(guān)聯(lián)查詢時(shí),服務(wù)器必須要掃描多行才能生成結(jié)果集 中的一行。掃描的行數(shù)對(duì)返回的行數(shù)的比率通常很小,一般在 1:1 和

????????10:1 之間, 不過(guò)有時(shí)候這個(gè)值也可能非常非常大。

  • 掃描的行數(shù)和訪問(wèn)類型

  ????????在評(píng)估查詢開銷的時(shí)候,需要考慮一下從表中找到某一行數(shù)據(jù)的成本。 MySQL 有好幾種訪問(wèn)方式可以查找并返回一行結(jié)果。有些訪問(wèn)方式可能需要掃描 很多行才能返回

????????一行結(jié)果,也有些訪問(wèn)方式可能無(wú)須掃描就能返回結(jié)果。在 EXPLAIN 語(yǔ)句中的 type 列反應(yīng)了訪問(wèn)類型。訪問(wèn)類型有很多種,從全表 掃描到索引掃描、范圍掃描、唯一索引

????????查詢、常數(shù)引用等。這里列的這些,速度 是從慢到快,掃描的行數(shù)也是從小到大。你不需要記住這些訪問(wèn)類型,但需要明 白掃描表、掃描索引、范圍訪問(wèn)和單值訪問(wèn)的概念。

???????? 如果查詢沒有辦法找到合適的訪問(wèn)類型,那么解決的最好辦法通常就是增加 一個(gè)合適的索引,為什么索引對(duì)于查詢優(yōu)化如此重要了。索引讓 MySQL 以最高 效、掃描行數(shù)最少

????????的方式找到需要的記錄。 一般 MySQL 能夠使用如下三種方式應(yīng)用 WHERE 條件,從好到壞依次為

????????在索引中使用 WHERE 條件來(lái)過(guò)濾不匹配的記錄。這是在存儲(chǔ)引擎層完成 的。使用索引覆蓋掃描(在 Extra 列中出現(xiàn)了 Using index)來(lái)返回記錄,直接 從索引中過(guò)濾不需要

????????的記?錄并返回命中的結(jié)果。這是在 MySQL 服務(wù)器層完成的, 但無(wú)須再回表查詢記錄。從數(shù)據(jù)表中返回?cái)?shù)據(jù),然后過(guò)濾不滿足條件的記錄(在 Extra 列中出現(xiàn) Using Where)。這在 ????????MySQL 服務(wù)器層完成,MySQL 需要先從數(shù)據(jù)表讀出記錄然 后過(guò)濾。

    好的索引可以讓查詢使用合適的訪問(wèn)類型,盡可能地只掃描需要的數(shù)據(jù)行。 如果發(fā)現(xiàn)查詢需要掃描大量的數(shù)據(jù)但只返回少數(shù)的行,那么通常可以嘗試下 面的技巧去優(yōu)化它:

????????????????????????使用索引覆蓋掃描,把所有需要用的列都放到索引中,這樣存儲(chǔ)引擎無(wú) 須回表獲取對(duì)應(yīng)行就可以返回結(jié)果了。

????????????????????????改變庫(kù)表結(jié)構(gòu)。例如使用單獨(dú)的匯總表。

????????????????????????重寫這個(gè)復(fù)雜的查詢,讓 MySQL 優(yōu)化器能夠以更優(yōu)化的方式執(zhí)行這個(gè) 查詢。

????????????????????????重構(gòu)查詢的方式

????????????????在優(yōu)化有問(wèn)題的查詢時(shí),目標(biāo)應(yīng)該是找到一個(gè)更優(yōu)的方法獲得實(shí)際需要的結(jié) 果。 而不一定總是需要從 MySQL 獲取一模一樣的結(jié)果集。有時(shí)候,可以將查 詢轉(zhuǎn)換一種

?????????寫法讓其返回一樣的結(jié)果,但是性能更好。一個(gè)復(fù)雜查詢還是多個(gè)簡(jiǎn)單查詢。如果一個(gè)查詢的需求很復(fù)雜,Sql語(yǔ)句很長(zhǎng),考慮把查詢語(yǔ)句拆分,拆成多個(gè)查詢語(yǔ)句,在應(yīng)用

? ? ? ? ?層匯總?數(shù)據(jù), 這樣做的好處提高sql閱讀和維護(hù)。

  • 分解關(guān)聯(lián)查詢  

  ????????很多高性能的應(yīng)用都會(huì)對(duì)關(guān)聯(lián)查詢進(jìn)行分解。簡(jiǎn)單地,可以對(duì)每一個(gè)表進(jìn)行 一次單表查詢,然后將結(jié)果在應(yīng)用程序中進(jìn)行關(guān)聯(lián)。

? ? ? ? ? ? ? ? ? ? ? ? 1. 讓緩存的效率更高。許多應(yīng)用程序可以方便地緩存單表查詢對(duì)應(yīng)的結(jié)果對(duì)象。 將查詢分解后,執(zhí)行單個(gè)查詢可以減少鎖的競(jìng)爭(zhēng)。

? ? ? ? ? ? ? ? ? ? ? ? 2. 在應(yīng)用層做關(guān)聯(lián),可以更容易對(duì)數(shù)據(jù)庫(kù)進(jìn)行拆分,更容易做到高性能和可擴(kuò) 展。查詢本身效率也可能會(huì)有所提升。

? ? ? ? ? ? ? ? ? ? ? ? 3. 可以減少冗余記錄的查詢。在應(yīng)用層做關(guān)聯(lián)查詢,意味著對(duì)于某條記錄應(yīng)用 只需要查詢一次,而在數(shù)據(jù)庫(kù)中做關(guān)聯(lián)查詢,則可能需要重復(fù)地訪問(wèn)一部分?jǐn)?shù)據(jù)。

???????????????????????????這樣的重構(gòu)還可能會(huì)減少網(wǎng)絡(luò)和內(nèi)存的消耗。

? ? ? ? ? ? ? ? ? ? ? ? 4. 更進(jìn)一步,這樣做相當(dāng)于在應(yīng)用中實(shí)現(xiàn)了哈希關(guān)聯(lián),而不是使用 MySQL 的 嵌套循環(huán)關(guān)聯(lián)。某些場(chǎng)景哈希關(guān)聯(lián)的效率要高很多。

  ????????在很多場(chǎng)景下,通過(guò)重構(gòu)查詢將關(guān)聯(lián)放到應(yīng)用程序中將會(huì)更加高效,這樣的 場(chǎng)景有很多,比如:當(dāng)應(yīng)用能夠方便地緩存單個(gè)查詢的結(jié)果的時(shí)候、當(dāng)可以將數(shù) 據(jù)分布

?????????到不同的 MySQL 服務(wù)器上的時(shí)候、當(dāng)能夠使用 IN()的方式代替關(guān)聯(lián)查詢 的時(shí)候、當(dāng)查詢中使用同一個(gè)數(shù)據(jù)表的時(shí)候。

  • 慢查詢配置

  ????????我們已經(jīng)知道慢查詢?nèi)罩究梢詭椭ㄎ豢赡艽嬖趩?wèn)題的 SQL 語(yǔ)句,從而進(jìn)行 SQL 語(yǔ)句層面的優(yōu)化。但是默認(rèn)值為關(guān)閉的,需要我們手動(dòng)開啟。

  查看慢查詢是否開啟?show VARIABLES like 'slow_query_log';? ? 如果off 則是關(guān)閉 需要開啟。

  ????????慢查詢開啟:?set GLOBAL slow_query_log=1; 再次調(diào)用上個(gè)命令查看是否開啟成功。

    ????????show VARIABLES like '%long_query_time%';? 運(yùn)行時(shí)間超過(guò)該值的所有 SQL 語(yǔ)句都記錄到慢查詢?nèi)罩局小?/p>

    ????????set? long_query_time=0; 設(shè)置慢查詢閾值,這里設(shè)置0是測(cè)試值, 實(shí)際設(shè)置值需要調(diào)整。

  對(duì)于沒有運(yùn)行的 SQL 語(yǔ)句沒有使用索引,則 MySQL 數(shù)據(jù)庫(kù)也可以將這 條 SQL 語(yǔ)句記錄到慢查詢?nèi)罩疚募?#xff0c;控制參數(shù)是:  

      show VARIABLES like '%log_queries_not_using_indexes%';

      set GLOBAL log_queries_not_using_indexes=1; 開啟

    慢查詢?nèi)罩据敵鑫恢?/p>

      show VARIABLES like 'log_output';

    小結(jié)

????????????????????????slow_query_log 啟動(dòng)停止慢查詢?nèi)罩?

????????????????????????slow_query_log_file 指定慢查詢?nèi)罩镜么鎯?chǔ)路徑及文件(默認(rèn)和數(shù)據(jù) 文件放一起)?

????????????????????????long_query_time 指定記錄慢查詢?nèi)罩?SQL 執(zhí)行時(shí)間得伐值(單位: 秒,默認(rèn) 10 秒)?

????????????????????????log_queries_not_using_indexes 是否記錄未使用索引的 SQL

????????????????????????log_output 日志存放的地方可以是[TABLE][FILE][FILE,TABLE]

  • 慢查詢解讀分析

    日志格式

    tail -f /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log // 這文件時(shí)執(zhí)行slow_query_log_file 取的文件名

????????????????# Time: 2021-12-05T05:27:02.408009Z? ?//?查詢執(zhí)行時(shí)間
????????????????# User@Host: root[root] @ localhost [] Id: 14 //?用戶名 、用戶的 IP 信 息、線程 ID 號(hào)
????????????????# Query_time: 0.000329 Lock_time: 0.000171 Rows_sent: 0 Rows_examined: 0

????????// Query_time?執(zhí)行花費(fèi)的時(shí)長(zhǎng)(ms )Lock_time?執(zhí)行獲得鎖的時(shí)長(zhǎng)?Rows_sentc?獲 得的結(jié)果行數(shù)?Rows_examined?掃描的數(shù)據(jù)行數(shù)
????????????????SET timestamp=1638682022;//這 SQL 執(zhí)行的具體時(shí)間
????????????????select * from student where sid=1000;//具體sql語(yǔ)句

  • 慢查詢分析

  ????????慢查詢的日志記錄非常多,要從里面找尋一條查詢慢的日志并不是很容易的 事情,一般來(lái)說(shuō)都需要一些工具輔助才能快速定位到需要優(yōu)化的 SQL 語(yǔ)句,

  ????????下面介紹慢查詢輔助工具 mysqldumpslow 常用的慢查詢?nèi)罩痉治龉ぞ?#xff0c;匯總除查詢條件外其他完全相同的 SQL,并將 分析結(jié)果按照參數(shù)中所指定的順序輸出。

? ? ? ? ? ? ? ? 主要參數(shù)如下

   ????????????????語(yǔ)法: sudo mysqldumpslow -s r -t 5 /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log (sudo是我在ubuntu執(zhí)行的 其他linux 不需要sudo)

      ????????-s order (c,t,l,r,at,al,ar)

        ????????c:總次數(shù)

        ????????t:總時(shí)間

        ????????l:鎖的時(shí)間

        ????????r?:獲得的結(jié)果行數(shù) at,al,ar :指 t,l,r 平均數(shù) 【例如:at = 總時(shí)間/總次數(shù)】

     ????????????????-s 對(duì)結(jié)果進(jìn)行排序,怎么排,根據(jù)后面所帶的 (c,t,l,r,at,al,ar),缺省為 at

    ? ?????????????????-t NUM just show the top n queries:僅顯示前 n 條查詢

    ??????????????????-g PATTERN grep: only consider stmts that include this string:通過(guò) grep 來(lái) 篩選語(yǔ)句。

????????????????????????執(zhí)行結(jié)果

????????????????????????Reading mysql slow query log from /var/lib/mysql/huangbingbing-Shangqi-X4270-slow.log
????????????????????????Count: 2 Time=0.00s (0s) Lock=0.00s (0s) Rows=19.0 (38), root[root]@localhost
????????????????????????show tables

????????????????????????Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=12.0 (12), root[root]@localhost
????????????????????????desc slow_log

????????????????????????Count: 2 Time=0.00s (0s) Lock=0.00s (0s) Rows=5.0 (10), root[root]@localhost
????????????????????????show databases

????????????????????????Count: 6 Time=0.00s (0s) Lock=0.00s (0s) Rows=1.0 (6), root[root]@localhost
????????????????????????show variables like 'S'

???????????????????????Count: 5 Time=0.00s (0s) Lock=0.00s (0s) Rows=0.8 (4), root[root]@localhost
???????????????????????show VARIABLES like 'S'

總結(jié):

  掌握了Mysql慢查詢的意義和如何分析慢查詢,為執(zhí)行計(jì)劃學(xué)習(xí)做準(zhǔn)備,下一文章將分析MySql執(zhí)行計(jì)劃。

技術(shù)參考

C/C++Linux服務(wù)器開發(fā)/后臺(tái)架構(gòu)師【零聲教育】-學(xué)習(xí)視頻教程-騰訊課堂

總結(jié)

以上是生活随笔為你收集整理的MySQL 性能优化一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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