淺談mysql innodb緩存策略

淺談mysql innodb緩存策略:mysql

 

 The InnoDB Buffer Pool

   Innodb 持有一個存儲區域叫作buffer pool是爲了在內存中緩存數據和索引,知道innodb bufferpool怎麼工做,和利用它讀取頻繁訪問的數據,是mysql優化重要的方面。算法

   理想情況下,把bufferpool的大小調整到足夠大,留下足夠的內存空間給其餘該服務器上的進程(使其完好頁便可)。bufferpool越大,innodb 月表現爲內存型數據庫,從硬盤上一次讀取數據,以後併成了從內存中讀取數據。buffer pool甚至緩存那些由於insert,update操做而改變的數據(insert buffer),因此隨機磁盤寫能夠彙集在一塊獲得更好的性能。sql

   innodb 把緩存池做爲鏈式管理,利用LRU(least recently used)算法,當添加新block到pool中時(無空間),innodb 替換(驅逐)一個最近最少使用的block,而後把新的block添加到鏈表的中間,"midpoint insertion strategy"策略把鏈表看出兩條子鏈。數據庫

     1:在鏈表的頭部,是由一些「NEW」(or "young")block 組成的最近剛被訪問的子鏈;緩存

     2:在鏈表的尾部,是由一些'old' block組成的最近沒被訪問(或者最少被訪問的)的子鏈;服務器

 

 該算法使大量查詢 blocks 保持在  new sublist. old sublist 持有最少使用的 blocks;這些blocks將成爲替換或驅逐的候選者。mysql優化

     1:3/8 的buffer pool 的大小分配給old sublist併發

     2: 鏈表的 midpoint (中間插入點) 是new sublist 尾部和 old sublist頭部聚合的地方性能

     3:當 innodb 讀取一個block進 buffer pool時,插入到midpoint(old sublist 的頭部),block被讀取發生在 客戶端操做,eg: sql查詢,或者innodb特性 readahead(預讀);優化

     4:當訪問在old sublist中一個 block時,使其變成'young',把它移動到 buffer pool的頭部(new sublist的頭部),若是該block 被讀取是由於客戶端sql查詢,則第一次訪問當即發生,而且該block變成'young'。若是該block被讀取是由於read ahead,第一次唄訪問不會發生,而且有可能在該Block被替換以前根本不能發生);

     5:隨着數據庫操做,在buffer pool 中的沒被訪問的blocks(年紀大的)被移動到鏈表的尾部.在old sublist中的blocks 比插入在midpoint上的block老,最終,一個Block一段長時間未被使用會到達old sublist的尾部會被替換。

     默認狀況下,被讀取的blocks會當即移動到 NEW sublist 的 head,同時意味着他們待着buffer pool中很長一段時間。當掃表時(eg, mysqldump 操做,或者 沒有where語句的select操做 )可使大量的blocks  push into buffer pool中,而且驅逐大量的older 數據,即便那些所謂剛加入的 new blocks 不會再次被訪問,相同的,read ahead 後臺線程一次載入大量的blocks  ,這些狀況使常常被訪問的blocks push into 到 old sublist中,而後它們成爲被驅逐的候選者。

  一些innodb 系統變量控制着buffer pool的大小和使你調整LRU算法

    1:innodb buffer pool size

       指明Buffer pool的大小,若是你的buffer pool 空間小,而且有充足的空間,使pool大點能夠減少磁盤IO的次數來提升性能;

    2: innodb buffer pool instances : 分紅多個獨立的區域,各個區域相同,來減小在併發內存讀寫操做的競爭;

    3:innodb old blocks pct:默認3/8;

    4:  innodb old blocks time: 指定多長時間以毫秒爲單位(ms),block插入到老子列表必須呆在那裏第一次訪問後多久,才能搬到新的子列表(解決預讀時,緩存污染問題);

 

  檢查查詢緩存是否存在於你的MySQL服務器:

mysql> show variables like 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

監控查詢緩存的性能,使用顯示狀態查看緩存狀態變量:

mysql> show status like 'qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 16768376 |
| Qcache_hits             | 0        |
| Qcache_inserts          | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 227      |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+
8 rows in set (0.00 sec)

  

mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
--Qcache_hits表示sql查詢在緩存中命中的累計次數,是累加值。  
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 0     |  --0次  
+---------------+-------+  
8 rows in set (0.00 sec)  
 
mysql>  select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql>  SHOW STATUS LIKE 'Qcache%';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 1     | --表示sql在緩存中直接獲得結果,不須要再去解析  
+---------------+-------+  
8 rows in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        6 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 3     |    --上面的sql也是是從緩存中直接取到結果  
+---------------+-------+  
1 row in set (0.00 sec)  
 
mysql> insert into animals select 9,'testsds' ; --插入數據後,跟這個表全部相關的sql緩存就會被清空掉  
Query OK, 1 row affected (0.00 sec)  
Records: 1  Duplicates: 0  Warnings: 0  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        7 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 3    |  --仍是等於3,說明上一條sql是沒有直接從緩存中直接獲得的  
+---------------+-------+  
1 row in set (0.00 sec)  
 
mysql> select count(*) from animals;  
+----------+  
| count(*) |  
+----------+  
|        7 |   
+----------+  
1 row in set (0.00 sec)  
 
mysql> SHOW STATUS LIKE 'Qcache_hits';   
+---------------+-------+  
| Variable_name | Value |  
+---------------+-------+  
| Qcache_hits   | 4     |   
+---------------+-------+  
1 row in set (0.00 sec) 
相關文章
相關標籤/搜索