MySQL-調優策略-SQL語句

引言

架構調優,在系統設計時首先需要充分考慮業務的實際情況,是否可以把不適合數據庫做的事情放到數據倉庫、搜索引擎或者緩存中去做;然后考慮寫的并發量有多大,是否需要采用分布式;最后考慮讀的壓力是否很大,是否需要讀寫分離。對于核心應用或者金融類的應用,需要額外考慮數據安全因素,數據是否不允許丟失。所以在進行優化時,首先需要關注和優化的應該是架構,如果架構不合理,即使是DBA能做的事情其實是也是比較有限的。

MySQL調優,需要確認業務表結構設計是否合理,SQL語句優化是否足夠,該添加的索引是否都添加了,是否可以剔除多余的索引等等

本文已如上角度進行分析,當然,關于業務表結構是否合理的話題,在今后深入到MySQL底層再討論。

同時,本文將介紹一些常用的提高索引效率的方案。

慢查詢基礎-數據訪問

查詢花費大量時間,超過long_query_time參數設定的時間閾值的SQL語句。

一般查詢性能低下的最基本原因是訪問的數據太多。

故,我們對于低效的查詢一般通過兩種步驟分析:是否檢索了大量不需要的數據、是否超過需要的數據行。

檢索了大量不需要的數據-列

總是取出全部列?

每次看到SELECT*的時候都需要用懷疑的眼光審視,是不是真的需要返回全部的列?很可能不是必需的。取出全部列,會讓優化器無法完成索引覆蓋掃描這類優化,還會為服務器帶來額外的I/O、內存和CPU的消耗。因此,一些DBA是嚴格禁止SELECT *的寫法的,這樣做有時候還能避免某些列被修改帶來的問題。

尤其是使用二級索引,使用*的方式會導致回表,導致性能低下。

什么時候可以使用?SELECT*如果應用程序使用了某種緩存機制,或者有其他考慮,獲取超過需要的數據也可能有其好處,但不要忘記這樣做的代價是什么。獲取并緩存所有的列的查詢,相比多個獨立的只獲取部分列的查詢可能就更有好處。

重復查詢相同的數據-加緩存

不斷地重復執行相同的查詢,然后每次都返回完全相同的數據。比較好的方案是,當初次查詢的時候將這個數據緩存起來,需要的時候從緩存中取出,這樣性能顯然會更好。

衡量查詢開銷的指標

響應時間(服務時間+排隊時間)、掃描行數、返回行數、訪問類型

如果發現查詢需要掃描大量的數據但只返回少數的行,那么通常可以嘗試下面的技巧去優化它:

1、使用索引覆蓋掃描,把所有需要用的列都放到索引中,這樣存儲引擎無須回表獲取對應行就可以返回結果了

2、改變庫表結構。例如使用單獨的匯總表。

3、重寫這個復雜的查詢,讓MySQL優化器能夠以更優的方式執行該查詢。

慢查詢配置

set global long_query_time=10; (10秒)

l slow_query_log 啟動停止慢查詢日志

l slow_query_log_file 指定慢查詢日志得存儲路徑及文件(默認和數據文件放一起)

l long_query_time 指定記錄慢查詢日志SQL執行時間得伐值(單位:秒,默認10秒)

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

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

Explian執行計劃

EXPLAIN語句來幫助我們查看某個查詢語句的具體執行計劃,我們需要搞懂EPLATNEXPLAIN的各個輸出項都是干嘛使的,從而可以有針對性的提升我們查詢語句的性能。

分析查詢語句或是表結構的性能瓶頸,總的來說通過EXPLAIN我們可以:

l 表的讀取順序

l 數據讀取操作的操作類型

l 哪些索引可以使用

l 哪些索引被實際使用

l 表之間的引用

l 每張表有多少行被優化器查詢

type

我們前邊說過執行計劃的一條記錄就代表著MySQL對某個表的執行查詢時的訪問方法/訪問類型,其中的type列就表明了這個訪問方法/訪問類型是個什么東西,是較為重要的一個指標,結果值從最好到最壞依次是:

出現比較多的是system>const>eq_ref>ref>range>index>ALL

一般來說,得保證查詢至少達到range級別,最好能達到ref。

