MYSQL-innodb性能優化幾個點

MYSQL-innodb性能優化幾個點

數據庫常用參數

MYSQL數據庫的參數配置一般在my.ini配置(部分參數也可以用set  global 參數名=值 做臨時調整,重啓後失效),配置完後需要重啓數據庫才生效。

 

參數1slow_query_log = 0|1

說明:開關慢查詢日誌。slow_query_log_file=爲存放路徑;long_query_time =記錄超過的時間,默認爲10s

 

參數2join_buffer_size = MB

說明:join buffer存放基於每thread的連接表信息,連接時,只需訪問join buffer,不需要再去有併發機制保護的cache.

 

參數3Sort_Buffer_Size = MB

說明:Sort_Buffer_Size 是一個connection級參數,每個connection第一次需要使用這個buffer的時候,一次性分配設置的內存。Sort_Buffer_Size 並不是越大越好,由於是connection級的參數,過大的設置+高併發可能會耗盡系統內存資源。官網文檔說“On Linux, there are thresholds of 256KB and 2MB where larger values may significantly slow down memory allocation” 

 

參數4: binlog_format = STATEMENT|ROW|MIXED

說明:日誌格式

1)STATEMENT模式(SBR

每一條會修改數據的sql語句會記錄到binlog中。優點是並不需要記錄每一條sql語句和每一行的數據變化,減少了binlog日誌量,節約IO,提高性能。缺點是在某些情況下會導致master-slave中的數據不一致(sleep()函數, last_insert_id(),以及user-defined functions(udf)等會出現問題)

2)ROW模式(RBR

不記錄每條sql語句的上下文信息,僅需記錄哪條數據被修改了,修改成什麼樣了。而且不會出現某些特定情況下的存儲過程、或function、或trigger的調用和觸發無法被正確複製的問題。缺點是會產生大量的日誌,尤其是alter table的時候會讓日誌暴漲。

3)MIXED模式(MBR

以上兩種模式的混合使用,一般的複製使用STATEMENT模式保存binlog,對於STATEMENT模式無法複製的操作使用ROW模式保存binlogMySQL會根據執行的SQL語句選擇日誌保存方式。

 

參數5binlog_cache_size = MB

說明:默認大小是37268即32K.根據事務需要調整大小參數表示在事務中容納二進制日誌sql語句的緩存大小。二進制日誌緩存,是服務器支持事務存儲引擎並且服務器啓用了二進制日誌(-log-bin選項)的前提下爲每個客戶端分配的內存,是每個client都可以分配設置大小的binlog cache空間

 

參數6:Max_binlog_cache_size = MB

說明:默認值是18446744073709547520,這個值很大,夠我們使用的了。此參數和binlog_cache_size相對應,代表binlog所能使用的cache最大使用大小。如果系統中事務過多,而此參數值設置有小,則會報錯。

 

參數7:Max_binlog_size = GB/MB

說明:Max_binlog_size: 1073741824=1G ,binlog的最大值,一般設置爲512M或1G,一般不能超過1G。此參數不能非常嚴格控制binlog的大小,特別是在遇到大事務時,而binlog日誌又到達了尾部,爲了保證事務完整性,不切換日誌,把所有sql都寫到當前日誌。

 

參數8:expire_logs_days = N

說明:設置binlog老化日期有大致三種情況引發日誌切換:binlog大小超過max_binlog_size手動執行flush logs重新啓動時(MySQL將會new一個新文件用於記錄binlog)

 

參數9:innodb_file_per_table = 0|1

說明:參數值爲1,表示對每張表使用單獨的 innoDB 文件

 

參數10:innodb_log_file_size = GB/MB

說明: Innodb 數據表有大量的寫入操作,那麼選擇合適的 innodb_log_file_size 值對提升MySQL性能很重要;值太大了會讓恢復過程變慢.

 

參數11innodb_log_files_in_group = N

說明:該變量控制日誌文件數。默認值爲2。日誌是以順序的方式寫入。

 

參數12:innodb_flush_method =  

說明:設置InnoDB同步IO的方式:Default (fsync);O_SYNC (sync模式打開文件,通常比較慢);O_DIRECT(Linux上使用Direct IO。可以顯著提高速度,特別是在RAID系統上。避免額外的數據複製和double bufferingmysql buffering OS buffering)

 

參數13:transaction_isolation = READ-UNCOMMITTED | READ-COMMITTED |REPEATABLE-READ | SERIALIZABLE

說明:設定事務隔離級別

1)未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的數據

