MYSQL優化彙總——學習入口

mysql優化的方式總的有以下幾種方式
1.msql服務器硬件的優化;單核CPU變成多核,加內存,這一般是運維乾的事情。
2.mysql服務的配置參數的優化;
3.sql語句本身的優化;
4.數據庫設計時的範式設計;
5.索引優化;
以上五點我們今天主要說說後面的四種,請聽我慢慢碎碎

1 mysql服務的配置參數優化

1.1 max_connections最大連接數

MySQL的最大連接數
如果服務器的併發連接請求量比較大,建議調高此值,以增加並行連接數量,當然這建立在機器能支撐的情況下,因爲如果連接數越多,MySql會爲每個連接提供連接緩衝區,就會開銷越多的內存,連接數太大,服務器消耗的內存越多,以至於影響服務器性能,所以要根據服務器的配置適當調整該值,不能盲目提高設值。可以過’conn%'通配符查看當前狀態的連接數量,以定奪該值的大小。下面給大家一個公式參考設置,但是mysql最大連接數不能超過1000,超過了操作系統不支持了

max_used_connections / max_connections * 100%(理想值≈ 85%),如果max_used_connections跟max_connections相同,那麼就是max_connections設置過低或者超過服務器負載上限了,低於10%則設置過大

mysql> show status like 'max_used_connections'; #響應的連接數
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Max_used_connections | 609   |
+----------------------+-------+
1 row in set (0.02 sec)
 
mysql> show variables like 'max_connections'; #最大連接數
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 800   |
+-----------------+-------+
1 row in set (0.02 sec)

1.2 back_log   MySQL能暫存的連接數量

當主要MySQL線程在一個很短時間內得到非常多的連接請求,這就起作用。如果MySQL的連接數據達到max_connections時,新來的請求將會被存在堆棧中,以等待某一連接釋放資源,該堆棧的數量即back_log,如果等待連接的數量超過back_log,將不被授予連接資源。 
back_log值指出在MySQL暫時停止回答新請求之前的短時間內有多少個請求可以被存在堆棧中。只有如果期望在一個短時間內有很多連接,你需要增加它,換句話說,這值對到來的TCP/IP連接的偵聽隊列的大小。 
mysql中back_log的設置取決於操作系統,在Linux下這個參數的值不能大於系統參數tcp_max_syn_backlog的值。通過以下命令可以查看tcp_max_syn_backlog的當前值 cat /proc/sys/net/ipv4/tcp_max_syn_backlog。 >默認數值是50,可調優爲128。

mysql> show variables like 'back_log%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| back_log      | 211   |
+---------------+-------+
1 row in set (0.02 sec)

1.3 thread_cache_size 線程池大小

可以複用的保存在內存中的線程的數量。如果有,新的線程從緩存中取得,當斷開連接的時候如果有空間,客戶的線置將保存在緩存中。如果有很多新的線程,爲了提高性能可以增加這個變量值。通過比較 Connections和Threads_created狀態的變量,可以看到這個變量的作用,如下:

mysql> show global status like ‘Thread%’;
+——————-+———-+
| Variable_name | Value |
+——————-+———-+
| Threads_cached | 26 |
| Threads_connected | 510 |
| Threads_created | 35168165 |
| Threads_running | 459 |
+——————-+———-+
4 rows in set (0.01 sec)

Threads_cached :代表當前此時此刻線程緩存中有多少空閒線程。
Threads_connected :代表當前已建立連接的數量,因爲一個連接就需要一個線程,所以也可以看成當前被使用的線程數。 Threads_created :代表從最近一次服務啓動,已創建線程的數量。
Threads_running :代表當前激活的(非睡眠狀態)線程數。並不是代表正在使用的線程數,有時候連接已建立,但是連接處於sleep狀態,這裏相對應的線程也是sleep狀態。 >默認值爲110,可調優爲80。 

1.4 wait_timeout  指定一個請求的最大連接時間

