1. 程式人生 > >數據庫 之 Mysql優化的問題

數據庫 之 Mysql優化的問題

pru 事務提交 生成 必須 pla ren ces 判斷 個數字

1 概述

數據庫優化的方法有四個:

索引策略,通過explain來判斷索引的有效性,移除多余索引,保留有效的索引

單機緩存,mysql內鍵的緩存

旁掛緩存,如使用redis或者memcached,由程序自行決定是否將結果進行緩存

修改相關參數,提升mysql服務器的性能

本文主要介紹mysql的單機緩存以及相關參數的介紹

2 單機緩存

mysql的內鍵緩存機制,query cache(查詢緩存),mysql緩存功能是自帶的,但是需要啟用,為了足夠高效命中,mysql在內存中開辟緩存空間,緩存中的數據是kv值,kv值也是緩存提高效率的原因之一。

這裏的問題是要把什麽當做鍵,鍵是hash值,所以需要將查詢結果做hash運算。Mysql的緩存是非預先分配的,可能會造成碎片,降低效率

為了提高緩存命中率,要使得程序員使用同一種分隔來寫語句,如都是用大寫,或者某些關鍵字都是小寫,原因是mysql會將查詢語句做hash運算,大小寫不一樣的話,hash值就不同。如果hash值不同,將不能被命中。通常是把關鍵詞大小。

mysql的查詢緩存是單機的,緩存是放在本地主機上。考慮到緩存命中率,在前端調度的時候,可以基於語句做路由,同一語句調度到同一主機上。但是proxysql沒有這種調度能力,haproxy可以實現七層協議調度,但是mysql不支持七層協議,mysql是列表語句,因此不能通過haproxy來做這種調度

查詢緩存:

緩存:k/v

key:查詢語句的hash值

value:查詢語句的執行結果

如何判斷緩存是否命中:

通過查詢語句的哈希值判斷:哈希值考慮的因素包括

查詢本身、要查詢數據庫、客戶端使用的協議版本、...

SELECT Name FROM students WHERE StuID=3;

Select Name From students where StuID=3;

哪些查詢可能不會被緩存?如下添加不變緩存

1 查詢語句中包含UDF(User-Defined Functions)

2 存儲函數

3 用戶自定義變量

4 臨時表

5 mysql系統表或者是包含列級別權限的查詢

6 有著不確定結果值的函數(now());

7 select 語句,如果已經啟用按需緩存,那麽在select 語句中,[SQL_CACHE | SQL_NO_CACHE]這兩個選項則明確表明該語句需要緩存或者不緩存,如明確使用sql_no_cache則不緩存

查看緩存相關的選項

MariaDB [(none)]> show global variables like '%cache%';

查詢緩存相關的服務器變量介紹:

query_cache_limit:能夠緩存的最大查詢結果;(單語句結果集大小上限)

有著較大結果集的語句,顯式使用SQL_NO_CACHE,以避免先緩存再移出;默認是1M

query_cache_min_res_unit:內存塊的最小分配單位;緩存過小的查詢結果集會浪費內存空間;

較小的值會減少空間浪費,但會導致更頻繁地內存分配及回收操作;

較大值的會帶來空間浪費;

query_cache_size:查詢緩存空間的總共可用的大小;單位是字節,必須是1024的整數倍;0表示沒有啟用 。這個數字建議不要隨便調整,因為每次調整這個值,之前的緩存項都會被刪除,緩存需要重新生成

如設置為64M,命令如下

MariaDB [(none)]> set @@global.query_cache_size=67108864;

query_cache_strip_comments

query_cache_type:緩存功能啟用與否;

ON:啟用;能緩存的數據就緩存,處理以上提到的7類不能緩存的查詢

OFF:禁用;

DEMAND:按需緩存,僅緩存SELECT語句中帶SQL_CACHE的查詢結果;如果確定結果大小比緩存空間大,明確不緩存,即no_cache。

query_cache_wlock_invalidate:如果某表被其它連接鎖定,是否仍然可以從查詢緩存中返回查詢結果;默認為OFF,表示可以;ON則表示不可以;默認是OFF(允許的,雙重否定invalidate OFF所以是啟用的,讀多寫少的環境,緩存基本是有效的)

查看狀態變量:計數器,查詢名字或者插入的次數。

mysql> SHOW GLOBAL STATUS LIKE 'Qcache%';

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

| Variable_name | Value |

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

| Qcache_free_blocks | 1 空閑的塊數 |