2)提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)

3)可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀

4)串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

 

參數14:character-set-server = utf8|utf8mb4

說明:設定字符集,utf8存3個字節,utf8mb4存4個字節。

 

參數15innodb_buffer_pool_size = Gb/MB

說明:此參數類似於oracle的SGA配置,當主機做爲mysql數據庫服務器時,一般配置爲整機內存的60%~80%。

 

參數16innodb_buffer_pool_instances=N

說明:內存緩衝池實例數,將innodb_buffer_pool_size配置的內存分割成N份,此參數當配置內存大小於1G時才生效,當數據庫有多個會話進行數據庫操作時,用於並行在多個內存塊中處理任務,一般配置值《=服務器CPU的個數。

 

參數17max_connections = xxxx

說明:最大連接數,當數據庫面對高併發時,這個值需要調節爲一個合理的值,才滿足業務的併發要求,避免數據庫拒絕連接。

 

參數18max_user_connections=xxxx

說明:設置單個用戶的連接數。

 

參數19innodb_log_buffer_size =xxxxx

說明:日誌緩衝區大小,一般不用設置太大,能存下1秒鐘操作的數據日誌就行了,mysql默認1秒寫一輪詢寫一次日誌到磁盤。

 

參數20innodb_flush_log_at_trx_commit =

說明:(這個配置很關鍵)一般的實時業務交易配置爲2,取值0,1,2

0:數據操作時,直接寫內存,並不同時寫入磁盤;

2:數據操作時,直接寫內存,並不同時寫入磁盤;

1:就每個事務提交就會要刷新到磁盤後纔算提交完成,這種情況是保證了事務的一致性,但性能會有很大的影響。

02的區別:

0:當mysql掛了之後,可能會損失前一秒的事務信息

2:當mysql掛了之後,如果系統文件系統沒掛,不會有事務丟失。

 

參數21innodb_read_io_threads = xxxx

說明:數據庫讀操作時的線程數,用於併發。

 

參數22innodb_write_io_threads = xxx

說明:數據庫寫操作時的線程數,用於併發。

 

參數23innodb file per table= 1

說明:每一個表是否使用獨立的數據表空間,默認爲OFF(使用共享表空間),一般建議配置爲1InnoDB 默認會將所有的數據庫InnoDB引擎的表數據存儲在一個共享空間中:(ibdata1),這樣就感覺不爽,增刪數據庫的時候,ibdata1文件不會自動收縮,

單個數據庫的備份也將成爲問題。通常只能將數據使用mysqldump 導出,然後再導入解決這個問題。

共享表空間在Insert操作上少有優勢。其它都沒獨立表空間表現好,如果數據庫基本上都插入操作則配置爲0。

 

參數24innodb_stats_on_metadata={ OFF|on}