對於4GB左右內存的服務器可以設置爲5-10。 


1.5 innodb_thread_concurrency  線程併發數

推薦設置爲 2*(NumCPUs+NumDisks),默認一般爲8。

1.6 緩存參數

緩存參數主要有key_buffer_size索引緩衝區大小,query_cache_size 總查詢緩衝大小,query_cache_limit單個查詢緩衝區大小 默認1M,query_cache_type指定是否使用查詢緩衝,可以設置爲0、1、2是否使用查詢緩衝區;等等這裏參數比較多不一一解釋,大家可以參考該博文

 https://blog.csdn.net/LNView/article/details/80325648?ops_request_misc=%7B%22request%5Fid%22%3A%22158159859319724845027301%22%2C%22scm%22%3A%2220140713.130056874..%22%7D&request_id=158159859319724845027301&biz_id=0&utm_source=distribute.pc_search_result.none-task

1.7 開啓慢查詢日誌 方便mysql語句的優化

具體操作參考我的開啓慢查詢一文

mysql語句本身的優化——sql優化十策略

mysql語句優化我總結了十策略;
1.儘量全值匹配
2.最佳左前綴法制
3.不在索引列上做計算
4.範圍條件字段放索引最後
5.覆蓋索引儘量用
6.不等於用慎用
7.null/not有影響
8.like要擔心
9.字符類型要加引號
10.or 改union

點我看詳細信息

數據庫範式的學習——設計數據庫時參考

第一範式(1NF):每個字段列不可分割的原子數據項
第二範式(2NF):非主鍵屬性必須完全依賴於主鍵
第三範式(3NF):任何非主屬性不依賴於其它非主屬性
巴斯-科德範式(BCNF):在3NF基礎上,任何非主屬性不能對主鍵子集依賴(在3NF基礎上消除對主碼子集的依賴)

索引的優化

在說索引優化之前我們得知道幾點mysql儲存引擎知識,索引的種類有
普通索引:僅加速查詢
唯一索引:加速查詢 + 列值唯一(可以有null)
主鍵索引:加速查詢 + 列值唯一(不可以有null)+ 表中只有一個
組合索引:多列值組成一個索引,專門用於組合搜索,其效率大於索引合併
全文索引:對文本的內容進行分詞,進行搜索(經常使用專業的搜索服務器,如lucene, es,solr他們利用分詞器,分詞過濾器 構建倒排索引)
ps.
說到索引種類還的說說,數據的儲存方式 聚簇索引 與 非聚簇索引;每種儲存引擎儲存索引的數據結構不同,這裏我介紹下InnoDB的聚簇索引實際上在同一個結構中保存了B+Tree索引和數據行。當表中有聚簇索引時,它的數據實際上存儲在索引的葉子頁中(葉子頁中包含了行的全部數據)。而沒有聚簇索引時B+Tree葉子頁存放的是指向數據的指針,查詢時會有二次查詢。

索引的優化需要藉助倆個工具 一個慢查詢日誌的分析工具mysqldumpshow.pl 該工具mysql安裝時已經安裝好了,只是它是perl語言開發的,需要安裝運行環境;安裝好了就可以用了

mysqldumpshow -s t -t 10 slow.log
mysqldumpslow -s c -t 20 slow.log
mysqldumpslow -s r -t 20 slow.log
主要功能是, 統計不同慢sql的
出現次數(Count), 
執行最長時間(Time), 
累計總耗費時間(Time), 
等待鎖的時間(Lock), 
發送給客戶端的行總數(Rows), 
掃描的行總數(Rows), 

通過以上命令我們定位到想要優化的sql ,再通過explain sql執行計劃看看如何優化索引;explain執行計劃的參數即使用 可以查看我的 這篇博文sql優化;通過執行計劃我們知道自己的sql是否使用了索引,以及索引使用的key-len是否全部覆蓋;下面就要學習下 mysql 索引key-len的算法了

key_length的計算方式

