一. 優化方案選擇
1.SQL本身的優化
1.1 從索引開始優化—提升SQL執行效率
1.1.1 B數索引
B數:小的放左邊,大的放右邊
索引建立原則:
A.頻繁更新的字段不適合
B.很少使用的效率
C.索引使用會降低寫操作的效
2. 選擇需要優化的sql ( 階段 )
選擇方法:優先選擇高併發低消耗的SQL:
A.1小時請求1W次,1次10個IO
B.1小時請求10次,1次1W個IO
即:A和B從單位時間產生的IO總數是相同的
針對A 把10個io 減少到7個,則1小時減少3W個IO
針對B 把1W個io減少到7K個,則1小時減少3W個IO
從系統性能上考慮,第一個SQL的優化能極大改善性能,第二個SQL慢一點無非也就是10個連接慢
3. 在索引中完成排序:
4.優化方法
- 使用最小的colum
4.2 Where 語句中的查詢條件不一定越多越好
因爲where語句中只能使用一個索引列
4.3 避免使用複雜的join和子查詢
4.4 把複雜SQL拆分成簡單的小SQL ,在內存中處理數據
5.引擎參數合理配置優化
5.1.緩衝池innodb_buffer_pool_size :
官網:
https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool-resize.html
LRU算法。用於緩存索引的內存和實際的數據的空間,一般是系統內存的50% --70%左右
該參數是在my.ini / my.cnf配置文件中設置,
查詢其大小:show global variables like 'innodb_buffer_pool_size';
如果是加載到緩存中是沒有IO操作的,索引對性能提升很大
緩衝池innodb_buffer_pool_size大小必須是
緩衝塊innodb_buffer_pool_chunk_size *
緩衝實例 innodb_buffer_pool_instances 結果的倍數。
Buffer = N * ( block * instance * num )
如果配置不滿足倍數則緩衝池大小會自動調整爲等於innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances 的倍數。
命令: SET GLOBAL innodb_buffer_pool_size = 3221225472
單位是bit
5.1.2 如何權衡配置innodb_buffer_pool_size大小
當前配置的innodb_buffer_pool_size是否合適,可以通過分析InnoDB緩衝池的性能來驗證。
可以使用以下公式計算InnoDB緩衝池性能:
Performance = innodb_buffer_pool_reads / innodb_buffer_pool_read_requests * 100
innodb_buffer_pool_reads:表示InnoDB緩衝池無法滿足的請求數。需要從磁盤中讀取。
innodb_buffer_pool_read_requests:表示從內存中讀取邏輯的請求數。
例如,在我的服務器上,檢查當前InnoDB緩衝池的性能:
5.1.2.1.緩存使用查詢
A.show status like 'innodb_buffer_pool_read%';
| Variable_name | Value |
+---------------------------------------+-------------+
| Innodb_buffer_pool_read_ahead_rnd | 0 |
| Innodb_buffer_pool_read_ahead | 0 |
| Innodb_buffer_pool_read_ahead_evicted | 0 |
| Innodb_buffer_pool_read_requests | 4029033624 |
| Innodb_buffer_pool_reads | 91661 |
+---------------------------------------+-------------+
5 rows in set (0.00 sec)
5.1.2.2. 命中率
A.Innodb_buffer_pool_reads:表示InnoDB緩衝池無法滿足的請求數,需要從磁盤中讀取。
B.Innodb_buffer_pool_read_requests:表示從內存中邏輯讀取的請求數
命中率= B / ( A + B ) * 100%
如果接近1 說明查詢的命中率很高,可以滿足緩衝池本身的大部分請求。從磁盤完成讀取的百分比非常小。因此無需增加innodb_buffer_pool_size值。
無需增大緩存,反之增加即可。
5.1.3. 什麼時候減小innodb_buffer_pool_size
在專用MySQL服務器上,多餘的innodb_buffer內存不會有問題,但是當使用共享服務器時,可能會有性能影響。因爲空閒內存對其他程序和操作系統很有用。
5.1.3.1.緩衝池的監控
可以使用SHOW ENGINE INNODB STATUS\G命令檢查內存池狀態:
mysql> show engine innodb status\G
Total large memory allocated 26386366464 //爲緩衝池分配的總內存(以字節爲單位)
Dictionary memory allocated 23826297//爲InnoDB數據字典分配的總內存(以字節爲單位
Buffer pool size 1572672
Free buffers 8192//緩衝池空閒列表的頁面總大小
Database pages 1553364 //緩衝池LRU列表的頁面總大小
Old database pages 573246//緩衝池舊LRU子列表的頁面總大小
Modified db pages 36//緩衝池舊LRU子列表的頁面總大小
Pending reads 0//等待讀入緩衝池的緩衝池頁數
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 881819, not young 18198964
0.02 youngs/s, 0.05 non-youngs/s
Pages read 681064, created 2749237, written 3988300
0.02 reads/s, 0.12 creates/s, 11.50 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1553364, unzip_LRU len: 0
I/O sum[5152]:cur[0], unzip sum[0]:cur[0]
Free buffers :表示有多少空閒buffer。如果 此值長時間都較高,則可以考慮減小InnoDB緩衝池大小。
InnoDB buffer pool 命中率:
InnoDB buffer pool 命中率 低於90%,則可以考慮增加innodb_buffer_pool_size
5.2.緩衝池實例 innodb_buffer_pool_instances
5.2.1. 作用
增加緩衝池的數量可以提高數據庫線程訪問的併發量,
- 查看引擎實例數量:SELECT @@innodb_buffer_pool_instances;
5.2.2. 設置原則
A.最大爲64(最大值)。
B.僅當您設置innodb_buffer_pool_size爲1GB或更大的大小時,實例的配置設置纔會生效 。
C.指定的總大小在所有緩衝池之間分配。爲了獲得最佳效率,指定的組合 innodb_buffer_pool_instances 和innodb_buffer_pool_size,使得每個緩衝池實例是至少爲1GB。
官網提供:
https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-buffer-pools.html
5.3. 緩衝塊設置 innodb_buffer_pool_chunk_size
5.3.1.規則
A.如果緩衝池等於(塊 * 實例個數)正整數倍,則引擎不會調整各值,結果取各自設置的原值
Buffer = N * ( 塊 * 實例 )
B.如果緩衝塊 大於緩衝池的大小 則 緩衝塊 = 緩衝池 / 實例數量
規則:見5.1.1
5.4.sync_binlog:控制數據庫的binlog刷到磁盤上
查看值:select @@sync_binlog;
該參數控制着二進制日誌寫入磁盤的過程。
該參數的有效值爲0 、1、N:
0:默認值。事務提交後,將二進制日誌從緩衝寫入磁盤,但是不進行刷新操作(fsync()),此時只是寫入了操作系統緩衝,若操作系統宕機則會丟失部分二進制日誌。
1:事務提交後,將二進制文件寫入磁盤並立即執行刷新操作,相當於是同步寫入磁盤,不經過操作系統的緩存。1是最安全的,但是也是最慢的。
N: 使執行N次寫入後,與硬盤同步
5.5.innodb_flush_log_at_trx_commit
查看值:select @@innodb_flush_log_at_trx_commit;
主要控制了innodb將log buffer中的數據寫入日誌文件並flush磁盤的時間點。來修改事務日誌同步時機:如下
- innodb_flush_log_at_trx_commit=0 //每1秒鐘同步一次事務日誌文件
- innodb_flush_log_at_trx_commit=1// 每個事務完成之後同步一次事務日誌文件
- innodb_flush_log_at_trx_commit=2//事務完成後,寫到事務日誌文件中,等到日誌覆蓋再同步數據
建議:A的性能最差,B不能完全保證數據是寫到數據文件中,C
5.6. innodb_use_native_aio
InnoDB使用Linux上的異步I / O子系統(本機AIO)來執行數據文件頁面的預讀和寫入請求。此行爲由innodb_use_native_aio 配置選項控制,該選項僅適用於Linux系統,默認情況下處於 啓用狀態