查詢優化器

SQL語句在MySQL中執行過程如圖所示。

優化:優化SQL語句,例如重寫查詢,決定表的讀取順序,以及選擇需要的索引等。這一階段用戶是可以查詢的,查詢服務器優化器是如何進行優化的,便于用戶重構查詢和修改相關配置,達到最優化。這一階段還涉及到存儲引擎,優化器會詢問存儲引擎,比如某個操作的開銷信息、是否對特定索引有查詢優化等。

高性能索引使用策略

不在索引列進行任何操作

盡量全值匹配

最佳左前綴法則

范圍條件放在最后

覆蓋索引盡量用

不等于慎用

Null/Not對查詢有影響

小心Like查詢

字符類型加上引號

小心使用or關鍵字

使用索引掃描來排序或分組

排序注意點

盡可能按照主鍵順序插入行

優化Count查詢

優化limit分頁

NULL特別說明

不在索引列進行任何操作:

在索引列上使用函數,是無法利用索引的;索引列不進行計算操作,MySQL無法自動解析方程式。

盡量全值匹配:

建立了聯合索引列后,如果我們的搜索條件中的列和索引列一致的話,這種情況就稱為全值匹配。查詢優化器會決定先用哪個后用哪個查詢的條件~

最佳左前綴法則:

建立了聯合索引列,如果搜索條件不夠全值匹配怎么辦?在我們的搜索語句中也可以不用包含全部聯合索引中的列,但要遵守最左前綴法則。指的是查詢從索引的最左前列開始并且不跳過索引中的列。PS:建立聯合索引只會產生一顆B+樹

范圍條件放最后

所有記錄都是按照索引列的值從小到大的順序排好序的,而聯合索引則是按創建索引時的順序進行分組排序。如果對多個列同時進行范圍查找的話,只有對索引最左邊的那個列進行范圍查找的時候才能用到B+樹索引。對于一個聯合索引來說,雖然對多個列都進行范圍查找時只能用到最左邊那個索引列,但是如果左邊的列是精確查找,則右邊的列可以進行范圍查找;而中間有范圍查詢會導致后面的列全部失效,無法充分利用這個聯合索引

覆蓋索引盡量用(不回表)

覆蓋索引是非常有用的工具,能夠極大地提高性能,三星索引里最重要的那顆星就是寬索引星。如果查詢只需要掃描索引而無須回表,

索引條目通常遠小于數據行大小,所以如果只需要讀取索引,那 MySQL就會極大地減少數據訪問量。這對緩存的負載非常重要,因為這種情況下響應時間大部分花費在數據拷貝上。覆蓋索引對于I/O密集型的應用也有幫助,因為索引比數據更小,更容易全部放入內存中。

因為索引是按照列值順序存儲的,所以對于I/O密集型的范圍查詢會比隨機從磁盤讀取每一行數據的I/O要少得多。

由于InnoDB的聚簇索引,覆蓋索引對InnoDB表特別有用。InnoDB的二級索引在葉子節點中保存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。

盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),不是必要的情況下減少select*,除非是需要將表中的全部列檢索后,進行緩存。

慎用不等于(mysql 在使用不等于(!= 或者<>)的時候無法使用索引會導致全表掃描)

小心Like查詢

like以通配符開頭('%abc...'),mysql索引失效會變成全表掃描的操作。解決方案是使用覆蓋索引涉及到的列進行like查詢。

字符類型加引號,不加單引號導致索引失效奧

原因:MySQL的查詢優化器,會自動的進行類型轉換,自然造成索引失效。

使用or關鍵字時要注意

使用同一列進行or,沒啥。如果or的兩列不是同一列,某個不是索引,就只能全盤掃描。這種情況下可以通過union all 或者 覆蓋掃描 改善這種問題。

使用索引掃描來排序和分組

MySQL有兩種方式可以生成有序的結果﹔通過排序操作﹔或者按索引順序掃描施﹔如果EXPLAIN出來的type列的值為“index”,則說明MySQL使用了索引掃描來做排序。

掃描索引本身是很快的,因為只需要從一條索引記錄移動到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那就不得不每掃描一條索引記錄就都回表查詢一次對應的行。這基本上都是隨機I/O,因此按索引順序讀取數據的速度通常要比順序地全表掃描慢,尤其是在IO密集型的工作負載時。

