超詳細的MySQL數據庫優化知識梳理

1 常見問題

  1. 阻塞
  2. 慢查詢

2 能夠從如下幾個方面入手

  1. 服務器硬件優化
  2. 系統配置優化
  3. 數據庫結構優化
  4. SQL和索引

一般優化3和4mysql

3 慢查詢日誌

show variables like 'slow_query_log';
# 開啓慢查詢日誌
set global slow_query_log=on;
# 查詢慢查詢日誌文件存放的位置
show variables like 'slow_query_log_file';
# 設置慢查詢日誌文件存放的位置
set global slow_query_log_file= '/home/mysql/sql_log/mysql-slow.log'
# 設置是否將沒有使用索引的SQL記錄到慢查詢日誌中
set global log_queries_not_using_indexes=on;
# 設置是否將查詢事件超過0秒的SQL記錄到慢查詢日誌中,通產設置0.01秒
set global long_query_time=0;

4 實操

4.1 默認不開啓慢查詢日誌

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zzScyPu6-1612943078099)(assets/image-20210209231209244.png)]

4.2 慢查詢日誌存儲的位置

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xJN69hS6-1612943078102)(assets/image-20210209231908399.png)] 查詢日誌,這裏我是Docker容器部署MySQL,映射在服務器上/data/mysql目錄下 [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-u53ZHzIs-1612943078103)(assets/image-20210209232254446.png)]linux

4.3 日誌格式

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-F2DwgpOi-1612943078105)(assets/image-20210209232640488.png)] 第一行:執行SQL的主機信息sql

第二行:SQL的執行信息shell

第三行:SQL的執行事件數據庫

第四行:SQL的內容json

5 慢查詢日誌分析工具

5.1 mysqldumpslow(官方工具)

5.1.1 參數解釋

-s 是order的順序
al 平均鎖定時間
ar 平均返回記錄時間
at 平均查詢時間(默認)
c 計數
l 鎖定時間
r 返回記錄
t 查詢時間
-t 是top n的意思,即爲返回前面多少條的數據
-g 後邊能夠寫一個正則匹配模式,大小寫不敏感的

5.1.2 基本使用

# 獲得返回記錄集最多的10個SQL。
mysqldumpslow -s r -t 10 /database/mysql/mysql06_slow.log
# 獲得訪問次數最多的10個SQL
mysqldumpslow -s c -t 10 /database/mysql/mysql06_slow.log
# 獲得按照時間排序的前10條裏面含有左鏈接的查詢語句。
mysqldumpslow -s t -t 10 -g 「left join」 /database/mysql/mysql06_slow.log
# 另外建議在使用這些命令時結合 | 和more 使用 ,不然有可能出現刷屏的狀況。
mysqldumpslow -s r -t 20 /mysqldata/mysql/mysql06-slow.log | more

5.2 pt-query-digest

5.2.1 快速安裝

wget https://www.percona.com/downloads/percona-toolkit/2.2.16/RPM/percona-toolkit-2.2.16-1.noarch.rpm && yum localinstall -y  percona-toolkit-2.2.16-1.noarch.rpm

5.2.2 參數解釋

pt-query-digest [OPTIONS] [FILES] [DSN]
--create-review-table  當使用--review參數把分析結果輸出到表中時,若是沒有表就自動建立。
--create-history-table  當使用--history參數把分析結果輸出到表中時,若是沒有表就自動建立。
--filter  對輸入的慢查詢按指定的字符串進行匹配過濾後再進行分析
--limit    限制輸出結果百分比或數量,默認值是20,即將最慢的20條語句輸出,若是是50%則按總響應時間佔比從大到小排序,輸出到總和達到50%位置截止。
--host  mysql服務器地址
--user  mysql用戶名
--password  mysql用戶密碼
--history 將分析結果保存到表中,分析結果比較詳細,下次再使用--history時,若是存在相同的語句,且查詢所在的時間區間和歷史表中的不一樣,則會記錄到數據表中,能夠經過查詢同一CHECKSUM來比較某類型查詢的歷史變化。
--review 將分析結果保存到表中,這個分析只是對查詢條件進行參數化,一個類型的查詢一條記錄,比較簡單。當下次使用--review時,若是存在相同的語句分析,就不會記錄到數據表中。
--output 分析結果輸出類型,值能夠是report(標準分析報告)、slowlog(Mysql slow log)、json、json-anon,通常使用report,以便於閱讀。
--since 從什麼時間開始分析,值爲字符串,能夠是指定的某個」yyyy-mm-dd [hh:mm:ss]」格式的時間點,也能夠是簡單的一個時間值:s(秒)、h(小時)、m(分鐘)、d(天),如12h就表示從12小時前開始統計。
--until 截止時間,配合—since能夠分析一段時間內的慢查詢。