| Qcache_free_memory | 16759688 |查詢緩存尚且剩余的空間

| Qcache_hits | 0 表示命中緩存的次數 |

| Qcache_inserts | 0 表示查詢插入的次數 |

| Qcache_lowmem_prunes | 0 這個值很大,說明緩存空間太小 |

| Qcache_not_cached | 0 本來要放入緩存空間但是實際沒有被緩存的數量 |

| Qcache_queries_in_cache | 0 在緩存系統中查詢的個數 |

| Qcache_total_blocks | 1 查詢總的塊數 |

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

評估select緩存命中率公式如下:

Qcache_hits/Com_select

當讀寫操作差不多的時候,建議關閉該功能,但是如果是大量查詢,即讀多寫少的環境中,建議啟用緩存

註意,第一次查詢時生成緩存,接下去的查詢才會命中緩存

查看Com_select的總數

MariaDB [sunny]> show global status like 'Com%select%';

3 修改相關參數

Innodb存儲引擎相關的參數查看命令如下

MariaDB [sunny]> show global variables like 'innodb%';

一般不建議使用默認參數,

優化相關參數,一般以下的參數不使用默認數值運行,而是要根據實際情況調整後才能使用服務,相關參數介紹如下

innodb_buffer_pool_size這個參數的相關解釋如下:

innodb的緩存池的大小,通常用來緩存索引,數據,插入數據時的緩沖區。innodb_buffer_pool_size這個參數一般要根據實際情況調大,不支持動態修改,需要修改配置文件,默認是128M,這個值一般要調大,提高性能的優化,這個是占用內存空間,這個根據服務器是專用或者組合使用的,來確定這個數值調整的大小。

如果innodb引擎為主的主機,建議innodb_buffer_pool_size設置40%~60%的內存空間。

如果msyql是專用主機,內存空間為32G以上,innodb_buffer_pool_size一般建議設置為70--80%的內存空間。這個值對mysql性能提升很有幫助。但是不能設置太大,如剩余的內存空間不夠系統正常運轉,可能會帶來更多的問題,所以這個值要適當設置。

如果數據集本身較小,可以根據數據變化幅度及規劃的在線時長來設定合理的innodb_buffer_pool_size值,如比預估的目標值略大。

5.7版本後innodb_buffer_pool_size可以動態調整,但是,建議將innodb_buffer_pool_size寫入配置文件中,而且建議不要在系統繁忙時調整該值

修改配置如下

[root@node71 ~]#vim /etc/my.cnf.d/server.cnf

[server]

innodb_buffer_pool_size = 512M

然後重啟mysql服務後生效

innodb_buffer_pool_instances:buffer_pool的區段(實例)數量, 表示把內存空間大小切割成幾個空間字段,鎖定的單位會變小,可以提高mysql運行效率,但是數量建議不要太多

innodb_log_files_in_group : 一組的日誌文件數量,至少兩個

innodb_log_file_size:日誌文件大小,不能太大,默認是5M;根據實際情況來調整。建議調大,一般可以設定為50--100M

innodb_flush_logs_at_trx_commit:事務提交刷寫磁盤的設置參數,值為0 1 2

0:log_buffer(內存中)每秒1次同步到log_file中,且同時會進行log file 到data file的同步操作,0最多丟失1s的事務

1:每次提交時,log buffer同步到log file,,同時進行log file 到data file的同步操作,1最多丟失1次事務

2: 每次提交時,log buffer同步到log file,,但是不會同時進行log file 到data file的同步操作,由mysql的線程自行決定什麽時候進行刷新數據。2的性能最高,如果事務的安全性不是很大,建議設置為2

建議:關閉autocommit,而後將此值innodb_flush_logs_at_trx_commit設置為1或2;

innodb_file_per_table:innodb的諸多高級特性都依賴此參數,建議開啟

innodb_file_io_threads:文件讀寫的io線程數,如果CPU核心夠多,建議調大,默認是4。這個值是要根據並發量和CPU核心數適量調整

innodb_open_files:innodb可打開的文件數量上限,按需調整此值

innodb_flush_method:innodb刷寫磁盤的方式

innodb_thread_concurrency:innodb的線程並發數,即內核級可以同時運行的線程數,一般是CPU核心數量*2

skip_name_resolve:忽略主機名稱解析,網絡優化相關,禁止調用外部dns進行名稱解析

max_connections:最大並發連接數

數據庫 之 Mysql優化的問題