當索引字段爲定長數據類型,比如char,int,datetime,如果有是否爲NULL的標記,這個標記需要佔用1個字節。對於變長數據類型,比如:varchar,除了是否爲NULL的標記外,還需要有長度信息,需要佔用2個字節。(當字段定義爲NOT NULL的時候,是否爲NULL的標記將不佔用字節)。
不同的字符集,latin1編碼一個字符一個字節,gbk編碼的爲一個字符2個字節,utf8編碼的一個字符3個字節。
創建索引的時候可以指定索引的長度,例如:
alter table test add index uri(uri(30));
長度30指的是字符的個數,如果爲utf8編碼varchar(255),key_length=30*3+2=92個字節

還有一個知識就是索引的數據結構了

圖解幾種數據結構:

二叉樹:如果數據是單邊增長的情況 那麼出現的就是和鏈表一樣的數據結構了,樹高度大

 

紅黑樹:在二叉樹的基礎上多了樹平衡,也叫二叉平衡樹,不像二叉樹那樣極端的情況會往一個方向發展。

 

 

同樣我們查找6,在二叉樹中我們需要經過6個節點才能找到(1-2-3-4-5-6),紅黑樹中我們只需要3個節點(2-4-6),但是mysql索引的數據結構並不是紅黑樹,因爲如果數據量大了之後,樹的高度就會很大。

 

B樹:在紅黑樹的基礎上,每個節點可以存放多個數據

這個時候我們查找6 只需要2個節點就可以了,而且樹的高度也比紅黑樹矮。

B+樹:B樹的變種

你會發現非葉子節點是會重複的,就像上面4,在葉子節點上面也出現了4,這是爲什麼呢?因爲它需要在葉子上面存放數據。那又是怎麼存放數據的呢?

 ---------------------------------------------------------------

mysql索引爲什麼用B+樹

首先說一點,mysql索引的數據結構就是用到的B+樹。

 

MyISAM存儲引擎索引文件和數據文件是分離的

 Usertabmyisam表使用的myisam存儲引擎,表相關文件有三個,.frm是存放表結構數據,MYD是表數據。MYI是存放索引,索引樹上會存儲數據在MYD文件裏面的位置。

InnoDB存儲引擎

Usertab使用的Innodb存儲引擎,表相關文件只有兩個同樣.frm文件是存放表結構數據,.ibd存放的數據和索引。

表數據文件本身就是按B+Tree組織的一個索引結構文件,主鍵索引葉節點包含了完整的數據記錄

以InnoDB爲例:

數據是放在主鍵索引上面,也就是說實際上在每個節點上還會存放所有的數據

使用B樹存放數據之後實際是這樣子的,會在每個對應的索引列的值上存放上對應的數據

而B+樹則不同,它只會在葉子節點上面掛載數據,非葉子節點不會存放數據,數據只會存在葉子節點上面,非葉子節點只存放索引列的數據

 

這樣一個節點就可以存放很多個索引列數據,一次IO就可以拿到很多數據,mysql默認的一個節點16K的大小,可以通過show global status like "Innodb_page_size" 看到該值是16384,每次IO讀取16K大小的數據,以索引列是bigInt類型爲例,大小8字節,每一條數據還有一個指向下一層的指針6字節,16384/(8+6)=1170,一個節點就大約可以存1170條數據。

以一個層高爲3的樹爲例,葉子節點存放數據之後大小1KB,那麼這個樹可以存放 1170 *1170 *16 =21,902,400,大約2200萬條數據。所以在這種千萬級的表中通過主鍵索引查找一條數據,最多3次IO就可以找到一條數據。而很多時候樹的根節點基本都是在內存中,所以多數時候只需要2次IO。

葉子節點之間也有雙向指針連接,提高區間範圍性能,範圍查找。

創建索引的時候,可以選擇索引數據類型,一個是btree一個是hash,hash查找當然也快,但是當遇到範圍查找的時候hash就尷尬了,所以根據實際業務需求來看是用btree還是hash。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章