MySQL可以使用同一個索引既滿足排序,又用于查找行。因此,如果可能,設計索引時應該盡可能地同時滿足這兩種任務,這樣是最好的。

只有當索引的列順序和ORDER BY子句的順序完全一致,并且所有列的排序方向(倒序或正序)都一樣時,MySQL才能夠使用索引來對結果做排序。如果查詢需要關聯多張表,則只有當ORDER BY子句引用的字段全部為第一個表時,才能使用索引做排序。

排序小心

排序列包含非同一個索引的列的情況,不能用索引進行排序。

盡可能按主鍵順序插入行

最好避免隨機的(不連續且值的分布范圍非常大)聚簇索引,特別是對于I/O密集型的應用。例如,從性能的角度考慮,使用UUID來作為聚簇索引則會很糟糕,它使得聚簇索引的插入變得完全隨機,這是最壞的情況,使得數據沒有任何聚集特性。

最簡單的方法是使用AUTO_INCREMENT自增列。這樣可以保證數據行是按順序寫入,對于根據主鍵做關聯操作的性能也會更好。

注意到向UUID主鍵插入行不僅花費的時間更長,而且索引占用的空間也更大。這一方面是由于主鍵字段更長﹔另一方面毫無疑問是由于頁分裂和碎片導致的。

因為主鍵的值是順序的,所以InnoDB把每一條記錄都存儲在上一條記錄的后面。當達到頁的最大填充因子時(InnoDB默認的最大填充因子是頁大小的15/16,留出部分空間用于以后修改),下一條記錄就會寫入新的頁中。一旦數據按照這種順序的方式加載,主鍵頁就會近似于被順序的記錄填滿,這也正是所期望的結果。

如果新行的主鍵值不一定比之前插入的大,所以InnoDB無法簡單地總是把新行插入到索引的最后,而是需要為新的行尋找合適的位置-—通常是已有數據的中間位置——并且分配空間。這會增加很多的額外工作,并導致數據分布不夠優化。下面是總結的一些缺點:

寫入的目標頁可能已經刷到磁盤上并從緩存中移除,或者是還沒有被加載到緩存中,InnoDB在插入之前不得不先找到并從磁盤讀取目標頁到內存中。這將導致大量的隨機IO。

因為寫入是亂序的,InnoDB不得不頻繁地做頁分裂操作,以便為新的行分配空間。頁分裂會導致移動大量數據,一次插入最少需要修改三個頁而不是一個頁。

所以使用InnoDB時應該盡可能地按主鍵順序插入數據,并且盡可能地使用單調增加的聚簇鍵的值來插入新行。

優化count查詢

COUNT()是一個特殊的函數,有兩種非常不同的作用:它可以統計某個列值的數量,也可以統計行數。

通常來說,COUNT()都需要掃描大量的行(意味著要訪問大量數據)才能獲得精確的結果,因此是很難優化的。在MySQL層面能做的基本只有索引覆蓋掃描了。如果這還不夠,就需要考慮修改應用的架構,可以用估算值取代精確值,可以增加匯總表,或者增加類似Redis這樣的外部緩存系統。

優化limit分頁查詢

先查詢翻頁中需要的N條數據的主鍵值,然后根據主鍵值回表查詢所需要的N條數據,在此過程中查詢N條數據的主鍵id在索引中完成,所以效率會高一些。

EXPLAIN SELECT * FROM (select id from order_exp limit 10000,10) b,order_exp

a where a.id = b.id;

select * from order_exp limit 10000,10; 這種偏移量大,相當于舍棄1w條數據,只要后面10條,這也是查詢遠超出需要的數據列。

關于NULL的特別說明

NULL 在MySQL中是獨一無二的!MySQL8 在進行索引列的數據統計行為把null視為nulls_equal情況(NULL值在業務上就是代表沒有,所有的NULL值和起來算一份),看起來,MySQL中對Null值的處理也很分裂。所以總的來說,對于列的聲明盡可能的不要允許為null。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73468.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73468.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73468.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

6502電氣集中聯鎖道岔控制電路的工作過程

