什麼影響了MySQL效能
影響效能的幾個因素
- 伺服器硬體(CPU、記憶體、磁碟I/O等)
- 伺服器系統
- 資料庫儲存引擎的選擇
- 資料庫引數的配置
- 資料庫結構設計和SQL語句
伺服器硬體
CPU
- 64位的CPU一定要工作在64位的系統下
- 對於併發比較高的 場景,CPU的數量比頻率重要
- 對於密集型場景和複雜SQL,則CPU頻率越高越好
記憶體
- 選擇主機板所能使用的最高頻率的記憶體
- 記憶體的大小對於效能很重要,所以儘可能的大
I/O子系統
- PCIe -> SSD ->Raid10 ->磁碟 ->SAN
伺服器系統
優先選擇Linux
CentOS系統引數優化
sysctl.conf 優化
編輯核心相關引數
vim /etc/sysctl.conf
- 1
- 2
調整配置檔案內容
// etc/sysctl.conf
//以下引數根據需求調整
net.core.somaxconn = 65535 //每個埠最大的監聽佇列長度
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
//調整tcp連線緩衝區的預設值和最大值
net.core.wmem_default = 87380
net.core.rmem_default = 87380
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
//用於減少失效tcp連線佔用的資源,加快資源回收的效率
net.ipv4.tcp_keepalive_time = 120
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
//Linux核心中最重要的引數之一,用於定義單個共享記憶體段的最大值
//注意:
//1、這個引數應該設定為足夠大,以便能在一個共享記憶體段下容納下整個Innodb緩衝池的大小
//2、這個值的大小對於64位Linux系統,可取的最大值為實體記憶體值減 -1 byte,建議值為大於實體記憶體的一半,一般取值大於Innodb緩衝池的大小即可,可以取實體記憶體減 -1 byte
kernel.shmmax = 4294967295
//這個引數當記憶體不足時,會對效能產生比較明顯的影響
//設定為0表示:告訴Linux核心除非虛擬記憶體完全佔滿了,否則不要使用交換分割槽swap
vm.swappiness = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
limit.conf引數優化
增加資源限制(/etc/security/limits.conf
),這個檔案實際上是Linux PAM,也就是插入式認證模組的配置檔案。開啟檔案數的限制
vim /etc/security/limits.conf
- 1
#加到/etc/security/limits.conf 檔案末尾
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
- 1
- 2
- 3
- 4
- 5
磁碟排程策略
檢視當前使用的排程策略
NOOP排程策略
Deadline排程策略
這種策略適用於資料庫
anticipatory排程策略
修改排程策略
如下為將排程策略修改為deadline策略
#操作日誌
#檢視當前系統的磁碟
[root@fu020 block]# df -l
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda1 20641404 10335756 9257124 53% /
tmpfs 4029028 0 4029028 0% /dev/shm
/dev/xvdb1 103210940 81019216 16948916 83% /hotdata
#檢視當前排程策略
[root@fu020 block]# cat /sys/block/xvdb/queue/scheduler
noop anticipatory deadline [cfq]
[root@fu020 block]# cat /sys/block/xvda/queue/scheduler
noop anticipatory deadline [cfq]
#修改當前排程策略
[root@fu020 block]# echo deadline > /sys/block/xvdb/queue/scheduler
[root@fu020 block]# echo deadline > /sys/block/xvda/queue/scheduler
[root@fu020 block]# cat /sys/block/xvda/queue/scheduler
noop anticipatory [deadline] cfq
[root@fu020 block]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
檔案系統對效能的影響
windows下有:
- FAT
- NTFS
Linux下有:
- EXT3
- EXT4
- XFS(最好,centos7已經預設採用)
EXT3/4需要注意的地方
資料庫儲存引擎的選擇
MyIsam
mysql5.5版本之前的預設儲存引擎
1、Myisam儲存引擎由MYD(資料)和 MYI(索引檔案)組成,frm檔案儲存表結構(所以儲存引擎都有)
myisam的特性:
- 併發性和鎖級別 (對於讀寫混合的操作不好,為表級鎖,寫入和讀互斥)
- 表損壞修復
- myisam表支援的索引型別(全文索引…)
- myisam支援表壓縮(壓縮後,此表為只讀,不可以寫入。使用myisampack壓縮)
check table tablename
repair table tablename
#修復myisam表還有一個命令,myisamchk ,在命令列使用這個命令,需要將資料庫停止,否則可能會造成更大的表損害
- 1
- 2
- 3
myisam的限制:
myisam適用場景:
- 非事務性應用
- 只讀類應用
- 空間類應用(唯一支援空間函式的引擎)
Innodb
Mysql5.5及之後版本的預設儲存引擎
- Innodb使用表空間進行資料儲存
當引數 innodb_file_per_table
為ON時,採用獨立表空間:tablename.id
,
為OFF時,採用系統表空間:ibdataX
,生成一個ibdata1的檔案
mysql> SHOW VARIABLES LIKE 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | OFF |
+-----------------------+-------+
1 row in set (0.00 sec)
mysql>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 獨立表空間和系統表空間應該如何抉擇呢?
兩者比較:
- 系統表空間無法簡單的收縮大小(這很恐怖,會導致ibdata1一直增大,即使刪除了資料也不會變小)
- 獨立表空間,可以通過optimize table 命令收縮系統檔案
- 系統表空間會產生I/O瓶頸(因為只有一個檔案)
- 獨立表空間可以向多個檔案重新整理資料
總結
強烈建議:對Innodb引擎使用獨立表空間(mysql5.6版本以後預設是獨立表空間)
系統錶轉移為獨立表的步驟(非常繁瑣):
- 使用mysqldump匯出所有資料庫表資料
- 停止mysql服務,修改引數,並且刪除Innodb相關檔案
- 重啟mysql服務,重建mysql系統表空間
- 重新匯入資料
Innodb儲存引擎特性
- Innodb為事務性儲存引擎
- 完全支援事物的ACID特性
- Redo log (實現事務的永續性) 和Undo log(為了實現事務的原子性,儲存未完成事務log,用於回滾)
- Innodb支援行級鎖
- 行級鎖可以最大程度的支援併發
- 行級鎖是由儲存引擎層實現的
什麼是鎖
- 鎖的主要作用是管理共享資源的併發訪問
- 鎖用於實現事務的隔離性
鎖的型別
- 共享鎖(也稱為讀鎖)
- 獨佔鎖(也成為為寫鎖,排他的)
- 讀鎖和讀鎖是相容的
鎖的粒度
- 表級鎖
- 行級鎖
阻塞和死鎖
什麼是阻塞
什麼是死鎖
Innodb狀態檢查
mysql> SHOW ENGINE INNODB STATUS;
- 1
- 2
使用場景
Innodb適合於大多數OLTP(線上處理)0應用
MySQL常用儲存引擎之CSV
檔案系統儲存特點
- 資料以文字方式儲存在檔案中
- .csv檔案儲存表內容
- .csm檔案儲存表的元資料,如表狀態和資料量
- .frm儲存表的結構
CSV儲存引擎特點
- 以CSV格式進行資料儲存
- 所有列 必須都是不能為NULL
- 不支援索引
- 可以對資料檔案直接編輯(其他引擎是二進位制儲存,不可編輯)
CSV適用場景
MySQL常用儲存引擎之Archive
Archive儲存引擎特點
- 以zlib對錶資料進行壓縮,磁碟I/O更少
- 資料儲存在ARZ為字尾的檔案中(表文件為a.arz,a.frm)
- 只支援insert 和 select 操作(不可以delete 和update,會提示沒有這個功能)
- 只允許在自增ID列上加索引
Archive適用場景
日誌和資料採集類應用
MySQL常用儲存引擎之Memory
Memory儲存引擎特點
也稱為HEAP儲存引擎,所以資料儲存在記憶體中(資料庫重啟後會導致資料丟失)
- 支援HASH索引(等值查詢應選擇HASH)和BTree索引(範圍查詢應選擇)
- 所有欄位都為固定長度,varchar(10) == char(10)
- 不支援BLOG和TEXT等大欄位
- Memory儲存使用表級鎖(效能可能不如innodb)
5.最大大小由max_heap_table_size
引數決定 - Memory儲存引擎預設表大小隻有16M,可以通過調整
max_heap_table_size
引數
Memory儲存引擎與臨時表
Memory儲存引擎和臨時表是不同概念
Memory適用場景
MySQL常用儲存引擎之Federated
Federated儲存引擎特點
- 提供了訪問遠端mysql伺服器上表的方法
- 本地不儲存資料,資料全部放在遠端伺服器上
使用 Federated
預設是禁止的。如果需要啟用,需要在啟動時增加Federated引數
如何選擇儲存引擎
參考條件:
- 是否需要事務
- 是否可以熱備份
- 崩潰恢復
- 儲存引擎的特有特性
重要一點:不要混合使用儲存引擎
強烈推薦: Innodb
MySQL伺服器引數介紹
Mysql獲取配置資訊
- 命令列引數,比如
mysql_safe --datadir = /data/sql_data
(不推薦在命令列指定) - 配置檔案,檢視配置檔案的
//檢視 MySQL 配置檔案載入順序
mysqld --verbose --help | grep -A 1 'Default options'
//載入順序
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf
- 1
- 2
- 3
- 4
- 5
Mysql配置引數的作用域
- 全域性引數
//下面兩種設定全域性引數的方式是等價的
set global 引數名 = 引數值
set @@global.引數名 := 引數值
- 1
- 2
- 3
- 4
- 會話引數
//下面兩種設定會話引數的方式是等價的
set [session] 引數名 = 引數值 ;
set @@session.引數名 := 引數值 ;
- 1
- 2
- 3
- 4
為Mysql配置記憶體相關引數
- 確定可以使用的記憶體上限(這裡要注意了,32位系統最多隻能使用4G記憶體,所以我們要選擇64位作業系統)
- 確定Mysql上的每個連線使用的記憶體
//以下引數都是為單個連線配置的
sort_buffer_size //排序緩衝區的記憶體,這個值不能過大,
join_buffer_size //連線緩衝區的記憶體,關聯多張表 ,這個值也不能太大
read_buffer_size //
read_rnd_buffer_size
- 1
- 2
- 3
- 4
- 5
3.確定需要為作業系統保留多少記憶體 (資料庫伺服器應該單獨配置,不合程式檔案放在一個伺服器)
4. 如何為快取池分配記憶體
#不僅要快取索引而且要快取資料,Innodb嚴重依賴快取池,應該分配足夠多的記憶體給這個引數
#分配值參考公式:總記憶體 - (每個執行緒所需要的記憶體 * 連線數)- 系統保留記憶體
innodb_buffer_pool_size
#key_buffer_size對MyISAM表效能影響很大.如果全是Innodb表,則不需要分配太大,夠系統表用即可
#查詢myisam表索引佔用的空間大小:
# select sum(index_length) from information_schema.tables where engine = 'myisam'
key_buffer_size
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
為Mysql配置IO相關引數
Innodb I/o相關配置
innodb_log_file_size #控制單個事務日誌大小
innodb_log_file_in_group #控制事務檔案個數(這個引數可以不用管它,不是越多越好)
#事務日誌總大小
# innodb_log_file_in_group * innodb_log_file_size
innodb_log_buffer_size #事務日誌的緩衝區大小
#0:表示每秒進行一次log寫入cache,並flush log 到磁碟(不安全)
#1【預設】:在每次事務提交執行log寫入cache,並flush log到磁碟(效率最低,最安全)
#2【建議】:每次事務提交,執行log資料寫入到cache,每秒執行一次flush log 到磁碟
innodb_flush_log_at_trx_commit = 2
#innodb重新整理的方式,影響innodb讀取資料的方式
innodb_flush_method = O_DIRECT #O_DIRECT 為Linux的最好選擇
#控制innodb如何使用表空間,為1表示為每個表建立單獨的表空間,為0表示使用系統表空間,強烈建議設定為1
innodb_file_per_table = 1
innodb_doublewrite = 1 #使用雙寫快取,建議啟用,為了安全
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
Myisam I/o相關配置
delay_key_write
#OFF : 每次寫操作後重新整理鍵緩衝中的髒塊到磁碟
#ON :只對建表時指定了delay_key_write選項的表使用延遲重新整理
#ALL :對所有Myisam表都使用延遲鍵寫入
- 1
- 2
- 3
- 4
Mysql安全相關配置引數
expire_logs_days = 7 #指定自動清理binlog的天數,建議設定為7天
max_allowed_packet = 32M #控制mysql可以接收包的大小,建議32M,主從都需配置一樣大小
skip-name-resolve #禁用DNS查詢,建議啟用
#以下主要針對從庫中配置
sysdate_is_now #確保sysdate返回確定性日期
read_only #禁止非super 許可權的使用者寫入
skip_slave_start #禁用slave自動恢復(不安全的崩潰,自動恢復可能是不安全的)
#設定mysql使用的SQL模式
#sql_mode
strict_trans_tables
no_engine_subtitution
no_zero_date
no_zero_in_date
only_full_group_by
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
其它常用配置引數
sync_binlog #控制Mysql如何向磁碟重新整理binlog
tmp_table_size 和 max_heap_table_size #控制記憶體臨時表的大小
max_connections #控制允許的最大連線數
- 1
- 2
- 3
資料庫設計對效能的影響
- 過分的反正規化化為表建立太多的列
- 過分的正規化化造成太多的表關聯
- 在OLTP環境中使用不恰當的分割槽表
- 使用外來鍵保證資料的完整性(儘量不使用外來鍵約束)
總結
效能優化順序
- 首先優化資料庫結構設計和SQL語句
- 選擇合理的儲存引擎和引數配置(不要混合使用儲存引擎)
- 系統選擇和優化
- 硬體升級
參考連結: