十七、MySQL 優化
阿新 • • 發佈:2020-12-17
一、資料硬體優化(選型)
1.資料庫選擇
1.真實的硬體物理機,虛擬化,搭建資料庫
2.雲伺服器ECS,自己搭建資料庫
3.雲資料庫(RDS,DRDS)
2.資料庫型別
1.OLTP 線上事務處理系統,支援大量的併發使用者修改資料
2.OLAP 資料倉庫,資料展示,資料的分析(非關係型資料庫)
3.硬體選擇
1)CPU選型
1.IO密集型:線上,OLTP主要就是IO密集型,支援高併發,E系列
2.CPU密集型:I系列,資料分析處理,CPU計算能力很高
2)記憶體
1.記憶體不是越大越好,記憶體越大,使用一定越多,浪費越多,命中率反而降低
2.一般記憶體是CPU核心數量的2-3倍
4核 12G記憶體
8核 24G記憶體
3)磁碟選擇
1.SATA盤
2.SSD盤
3.SAS盤
4)儲存選擇
1.本地SSD盤
2.雲盤
5)網路選擇
1.硬體伺服器,網絡卡最好買單卡單口
2.網絡卡繫結
4.作業系統的優化
1)作業系統優化
[root@db03 ~]# cat /etc/sysctl.conf
net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
net.ipv4.ip_forward = 1
2)swap空間利用調整
#swap空間的利用率,值越大,越可能使用swap空間
[root@db03 ~]# cat /proc/sys/vm/swappiness
30
#配置成最小值(臨時設定)
[root@db03 ~]# echo 0 > /proc/sys/vm/swappiness
[root@db03 ~]# cat /proc/sys/vm/swappiness
0
#永久設定
[root@db03 ~]# cat /etc/sysctl.conf
vm.swappiness = 0
3)IO排程策略
#排程策略檔案
[root@db03 ~]# cat /sys/block/sda/queue/scheduler
noop deadline [cfq]
#修改排程策略
[root@db03 ~]# echo deadline > /sys/block/sda/queue/scheduler
[root@db03 ~]# cat /sys/block/sda/queue/scheduler
noop [deadline] cfq
二、資料庫資料查詢
1.建立資料庫資料
#建立資料庫
mysql> create database devtest;
Query OK, 1 row affected (0.00 sec)
#建立表
mysql> create table test(id int(11),num int(11),k1 char(2),k2 char(4),dt timestamp not null);
Query OK, 0 rows affected (0.00 sec)
#插入100萬的資料
delimiter //
create procedure rand_data(in num int)
begin
declare str char(62) default 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
declare str2 char(2);
declare str4 char(4);
declare i int default 0;
while i<num do
set str2=concat(substring(str,1+floor(rand()*61),1),substring(str,1+floor(rand()*61),1));
set str4=concat(substring(str,1+floor(rand()*61),2),substring(str,1+floor(rand()*61),2));
set i=i+1;
insert into test values(i,floor(rand()*num),str2,str4,now());
end while;
end;
//
mysql> \d ;
mysql> call rand_data(1000000);
2.檢視資料可用性
#檢視資料量
mysql> select count(*) from test;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.24 sec)
#檢視資料內容
mysql> select * from test limit 10;
+------+--------+------+------+---------------------+
| id | num | k1 | k2 | dt |
+------+--------+------+------+---------------------+
| 1 | 862115 | xl | UVno | 2020-11-12 18:00:21 |
| 2 | 557819 | MI | 4512 | 2020-11-12 18:00:21 |
| 3 | 290215 | nA | HIxy | 2020-11-12 18:00:21 |
| 4 | 517425 | sM | qrCD | 2020-11-12 18:00:21 |
| 5 | 680528 | lv | noef | 2020-11-12 18:00:21 |
| 6 | 44996 | l3 | 23ST | 2020-11-12 18:00:21 |
| 7 | 1334 | a6 | MNxy | 2020-11-12 18:00:21 |
| 8 | 33982 | 1r | YZst | 2020-11-12 18:00:21 |
| 9 | 799722 | pl | klpq | 2020-11-12 18:00:21 |
| 10 | 333293 | nR | 45zA | 2020-11-12 18:00:21 |
+------+--------+------+------+---------------------+
10 rows in set (0.01 sec)
3.壓力測試
mysqlslap --defaults-file=/etc/my.cnf \
--concurrency=100 --iterations=1 --create-schema='devtest' \
--query="select * from devtest.test where num='698623'" engine=innodb \
--number-of-queries=20000 -uroot -p123 -verbose
三、資料庫優化引數
1.最大連線數 max_connections
1.簡介
MySQL的最大連線數,增加該值增加mysqld 要求的檔案描述符的數量。如果伺服器的併發連線請求量比較大,建議調高此值,以增加並行連線數量,當然這建立在機器能支撐的情況下,因為如果連線數越多,介於MySQL會為每個連線提供連線緩衝區,就會開銷越多的記憶體,所以要適當調整該值,不能盲目提高設值。
2.檢視方式
#檢視最大連線數
mysql> show variables like 'max_connection';
#檢視已經使用的連線數
mysql> show status like 'max_used_connections';
3.一般配置
max_connections=1024
4.如何判斷該配置多少
1)先給一個比較大的值
2)業務高峰期,檢視已經使用的數量
3)如果max_used_connections遠遠小於max_connection則降低配置
2.連線佇列 back_log
1.簡介
back_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆疊中。也就是說,如果MySql的連線數達到max_connections時,新來的請求將會被存在堆疊中,以等待某一連線釋放資源,該堆疊的數量即back_log,如果等待連線的數量超過back_log,將不被授予連線資源
2.檢視方式
mysql> show variables like 'back_log';
mysql> select @@back_log;
3.如何配置
back_log=1024
3.超時時間 wait_timeout和interactive_timeout
1.簡介
wait_timeout和interactive_timeout都是指不活躍的連線超時時間,連線執行緒啟動的時候wait_timeout會根據是互動模式還是非互動模式被設定為這兩個值中的一個。如果我們執行mysql -uroot -p命令登陸到mysql,wait_timeout就會被設定為interactive_timeout的值。如果我們在wait_timeout時間內沒有進行任何操作,那麼再次操作的時候就會提示超時,這是mysql client會重新連線。
如果時間太長,show processlist得到的連線結果會很多,會造成資源的浪費
2.檢視方式
mysql> select @@wait_timeout;
mysql> show variables like 'wait_timeout';
mysql> show variables like 'interactive_timeout';
3.一般配置
wait_timeout=60
interactive_timeout=7200
4.索引緩衝區 key_buffer_size
1.簡介
key_buffer_size是對MyISAM表效能影響最大的一個引數,這個引數影響的是索引的讀取速度
2.檢視方式(預設是8M)
mysql> show variables like 'key_buffer_size';
#檢視有多少索引走緩衝器
mysql> show status like '%key_read%';
3.一般設定
key_buffer_size=16M
5.查詢緩衝區 query_cache_size
1.簡介
MySQL的該功能是沒有啟動的,可能你通過show variables like '%query_cache%',會發現其變數have_query_cache的值是yes,MYSQL初學者很容易以為這個引數為YES就代表開啟了查詢快取,實際上是不對的,該引數表示當前版本的MYSQL是否支援Query Cache,實際上是否開啟查詢快取是看另外一個引數的值:query_cache_size ,該值為0,表示禁用query cache,而預設配置正是配置為0。
2.檢視方式
#檢視快取查詢是否開啟
mysql> show variables like '%query_cache%';
#測試能否快取查詢
mysql> show status like '%Qcache%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Qcache_free_blocks | 1 | #快取中目前剩餘的blocks數量(如果值較大,則查詢快取中的記憶體碎片過多)
| Qcache_free_memory | 1031352 | #空閒快取的記憶體大小
| Qcache_hits | 0 | #命中快取次數
| Qcache_inserts | 0 | #未命中然後插入次數
| Qcache_lowmem_prunes | 0 | #查詢因為記憶體不足而被移除出查詢快取記錄
| Qcache_not_cached | 47199 | #沒有被快取的查詢數量
| Qcache_queries_in_cache | 0 | #當前快取中快取的查詢數量
| Qcache_total_blocks | 1 | #當前快取的block數量
+-------------------------+---------+
3.一般配置
query_cache_size=64M
query_cache_type=1 #開啟查詢快取
query_cache_limit=50M #快取的限制大小
6.錯誤連線最大次數 max_connect_errors
1.簡介
max_connect_errors是MySQL的安全引數,阻止暴力破解資料庫密碼,超過設定的錯誤次數,鎖定該使用者或主機
2.檢視方式
mysql> show variables like '%connect_errors%';
3.一般配置
max_connect_errors=20
7.sort_buffer_size
1.簡介
資料需要進行排序時,查詢結果的緩衝區
order by,group by,distinct
2.檢視方式
mysql> show variables like '%sort_buffer_size%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| innodb_sort_buffer_size | 1048576 |
| myisam_sort_buffer_size | 8388608 |
| sort_buffer_size | 262144 |
+-------------------------+---------+
3.一般設定
sort_buffer_size=2M
8.資料包限制 max_allowed_packet
1.簡介
指代mysql伺服器端和客戶端在一次傳送資料包的過程當中最大允許的資料包大小
2.檢視方式
mysql> show variables like '%max_allowed_packet%';
+--------------------------+------------+
| Variable_name | Value |
+--------------------------+------------+
| max_allowed_packet | 4194304 |
| slave_max_allowed_packet | 1073741824 |
+--------------------------+------------+
3.一般配置
max_allowed_packet=32M
9.join_buffer_size
1.簡介
資料需要使用join語句時,查詢結果的緩衝區
2.檢視方式
mysql> show variables like 'join_buffer_size';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| join_buffer_size | 262144 |
+------------------+--------+
3.一般設定
join_buffer_size=2M
10.thread_cache_size
1.簡介
當客戶端斷開之後,伺服器處理此客戶的執行緒將會快取起來以響應下一個客戶而不是銷燬(前提是快取數未達上限)
即可以重新利用儲存在快取中執行緒的數量,當斷開連線時如果快取中還有空間,那麼客戶端的執行緒將被放到快取中,如果執行緒重新被請求,那麼請求將從快取中讀取,如果快取中是空的或者是新的請求,那麼這個執行緒將被重新建立,如果有很多新的執行緒,增加這個值可以改善系統性能。
2.檢視方式
mysql> show variables like 'thread_cache_size';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| thread_cache_size | 9 |
+-------------------+-------+
3.一般設定
thread_cache_size=200
4.配置依據
#檢視試圖連線到mysql的連結數
mysql> show status like '%thread_%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Threads_cached | 9 | #當前執行緒的空閒數
| Threads_connected | 94 | #正在連線的執行緒數
| Threads_created | 107 | #曾經達到過最大的連結執行緒數
| Threads_running | 86 | #活躍執行緒數
+--------------------------+-------+
11.innodb_buffer_pool_size
1.簡介
innodb_buffer_pool_size引數對於innodb儲存引擎的庫設定快取
pool_size快取池的大小,包含索引和資料
2.檢視方式
mysql> show variables like 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
3.配置方式(資料庫伺服器總記憶體的70%-80%)
innodb_buffer_pool_size=800M
12.innodb_flush_log_at_trx_commit
1.簡介
#雙一標準的其中一個(預設是1)
innodb_flush_log_at_trx_commit=1,用於控制redo log buffer中資料寫入磁碟redo log檔案的。
1:1代表在commit命令後會立即把redo log buffer,遞交到作業系統記憶體中,然後由作業系統再立即寫入到磁碟的redo log檔案中
0:0代表每秒執行一次把redo log buffer遞交到作業系統記憶體,作業系統記憶體也每秒往redo log中寫入一次。
2:2代表每次commit後立即把redo log buffer資料遞交到作業系統記憶體,然後作業系統每秒往redo log中寫入一次
#2和0一樣,只不過能好一點,如果只是mysql服務宕機的話,提交到作業系統記憶體的事務還不會丟失。
#雙一表中的另一個
sync_binlog=1 每次事務遞交都立即把二進位制日誌刷寫到磁碟。
#雙一標準都是用來控制mysql記憶體資料刷寫到磁碟的頻率,一個用來控制redo log, 一個用來控制二進位制日誌的
2.檢視方式
mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
3.一般配置
innodb_flush_log_at_trx_commit=1
sync_binlog=1
13.innodb_log_buffer_size
1.簡介
日誌檔案的緩衝區大小
2.檢視方式
mysql> show variables like 'innodb_log_buffer_size';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| innodb_log_buffer_size | 8388608 |
+------------------------+---------+
3.一般設定
innodb_log_buffer_size=32M
14.innodb_log_file_size
1.簡介
磁碟上日誌檔案的大小
[root@db01 ~]# ll /usr/local/mysql/data/ib_logfile*
-rw-rw---- 1 mysql mysql 50331648 11月 12 19:49 /usr/local/mysql/data/ib_logfile0
-rw-rw---- 1 mysql mysql 50331648 11月 12 18:06 /usr/local/mysql/data/ib_logfile1
2.檢視方式
mysql> show variables like 'innodb_log_file_size';
+----------------------+----------+
| Variable_name | Value |
+----------------------+----------+
| innodb_log_file_size | 50331648 |
+----------------------+----------+
3.一般配置
innodb_log_file_size=128M
15.innodb_log_files_in_group
1.簡介
將log檔案分組,迴圈的方式寫入多個檔案,值是多少就有幾個ib_logfile檔案
2.檢視方式
mysql> show variables like 'innodb_log_files_in_group';
+---------------------------+-------+
| Variable_name | Value |
+---------------------------+-------+
| innodb_log_files_in_group | 2 |
+---------------------------+-------+
3.一般設定
innodb_log_files_in_group=3
16.read_buffer_size
1.簡介
mysql讀資料的緩衝區大小
設定以順序掃描的方式掃描表資料的時候使用緩衝區的大小.
每個執行緒進行順序掃描的時候都會產生該buffer ,而且同一個Query中如果有多個表進行全表掃描,會產生多個該buffer
2.檢視方式
mysql> show variables like 'read_buffer_size';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| read_buffer_size | 131072 |
+------------------+--------+
3.一般配置
read_buffer_size=2M
17.read_rnd_buffer_size
1.簡介
read_rnd_buffer_size是很重要的引數,尤其工作在如下場景:
* sort_buffer中存的是行指標而不是要查詢的資料。
* 查詢的欄位中包含Blob/Text欄位。
* sort後有大量的資料行(limit 10並不能幫助你,因為MySQL是通過指標獲取行資料的)
如果你取出很少欄位的資料(小於max_length_for_sort_data),行資料將會全部儲存在sort buffer裡,因此將不需要read_rnd_buffer_size這個引數。
而如果你查詢的欄位資料很長(這些欄位很可能含有Text/Blob欄位),比max_length_for_sort_data還長,read_rnd_buffer_size這個引數將派上用場。
2.檢視方式
mysql> show variables like 'read_rnd_buffer_size';
+----------------------+--------+
| Variable_name | Value |
+----------------------+--------+
| read_rnd_buffer_size | 262144 |
+----------------------+--------+
3.一般配置
read_rnd_buffer_size=2M
18.資料庫優化完整配置
[mysqld]
datadir= /service/mysql/data
basedir= /service/mysql
server_id=1
log_bin=mysql-bin
character-set-server=utf8
binlog_format=row
relay_log_purge=0
log_slave_updates
skip_name_resolve
socket=/tmp/mysql.sock
log-error=mysql.err
max_connections=1024
back_log=128
wait_timeout=60
interactive_timeout=7200
key_buffer_size=16M
query_cache_size=64M
query_cache_type=1
query_cache_limit=50M
max_connect_errors=20
sort_buffer_size=2M
max_allowed_packet=32M
join_buffer_size=2M
thread_cache_size=200
innodb_buffer_pool_size=1024M
innodb_flush_log_at_trx_commit=1
sync_binlog=1
innodb_log_buffer_size=32M
innodb_log_file_size=128M
innodb_log_files_in_group=3
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
read_buffer_size=2M
read_rnd_buffer_size=2M
bulk_insert_buffer_size=8M
[client]
socket=/tmp/mysql.sock
#單位轉換
基本概念
bit(位,又名“位元”):bit的縮寫是b,是計算機中的最小資料單位(屬於二進位制的範疇,其實就是0或者1)
Byte(位元組):Byte的縮寫是B,是計算機檔案大小的基本計算單位。比如一個字元就是1Byte,如果是漢字,則是2Byte。
換算
1B(位元組)= 8b(位)
1 KB = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
四、優化結果
1.沒有優化前
[root@db01 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='devtest' --query="select * from devtest.test where num='698623'" engine=innodb --number-of-queries=20000 -uroot -verbose
Benchmark
Running for engine rbose
Average number of seconds to run all queries: 5456.335 seconds
Minimum number of seconds to run all queries: 5456.335 seconds
Maximum number of seconds to run all queries: 5456.335 seconds
Number of clients running queries: 100
Average number of queries per client: 200
2.優化後結果
#1.第一次查詢
[root@db02 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='devtest' --query="select * from devtest.test where num='698623'" engine=innodb --number-of-queries=20000 -uroot -verbose
Benchmark
Running for engine rbose
Average number of seconds to run all queries: 63.146 seconds
Minimum number of seconds to run all queries: 63.146 seconds
Maximum number of seconds to run all queries: 63.146 seconds
Number of clients running queries: 100
Average number of queries per client: 200
#2.第二次查詢
[root@db02 ~]# mysqlslap --defaults-file=/etc/my.cnf --concurrency=100 --iterations=1 --create-schema='devtest' --query="select * from devtest.test where num='698623'" engine=innodb --number-of-queries=20000 -uroot -verbose
Benchmark
Running for engine rbose
Average number of seconds to run all queries: 0.787 seconds
Minimum number of seconds to run all queries: 0.787 seconds
Maximum number of seconds to run all queries: 0.787 seconds
Number of clients running queries: 100
Average number of queries per client: 200