Mysql數據庫優化總結
說明:本文的環境爲CENTOS 5.5 64 Bit /Mysql 5.1.50
說明:本文的環境爲CENTOS 5.5 64 Bit /Mysql 5.1.50
簡介:使用Mysql有一段時間了,期間做了不少關於Mysql優化、設計、維護的工作,這兩天有時間做一下簡單的總結,方便自己回憶,同時也希望能對大家有點幫助.
I 硬件配置優化
Ø CPU選擇:多核的CPU,主頻高的CPU
Ø 內存:更大的內存
Ø 磁盤選擇:更快的轉速、RAID、陣列卡,
Ø 網絡環境選擇:儘量部署在局域網、SCI、光纜、千兆網、雙網線提供冗餘、0.0.0.0多端口綁定監聽
II 操作系統級優化
Ø 使用64位的操作系統,更好的使用大內存。
Ø 設置noatime
[zhangxy@dowload_server1 ~]$ cat /etc/fstab
LABEL=/ / ext3 defaults,noatime 1 1
/dev/sda5 /data xfs defaults,noatime 1 2
Ø 優化內核參數
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_max_syn_backlog=1024
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.neigh.default.gc_thresh3 = 2048
net.ipv4.neigh.default.gc_thresh2 = 1024
net.ipv4.neigh.default.gc_thresh1 = 256
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.tcp_syncookies = 1
net.core.netdev_max_backlog = 2048
net.core.dev_weight = 64
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_sack = 0
net.ipv4.tcp_fin_timeout = 20
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_max_orphans = 32768
net.core.optmem_max = 20480
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216
net.core.somaxconn = 500
net.ipv4.tcp_orphan_retries = 1
net.ipv4.tcp_max_tw_buckets = 18000
net.ipv4.ip_forward = 0
net.ipv4.conf.default.proxy_arp = 0
net.ipv4.conf.all.rp_filter = 1
kernel.sysrq = 1
net.ipv4.conf.default.send_redirects = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.ip_local_port_range = 5000 65000
kernel.shmmax = 167108864
vm.swappiness=0
Ø 加大文件描述符限制
Vim /etc/security/limits.conf
加上
* soft nofile 65535
* hard nofile 65535
Ø 文件系統選擇 xfs
/dev/sda5 /data xfs defaults,noatime 1 2
III Mysql設計優化
III.1存儲引擎的選擇
III.1存儲引擎的選擇
Ø Myisam:數據庫併發不大,讀多寫少,而且都能很好的用到索引,sql語句比較簡單的應用,TB數據倉庫
Ø Innodb:併發訪問大,寫操作比較多,有外鍵、事務等需求的應用,系統內存較大。
III.2命名規則
Ø 多數開發語言命名規則:比如MyAdress
Ø 多數開源思想命名規則:my_address
Ø 避免隨便命名
III.3字段類型選擇
字段類型的選擇的一般原則:
Ø 根據需求選擇合適的字段類型,在滿足需求的情況下字段類型儘可能小。
Ø 只分配滿足需求的最小字符數,不要太慷慨。
原因:更小的字段類型更小的字符數佔用更少的內存,佔用更少的磁盤空間,佔用更少的磁盤IO,以及佔用更少的帶寬。
III.3.1 整型:
見如下圖:
類型
|
字節
|
最小值
|
最大值
|
(帶符號的/無符號的)
|
(帶符號的/無符號的)
|
||
TINYINT
|
1
|
-128
|
127
|
0
|
255
|
||
SMALLINT
|
2
|
-32768
|
32767
|
0
|
65535
|
||
MEDIUMINT
|
3
|
-8388608
|
8388607
|
0
|
16777215
|
||
INT
|
4
|
-2147483648
|
2147483647
|
0
|
4294967295
|
||
BIGINT
|
8
|
-9223372036854775808
|
9223372036854775807
|
0
|
18446744073709551615
|
根據滿足需求的最小整數爲選擇原則,能用INT的就不要用BIGINT。
用無符號INT存儲IP,而非CHAR(15)。
III.3.2 浮點型:
類型
|
字節
|
精度類型
|
使用場景
|
FLOAT(M,D)
|
4
|
單精度
|
精度要求不高,數值比較小
|
DOUBLE(M,D)(REAL)
|
8
|
雙精度
|
精度要求不高,數值比較大
|
DECIMAL(M,D)(NUMERIC)
|
M+2
|
自定義精度
|
精度要求很高的場景
|
III.3.3 時間類型
類型
|
取值範圍
|
存儲空間
|
零值表示法
|
DATE
|
1000-01-01~9999-12-31
|
3字節
|
0000-00-00
|
TIME
|
-838:59:59~838:59:59
|
3字節
|
00:00:00
|
DATETIME
|
1000-01-01 00:00:00~9999-12-31 23:59:59
|
8字節
|
0000-00-00 00:00:00
|
TIMESTAMP
|
19700101000000~2037年的某個時刻
|
4字節
|
00000000000000
|
YEAR
|
YEAR(4):1901~2155 YEAR(2):1970~2069
|
1字節
|
0000
|
III.3.4 字符類型
類型
|
最大長度
|
佔用存儲空間
|
CHAR[(M)]
|
M字節
|
M字節
|
VARCHAR[(M)]
|
M字節
|
M+1字節
|
TINYBLOD,TINYTEXT
|
2^8-1字節
|
L+1字節
|
BLOB,TEXT
|
2^16-1字節
|
L+2
|
MEDIUMBLOB,MEDIUMTEXT
|
2^24-1字節
|
L+3
|
LONGBLOB,LONGTEXT
|
2^32-1字節
|
L+4
|
ENUM('value1','value2',...)
|
65535個成員
|
1或2字節
|
SET('value1','value2',...)
|
64個成員
|
1,2,3,4或8字節
|
注:L表示可變長度的意思
對於varchar和char的選擇要根據引擎和具體情況的不同來選擇,主要依據如下原則:
1. 如果列數據項的大小一致或者相差不大,則使用char。
2. 如果列數據項的大小差異相當大,則使用varchar。
3. 對於MyISAM表,儘量使用Char,對於那些經常需要修改而容易形成碎片的myisam和isam數據表就更是如此,它的缺點就是佔用磁盤空間。
4. 對於InnoDB表,因爲它的數據行內部存儲格式對固定長度的數據行和可變長度的數據行不加區分(所有數據行共用一個表頭部分,這個標頭部分存放着指向各有關數據列的指針),所以使用char類型不見得會比使用varchar類型好。事實上,因爲char類型通常要比varchar類型佔用更多的空 間,所以從減少空間佔用量和減少磁盤i/o的角度,使用varchar類型反而更有利。
5. 表中只要存在一個varchar類型的字段,那麼所有的char字段都會自動變成varchar類型,因此建議定長和變長的數據分開。
III.4編碼選擇
單字節 latin1
多字節 utf8(漢字佔3個字節,英文字母佔用一個字節)
如果含有中文字符的話最好都統一採用utf8類型,避免亂碼的情況發生。
III.5主鍵選擇原則
注:這裏說的主鍵設計主要是針對INNODB引擎
1. 能唯一的表示行。
2. 顯式的定義一個數值類型自增字段的主鍵,這個字段可以僅用於做主鍵,不做其他用途。
3. MySQL主鍵應該是單列的,以便提高連接和篩選操作的效率。
4. 主鍵字段類型儘可能小,能用SMALLINT就不用INT,能用INT就不用BIGINT。
5. 儘量保證不對主鍵字段進行更新修改,防止主鍵字段發生變化,引發數據存儲碎片,降低IO性能。
6. MySQL主鍵不應包含動態變化的數據,如時間戳、創建時間列、修改時間列等。
7. MySQL主鍵應當有計算機自動生成。
8. 主鍵字段放在數據表的第一順序。
推薦採用數值類型做主鍵並採用auto_increment屬性讓其自動增長。
III.6其他需要注意的地方
Ø NULL OR NOT NULL
儘可能設置每個字段爲NOT NULL,除非有特殊的需求,原因如下:
1. 使用含有NULL列做索引的話會佔用更多的磁盤空間,因爲索引NULL列需要而外的空間來保存。
2. 進行比較的時候,程序會更復雜。
3. 含有NULL的列比較特殊,SQL難優化,如果是一個組合索引,那麼這個NULL 類型的字段會極大影響整個索引的效率。
Ø 索引
索引的缺點:極大地加速了查詢,減少掃描和鎖定的數據行數。
索引的缺點:佔用磁盤空間,減慢了數據更新速度,增加了磁盤IO。
添加索引有如下原則:
1. 選擇唯一性索引。
2. 爲經常需要排序、分組和聯合操作的字段建立索引。
3. 爲常作爲查詢條件的字段建立索引。
4. 限制索引的數據,索引不是越多越好。
5. 儘量使用數據量少的索引,對於大字段可以考慮前綴索引。
6. 刪除不再使用或者很少使用的索引。
7. 結合核心SQL優先考慮覆蓋索引。
8. 忌用字符串做主鍵。
Ø 反範式設計
適當的使用冗餘的反範式設計,以空間換時間有的時候會很高效。
IV Mysql軟件優化
Ø 開啓mysql複製,實現讀寫分離、負載均衡,將讀的負載分攤到多個從服務器上,提高服務器的處理能力。
Ø 使用推薦的GA版本,提升性能
Ø 利用分區新功能進行大數據的數據拆分
V Mysql配置優化
注意:全局參數一經設置,隨服務器啓動預佔用資源。
Ø key_buffer_size參數
mysql索引緩衝,如果是採用myisam的話要重點設置這個參數,根據(key_reads/key_read_requests)判斷
Ø innodb_buffer_pool_size參數
INNODB 數據、索引、日誌緩衝最重要的引擎參數,根據(hit riatos和FILE I/O)判斷
Ø wait_time_out參數
線程連接的超時時間,儘量不要設置很大,推薦10s
Ø max_connections參數
服務器允許的最大連接數,儘量不要設置太大,因爲設置太大的話容易導致內存溢出,需要通過如下公式來確定:
SET @k_bytes = 1024;
SET @m_bytes = @k_bytes * 1024;
SET @g_bytes = @m_bytes * 1024;
SELECT
(
@@key_buffer_size + @@query_cache_size + @@tmp_table_size+
@@innodb_buffer_pool_size + @@innodb_additional_mem_pool_size+
@@innodb_log_buffer_size+
@@max_connections *
( @@read_buffer_size + @@read_rnd_buffer_size + @@sort_buffer_size+
@@join_buffer_size + @@binlog_cache_size + @@thread_stack
) )
/ @g_bytes AS MAX_MEMORY_USED_GB;
Ø thread_concurrency參數
線程併發利用數量,(cpu+disk)*2,根據(os中顯示的請求隊列和tickets)判斷
Ø sort_buffer_size參數
獲得更快的--ORDER BY,GROUP BY,SELECT DISTINCT,UNION DISTINCT
Ø read_rnd_buffer_size參數
當根據鍵進行分類操作時獲得更快的--ORDER BY
Ø join_buffer_size參數
join連接使用全表掃描連接的緩衝大小,根據select_full_join判斷
Ø read_buffer_size參數
全表掃描時爲查詢預留的緩衝大小,根據select_scan判斷
Ø tmp_table_size參數
臨時內存表的設置,如果超過設置就會轉化成磁盤表,根據參數(created_tmp_disk_tables)判斷
Ø innodb_log_file_size參數(默認5M)
記錄INNODB引擎的redo log文件,設置較大的值意味着較長的恢復時間。
Linux系統可以使用O_DIRECT處理數據文件,避免OS級別的cache,O_DIRECT模式提高數據文件和日誌文件的IO提交性能
Ø innodb_flush_log_at_trx_commit(默認1)
1. 0表示每秒進行一次log寫入cache,並flush log到磁盤。
2. 1表示在每次事務提交後執行log寫入cache,並flush log到磁盤。
3. 2表示在每次事務提交後,執行log數據寫入到cache,每秒執行一次flush log到磁盤。
VI Mysql語句級優化
1. 性能查的讀語句,在innodb中統計行數,建議另外弄一張統計表,採用myisam,定期做統計.一般的對統計的數據不會要求太精準的情況下適用。
2. 儘量不要在數據庫中做運算。
3. 避免負向查詢和%前綴模糊查詢。
4. 不在索引列做運算或者使用函數。
5. 不要在生產環境程序中使用select * from 的形式查詢數據。只查詢需要使用的列。
6. 查詢儘可能使用limit減少返回的行數,減少數據傳輸時間和帶寬浪費。
7. where子句儘可能對查詢列使用函數,因爲對查詢列使用函數用不到索引。
8. 避免隱式類型轉換,例如字符型一定要用’’,數字型一定不要使用’’。
9. 所有的SQL關鍵詞用大寫,養成良好的習慣,避免SQL語句重複編譯造成系統資源的浪費。
10. 聯表查詢的時候,記得把小結果集放在前面,遵循小結構及驅動大結果集的原則。
11. 開啓慢查詢,定期用explain優化慢查詢中的SQL語句。