5.2.3 基本使用

# 輸出到文件
pt-query-digest slow-log > slow_log.report
# 輸出到數據庫 --create-reviewtable 意思是慢查詢日誌輸出到某一張表中
pt-query-digest slow.log -review h=127.0.0.1,D=test,p=root,P=3306,u=root.t=query_review --create-reviewtable --review-history t= hostname_slow

6 SQL優化

6.1 須要優化的SQL特徵

  1. 查詢次數多且每次查詢佔用時間長的SQL
  2. IO大的SQL(SQL中掃描行數越多,IO越大)
  3. 未命中索引的SQL

6.2 使用explain查詢SQL的執行計劃

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-z8x5DQu3-1612943078107)(assets/image-20210210001840269.png)]

6.2.1 解釋說明

table 顯示這一行數據時關於哪張表的
type 這是重要的列,顯示鏈接使用了那種類型。從最好到最差的鏈接類型爲const,eq_reg,ref,range,index,ALL。const常見於主鍵/惟一索引查找,eq_reg常見於主鍵的範圍查找,ref常見於鏈接查詢,range常見於索引的範圍查找,index常見於索引的掃描,ALL常見於表掃描
possible_keys 顯示可能應用在這張表中的索引。若是爲空,沒有可能的索引。
key 實際使用的索引。若是爲NULL,則沒有使用索引。
key_len 使用的索引長度。在不損失精確性的狀況下,長度越短越好
ref 顯示索引的那一列被使用了,若是可的話,是一個常數
rows MySQL認爲必須檢查的用來返回請求數據的行數

6.3 SQL優化

  1. 在常常查詢的字段上適當加索引
  2. 避免子查詢,可優化爲鏈接查詢,注意是否存在一對多關係,可能會出現數據重複

6.4 如何選擇合理的列創建索引

  1. 在where從句,group by 從句,order by 從句,on 從句中出現的列
  2. 索引字段越小越好
  3. 離散度大的列放在聯合索引的前面

例如:緩存

select * from payment where staff_id = 2 and customer_id = 584;

因爲customer_id的離散度更大,因此應該使用index(customer_id,staff_id)安全

6.4.1 如何判斷列的離散程度

select count(distinct customer_id),count(distinct staff_id) from payment

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ra3qpWkz-1612943078108)(assets/image-20210210130622515.png)] 列的惟一值越高,離散程度越大,可選擇性越高。服務器

6.4.2 索引的維護和優化

重複及冗餘索引,重複索引是指相同的列以相同的順序創建的同類型的索引,以下面parmary keyID列上的索引就是重複索引網絡

create table test(id int not null primart key),name vachar(10) not null,title varchar(50) not null,unique(id) ) engine=innodb

使用pt-duplicate-key-checker工具檢查重複及冗餘索引

pt-duplicate-key-checker -uroot -p'' -h 127.0.0.1

7 數據庫及表結構優化

7.1 選擇合適的數據類型

  1. 使用能夠存下你的數據的最小的數據類型
  2. 使用簡單數據類型,int要比varchar類型在MySQL處理上簡單
  3. 儘可的使用not null 定義字段
  4. 儘可能少用text類型,非用不可時最好考慮分表

例如

使用bigint來存儲IP地址,利用INET_ATON(),INET__NTOA()兩個函數進行轉換

insert into sessions(ipaddress) values (INET_ATON('127.0.0.1'));
select INET__NTOA('127.0.0.1') from sessions;

7.2 範式化和反範式化