6502電氣集中聯鎖道岔控制電路的工作過程主要包括選擇進路、轉換道岔、鎖閉進路、開放信號和解鎖進路等環節&#xff0c;以下是其具體工作過程模擬&#xff1a; 選擇進路&#xff1a; 按壓按鈕&#xff1a;操作人員在控制臺上按壓進路兩端的按鈕&#xff0c;如始端按鈕和終端按…

DS足球監控【比分直播】監控,釘釘實現自動提醒

文章目錄 目標網站分析詳細分析提醒工具代碼截圖成功提示對爬蟲、逆向感興趣的同學可以查看文章,一對一小班教學:https://blog.csdn.net/weixin_35770067/article/details/142514698 目標網站分析 https://live.dszuqiu.com/監控目標:實現固定時間內對比分監控,實現自動下單…

基于ssm的醫院預約掛號系統

一、系統架構 前端&#xff1a;jsp | bootstrap | jquery | css | ajax 后端&#xff1a;spring | springmvc | mybatis 環境&#xff1a;jdk1.8 | mysql | maven | tomcat 二、代碼及數據 三、功能介紹 01. 注冊 02. 登錄 03. 首頁 04. 醫院掛號 05. …

華為OD機試A卷 - 快遞業務站 計算快遞主站點(C++ Java JavaScript Python )

最新華為OD機試 真題目錄:點擊查看目錄 華為OD面試真題精選:點擊立即查看 題目描述 快遞業務范圍有 N 個站點,A 站點與 B 站點可以中轉快遞,則認為 A-B 站可達, 如果 A-B 可達,B-C 可達,則 A-C 可達。 現在給 N 個站點編號 0、1、…n-1,用 s[i][j]表示 i-j 是否可…

三維動態規劃-LeetCode3418. 機器人可以獲得的最大金幣數

太爽了&#xff01;做完這道題&#xff0c;讓我感覺就像是斬殺了一條大龍&#xff01;歷時72天&#xff0c;分3次花掉30小時。終獲突破&#xff01; 零、題目 3418. 機器人可以獲得的最大金幣數 給你一個 m x n 的網格。一個機器人從網格的左上角 (0, 0) 出發&#xff0c;目…

相生、相克、乘侮、復雜病機及對應的臟腑功能聯系

一、五行相生關系&#xff08;母子關系&#xff09; 五行生序臟腑關系生理表現舉例木生火肝&#xff08;木&#xff09;滋養心&#xff08;火&#xff09;肝血充足則心血旺盛火生土心&#xff08;火&#xff09;溫煦脾&#xff08;土&#xff09;心陽充足則脾胃運化功能正常土…

Ubuntu22.04搭建freeradius操作說明

Ubuntu22.04搭建freeradius操作說明 更新依賴庫 sudo apt update sudo apt install build-essential sudo apt install libtalloc-dev sudo apt install libssl-dev 按照freeradius sudo apt install freeradius 修改freeradius配置 文件路徑如下 /etc/freeradius/3.…

es中安裝ik分詞器

在線安裝ik插件&#xff08;較慢&#xff09; docker exec -it es /bin/bash ./bin/es-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip 看到報錯了&#xff0c;我訪問一下。就是沒有了…

最大字段和問題 C++(窮舉、分治法、動態規劃)

問題描述 給定由n個整數&#xff08;包含負整數&#xff09;組成的序列a1,a2,…,an&#xff0c;求該序列子段和的最大值。規定當所有整數均為負值時定義其最大子段和為0 窮舉法 最簡單的方法就是窮舉法&#xff0c;用一個變量指示求和的開始位置&#xff0c;一個變量指示結束…

如何理解三極管截至區、放大區、飽和區

一、 三極管符號&#xff1a; NPN : PNP: 二、Vce、與Ic曲線圖 1、截至區&#xff1a;ib很小的時候就是截至區。因為Ib很小的時候等價于Ub很小&#xff0c;Ub如果不足以達到0.7V PN結就不會導通&#xff0c;所以三極管就…

電腦上我的windows目錄下,什么是可以刪除的