說明:是否動態收集統計信息,開啓時會影響數據庫的性能(一般關閉,找個時間手動刷新,或定時刷新如果爲關閉時,需要配置數據庫調度任務,定時刷新數據庫的統計信息。

 

參數25innodb_spin_wait_delay=xxxxx

說明:控制CPU的輪詢時間間隔,默認是6,配置過低時,任務調度比較頻繁,會消耗CPU資源。

 

參數26innodb_lock_wait_timeout=xxxx

說明:控制鎖的超時時間,默認爲50,這個值要注意,如果有特殊業務確實要耗時較長時,不能配置太短。

 

 

 

具體的調優參數內容較多,可參考官方文檔,一些比較重要的參數:

back_logback_log值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆棧中。也就是說,如果MySql的連接數據達到max_connections時,新來的請求將會被存在堆棧中,以等待某一連接釋放資源,該堆棧的數量即back_log,如果等待連接的數量超過back_log,將不被授予連接資源。可以從默認的50升至500

 

wait_timeout:數據庫連接閒置時間,閒置連接會佔用內存資源。可以從默認的8小時減到半小時

 

max_user_connection: 最大連接數,默認爲0無上限,最好設一個合理上限

 

thread_concurrency:併發線程數,設爲CPU核數的兩倍

 

skip_name_resolve:禁止對外部連接進行DNS解析,消除DNS解析時間,但需要所有遠程主機用IP訪問

 

key_buffer_size:索引塊的緩存大小,增加會提升索引處理速度,對MyISAM表性能影響最大。對於內存4G左右,可設爲256M384M,通過查詢show status like 'key_read%',保證key_reads / key_read_requests0.1%以下最好

 

innodb_buffer_pool_size:緩存數據塊和索引塊,對InnoDB表性能影響最大。通過查詢show status like 'Innodb_buffer_pool_read%',保證 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests越高越好

 

innodb_additional_mem_pool_sizeInnoDB存儲引擎用來存放數據字典信息以及一些內部數據結構的內存空間大小,當數據庫對象非常多的時候,適當調整該參數的大小以確保所有數據都能存放在內存中提高訪問效率,當過小的時候,MySQL會記錄Warning信息到數據庫的錯誤日誌中,這時就需要該調整這個參數大小

 

innodb_log_buffer_sizeInnoDB存儲引擎的事務日誌所使用的緩衝區,一般來說不建議超過32MB

 

query_cache_size:緩存MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當某個表的數據有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的緩存數據失效。所以,當我們的數據變化非常頻繁的情況下,使用Query Cache可能會得不償失。根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態數據可適當調大.
可以通過命令show status like 'Qcache_%'查看目前系統Query catch使用大小

 

read_buffer_sizeMySql讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySql會爲它分配一段內存緩衝區。如果對錶的順序掃描請求非常頻繁,可以通過增加該變量值以及內存緩衝區大小提高其性能

 

sort_buffer_sizeMySql執行排序使用的緩衝大小。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試增加sort_buffer_size變量的大小

 

read_rnd_buffer_sizeMySql的隨機讀緩衝區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀緩存區。進行排序查詢時,MySql會首先掃描一遍該緩衝,以避免磁盤搜索,提高查詢速度,如果需要排序大量數據,可適當調高該值。但MySql會爲每個客戶連接發放該緩衝空間,所以應儘量適當設置該值,以避免內存開銷過大。

 

record_buffer:每個進行一個順序掃描的線程爲其掃描的每張表分配這個大小的一個緩衝區。如果你做很多順序掃描,可能想要增加該值

 

thread_cache_size:保存當前沒有與連接關聯但是準備爲後面新的連接服務的線程,可以快速響應連接的線程請求而無需創建新的

 

table_cache:類似於thread_cache_size,但用來緩存表文件,對InnoDB效果不大,主要用於MyISAM

 

 

 

執行計劃分析

mysql> EXPLAIN SELECT * FROM smssendbak;

+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+

| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |

+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+

|  1 | SIMPLE      | smssendbak | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   10 |   100.00 | NULL  |

+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+

說明                                                                                    

Table:表名稱

Type:重要的一列,顯示使用了何種連接,從好到差依次爲consteq_refrefrangeindexall,下面詳細說明:

type的描述:

System表只有一行,這是const連接類型的特例;

Const表中一個記錄的最大值能夠匹配這個查詢(索引可以是主鍵或唯一索引)。因爲只有一行,這個值實際就是常數,因爲mysql先讀這個值,再把它當作常數對待

eq_ref從前面的表中,對每一個記錄的聯合都從表中讀取一個記錄。在查詢使用索引爲主鍵或唯一索引的全部時使用;

Ref只有使用了不是主鍵或唯一索引的部分時發生。對於前面表的每一行聯合,全部記錄都將從表中讀出,這個連接類型嚴重依賴索引匹配記錄的多少-越少越好;

Range使用索引返回一個範圍中的行,比如使用><查找時發生;

Index這個連接類型對前面的表中的每一個記錄聯合進行完全掃描(all好,因爲索引一般小於表數據)

All這個連接類型多前面的表中的每一個記錄聯合進行完全掃描,這個比較糟糕,應該儘量避免。

 

possible_keys可以應用在這張表中的索引,如果爲null,則表示沒有可用索引;

Key實際使用的索引,如爲null,表示沒有用到索引;

key_len索引的長度,在不損失精確度的情況下,越短越好;

Ref顯示索引的哪一列被使用了,如果可能的話,是個常數;

Rows返回請求數據的行數;

Extra關於mysql如何解析查詢的額外信息,下面會詳細說明。

  extra行的描述:

    distinctmysql找到了域行聯合匹配的行,就不再搜索了;

    not existsmysql優化了left join,一旦找到了匹配left join的行,就不再搜索了;

    range checked for each-沒找到理想的索引,一次對於從前面表中來的每一個行組合;

    record(index map: #)-檢查使用哪個索引,並用它從表中返回行,這是使用索引最慢的一種;

    using filesort-看到這個就需要優化查詢了,mysql需要額外的步驟來發現如何對返回的行排序。他根據連接類型以及存儲排序鍵值和匹配條件的全部行的行指針來排序全部行.

    using index-列數據是從單使用了索引中的信息而沒有讀取實際行的表返回的,這發生在對錶的全部的請求列都是同一個索引時;

    using temporary-看到這個就需要優化查詢了,mysql需要創建一個臨時表來查詢存儲結果,這通常發生在多不同的列表進行order by時,而不是group by

where used-使用了where從句來限制哪些行將與下一張表匹配或是返回給用戶。如不想返回表中用的全部行,並連接類型是allindex,這就會發生,也可能是查詢有問題。

 

SQL語句優化:注意SQL語句的書寫規則,where條件,order by ,group by ,having , in ,like ,jion on,表順序,聚合函數的使用,子查詢等。

 

索引優化

1是否有無重複索引

2索引字段類型,順序是否合理

3是否有無用索引

4索引利用率

 

表結構優化

1表的字段類型是否合理

2數據是否冗餘

3根據業務規則建立合理的約束

4建表時,儘量使字段值不爲空(not null約束),索引列值儘量離散(不重複)

5不常用的字段列可適當考慮折分表

6數據量較大的表,有存儲時間,IP地址數據時,轉爲int ,bigint

INT類型的時間數據轉換:

UNIX_TIMESTAMP('2015-01-10 12:00:00') int(插入數據時)

FROM_UNIXTIME(時間字段)     取時間字段的值

IP地址數據操作轉換:

INET_ATON  :IP地址轉bigint   inet_aton(192.168.1.1)

INET_NTOA :BIGINTIP地址(inet_ntoa(ip地址字段)

:mysqlint ,varchar處理要簡單,儘量少使用text類型

 

數據庫主機參數優化

網絡:(/etc/security/sysctl.conf)

net.ipv4.tcp_keepalive_time = 1200

說明:表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改爲20分鐘。

net.ipv4.ip_local_port_range = 10000 65000  

說明:表示用於向外連接的端口範圍,一般低位端口不要設置太低,有可能會用到其它程序固定的端口

net.ipv4.tcp_max_syn_backlog = 65535                

說明:表示SYN隊列的長度,默認爲1024,加大隊列長度爲65535,可以容納更多等待連接的網絡連接數。

net.ipv4.tcp_max_tw_buckets = 5000                

說明:示系統同時保持TIME_WAIT的最大數量,如果超過這個數字,TIME_WAIT將立刻被清除並打印警告信息。默 認爲180000,避免被大量的timewait拖死。

net.ipv4.tcp_syncookies = 1

說明:表示開啓SYN Cookies

net.ipv4.tcp_tw_reuse=1                         

說明:表示開啓重用,允許將TIME-WAIT sockets重新用於新的TCP連接

net.ipv4.tcp_recycle=1                        

說明:表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉;

net.ipv4.tcp_fin_timeout=10        

說明:修改系統默認的 TIMEOUT 時間。

limit.conf內核相關參數優化:

詳見:《limits.conf詳解》

vi /etc/security/limits.conf

limits.conf的格式如下: 

<domain> <type> <item> <value>

或:username|@groupname type resource limit

username|@groupname:設置需要被限制的用戶名,組名前面加@和用戶名區別。也可以用通配符*來做所有用戶的限制。

如:


type:有 soft,hard 和 -

soft 指的是當前系統生效的設置值

hard 表明系統中所能設定的最大值

soft 的限制不能比har 限制高

用 - 就表明同時設置了 soft 和 hard 的值。


resource:

core - 限制內核文件的大小

data - 最大數據大小

fsize - 最大文件大小

memlock - 最大鎖定內存地址空間

nofile - 打開文件的最大數目

rss - 最大持久設置大小

stack - 最大棧大小

cpu - 以分鐘爲單位的最多 CPU 時間

noproc - 進程的最大數目

as - 地址空間限制

maxlogins - 此用戶允許登錄的最大數目


要使 limits.conf 文件配置生效,必須要確保 pam_limits.so 文件被加入到啓動文件中。

查看 /etc/pam.d/login 文件中有:

session required /lib/security/pam_limits.so


暫時地:適用於通過 ulimit 命令登錄 shell 會話期間。 

永久地:通過將一個相應的 ulimit 語句添加到由登錄 shell 讀取的文件之一(例如 ~/.profile),即特定於 shell 的用戶資源文件;或者通過編輯 /etc/security/limits.conf。

何謂core文件,當一個程序崩潰時,在進程當前工作目錄的core文件中複製了該進程的存儲圖像。core文件僅僅是一個內存映象(同時加上調試信息),主要是用來調試的。 core文件是個二進制文件,需要用相應的工具來分析程序崩潰時的內存映像。


系統默認core文件的大小爲0,所以沒有創建。可以用ulimit命令查看和修改core文件的大小。

$ulimit -c 0

$ ulimit -c 1000

$ ulimit -c 1000

-c 指定修改core文件的大小,1000指定了core文件大小。也可以對core文件的大小不做限制,如:

# ulimit -c unlimited


如果想讓修改永久生效,則需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。

2.nofile - 打開文件的最大數目

[plain] 

* soft nofile 10000 #軟限制 


* hard nofile 10000 #硬限制 


對於需要做許多套接字連接並使它們處於打開狀態的應用程序而言,最好通過使用 ulimit –n,或者通過設置nofile 參數,爲用戶把文件描述符的數量設置得比默認值高一些


vi /etc/security/limits.conf


用ulimit -n 2048 修改只對當前的shell有效,退出後失效:!!!!!!!!!!!!!!!!!

如A程序已經運行,此時ulimit -n爲1024;之後ulimit -n 2048,這時在運行B程序;退出當前shell用戶,再次進行shell,之後運行C程序;這時只有B程序用的是2048,其它用的都是1024.

數據庫參數調節效果對比

下列參數配置測試結果對比。

innodb_buffer_pool_size = 1024M

innodb_buffer_pool_instances = 4

max_connections = 2000

max_user_connections = 2000

innodb_flush_log_at_trx_commit = 2

innodb_write_io_threads = 16

innodb_read_io_threads = 16

innodb_spin_wait_delay = 10

innodb_lock_wait_timeout = 30

更改前:增查刪操作通過jmeter測試每秒只有80.8筆。

wKioL1iuXObzFggnAAHxe6Uz0HQ092.png-wh_50

 

 

更改後:增查刪操作通過jmeter測試每秒達到1513.1筆。

 wKioL1iuXPLT9YpwAAHQRpduLEg748.png-wh_50

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章