7.2.1 範式化

  1. 第一範式,強調原子性,要求屬性具備原子性,不可再分解

  2. 第二範式,強調主鍵,要求記錄有惟一標識,即實體的惟一性,級不存在部分依賴

  3. 第三範式,強調外鍵,要求任何字段不能由其餘字段派生出來,要求字段沒有冗餘,即不存在依賴傳遞

7.2.2 反範式化

爲了查詢效率的考慮,把本來符合第三範式的表適當的增長冗餘,以達到優化查詢效率的目的,反範式化是一種以控件來換時間的操做。

7.3 數據庫結構的優化

7.3.1 表的垂直拆分

把原來一個有不少列的表拆分紅多個表,這解決了表的寬度問題,一般垂直拆分能夠按如下原則進行:

  1. 把不經常使用的字段單獨存放在一個表中
  2. 把大字段獨立存在在一個表中
  3. 把常常一塊兒使用的字段放在一塊兒

7.3.2 表的水平拆分

爲了解決單表的數據量大的問題,水平拆分的表每個表的結構都是徹底一致的

8 系統配置優化

數據庫是基於操做系統的,目前大多數MySQL都是安裝在Linux上,因此對於操做系統的一些參數配置也會影響MySQL的性能,下面列出經常使用的系統配置

8.1 網絡配置方面

修改/etc/sysctl.coonf文件

# 增長tcp支持的隊列數
net.ip4.tcp_max_syn_backlog=65535
# 減小斷開鏈接時,資源回收
net.ipv4.tcp_max_tw_buckets=8000
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=10

打開文件數的限制,可使用ulimit -a查看目錄的各位限制,能夠修改/etc/security/limits.conf文件,增長如下內容以修改打開文件數量的限制

soft nofile 65335
hard nofile 65535

除此以外最好在MySQL服務器上關閉iptables,selinux 等防火牆軟件

8.2 MySQL配置文件

8.2.1 配置文件路徑

Linux:/etc/my.cnf

8.2.2 參數

innodb_buffer_pool_size:很是重要的參數,用於配置innodb的緩衝池若是數據庫中只有innodb表,則推薦配置量爲總內存的75%

innodb_buffer_pool_instances:MySQL5.5中新增的參數,能夠控制緩存池的個數,默認狀況下只有一個緩存池

innodb_log_buffer_size:innodb log緩存的大小,因爲日誌最長每秒鐘就會刷新因此通常不用太大

innodb_flush_log_at_trx_commit:關鍵參數,對innodb的IO效率影響最大,默認值爲1,能夠取0,1,2三個值,通常建議設置爲2,但若是數據安全性要求比較高則使用默認值1

innodb_read_io_threads/innodb_write_io_threads:決定innodb讀寫IO的進程數,默認爲4

innodb_file_per_table:關鍵參數,控制innodb沒一個表使用獨立的表空間,默認爲OFF,也就是全部表都會創建在共享表空間中

innodb_stats_on_metadata:決定MySQL在什麼狀況下會刷新innodb表的統計信息

8.2.3 第三方配置工具

Percon Configuration Wizard

9 服務器硬件的優化

9.1 CPU

選擇合適的CPU,單個頻率更快的CPU

  1. MySQL一些工做只能使用到單核
  2. MySQL對CPU的核數支持並非越快越好,MySQL5.5使用的服務器不要超過32核

9.2 disk IO優化

經常使用RAID級別簡介

RAID0:也成爲條帶,就是把多個磁盤鏈接成一個硬盤使用,這個級別IO最好

RAID1:也稱爲鏡像,要求至少有兩個磁盤,每組磁盤存儲的數據相同

RAID5:也是把多個(最少3個)硬盤合併成一個邏輯盤使用,數據讀寫時會創建奇偶校驗信息,而且奇偶校驗信息和相對應的數據分別存儲於不一樣的硬盤上。當RAID5的一個磁盤數據發生損壞後,就剩下的數據和相應的奇偶校驗信息去恢復被損壞的數據。

RAID1+0:就是RAID1和RAID0的結合,同時具有兩個級別的優缺點。通常建議數據庫使用這個級別。

SNA和NAT是否適合數據庫

  1. 經常使用於高可用的解決方案
  2. 順序讀寫效率很高,可是隨機讀寫不如人意
  3. 數據庫隨機讀寫效率很高
相關文章
相關標籤/搜索