在Windows系統目錄&#xff08;通常是C:\Windows&#xff09;中&#xff0c;大部分文件和文件夾都是系統運行所必需的&#xff0c;隨意刪除可能導致系統崩潰或程序無法運行。不過&#xff0c;部分文件可以安全清理。以下是詳細指南&#xff1a; 可安全清理的內容 臨時文件&…

工作中遇到的spark SQL小問題:包含某個或某些字符的條件

今天又來總結工作中遇到的問題了&#xff0c;今天是SQL&#xff0c;spark引擎 需求描述&#xff0c;篩選渠道包含”線上化“的數據 也就是討論where里面的這個篩選條件怎么寫 一般起手都是 where QD like %線上化%‘ 學習了其他的寫法: 1.INSTR函數 where INSTR(QD,&quo…

Git 命令操作完全指南

Git 是現代軟件開發中不可或缺的分布式版本控制系統。它不僅能追蹤代碼變更&#xff0c;還能協調多人協作、管理項目歷史。本文從核心概念入手&#xff0c;逐步深入講解 Git 的基礎與高級命令&#xff0c;結合實用場景&#xff0c;幫助您從入門到精通。 一、Git 核心概念 理解…

深入剖析帶頭循環雙向鏈表的實現與應用

引言 場景描述 想象一個 環形地鐵線路&#xff08;如深圳地鐵11號線&#xff09;&#xff0c;這條線路首尾相連&#xff0c;列車可以順時針或逆時針循環行駛。為了方便管理&#xff0c;地鐵系統設置了一個 “虛擬調度中心”&#xff08;頭節點&#xff09;&#xff0c;它不承…

DeepSeek Smallpond 在火山引擎 AI 數據湖的探索實踐

資料來源&#xff1a;火山引擎-開發者社區 DeepSeek Smallpond 介紹 Smallpond 是一套由 DeepSeek 推出的 、針對 AI 領域&#xff0c;基于 Ray 和 DuckDB 實現的輕量級數據處理引擎&#xff0c;具有以下優點&#xff1a; 1.輕量級 2.高性能 3.支持規模大 4.無需運維 5.P…

Linux進程間的通信

進程間通信 1.進程間通信介紹2.匿名命名管道原理操作 1.進程間通信介紹 1.1 進程間通信目的&#xff1a;一個進程需要將他的數據發送給另一個進程&#xff0c;大家應該都多少接觸過linux中的管道符"|"&#xff0c;這個符號就是用來多個命令執行&#xff0c;在Linux中…

直播預告 | TDgpt 智能體發布 時序數據庫 TDengine 3.3.6 發布會即將開啟

從海量監控數據&#xff0c;到工業、能源、交通等場景中實時更新的各類傳感器數據&#xff0c;時序數據正在以指數級速度增長。而面對如此龐雜的數據&#xff0c;如何快速分析、自動發現問題、精準預測未來&#xff0c;成為企業數字化轉型過程中的關鍵挑戰。 TDengine 的答案是…

手撕FIO工具指南:從壓測翻車到避坑實戰

文章目錄 手撕FIO工具指南&#xff1a;從壓測翻車到避坑實戰一、背景&#xff1a;一次FIO壓測引發的驚魂夜二、FIO vs 其他IO工具&#xff1a;為何讓人又愛又怕&#xff1f;三、安裝指南&#xff1a;避開依賴地獄四、參數詳解五、避坑指南&#xff1a;血淚經驗總結六、安全壓測…

智能汽車圖像及視頻處理方案,支持視頻星軌拍攝能力

美攝科技作為智能汽車圖像及視頻處理領域的先行者&#xff0c;正以革新性的技術引領著行業的未來發展。美攝科技智能汽車圖像及視頻處理方案&#xff0c;一個集高效性、智能化、畫質增強于一體的創新解決方案&#xff0c;旨在重塑智能汽車圖像畫質的新標準&#xff0c;并支持前…

B站左神算法課學習筆記(P7):圖

目錄 一、圖的存儲方式&#xff08;千奇百怪&#xff09; 1&#xff09;鄰接表 2&#xff09;鄰接矩陣 3&#xff09;其他 4&#xff09;推薦存儲方式&#xff08;代碼&#xff09; 二、圖的遍歷 &#xff08;1&#xff09;寬度優先遍歷 &#xff08;2&#xff09;深度…