1. 程式人生 > 其它 >資料庫與快取

資料庫與快取

資料庫與快取

摘要: 這裡講的快取是資料庫本身的快取,並不是外部快取例如Redis/Memcache等等。 資料庫的資料分為冷資料和熱資料庫,通俗的講冷資料是儲存在磁碟上不經常查詢的資料;而熱資料是頻繁查詢的資料,這部分資料會被快取到記憶體中。

本文節選自《Netkiller Architect 手札》

第 10 章 資料庫與快取

目錄

  • 10.1. 什麼是資料庫快取?
  • 10.2. 為什麼快取資料呢?
  • 10.3. 什麼時候使用資料庫快取
  • 10.4. 涉及快取的地方有哪些
  • 10.5. 誰來控制資料庫快取
  • 10.6. 怎麼控制資料庫快取
    • 10.6.1. SQL_CACHE 快取
    • 10.6.2. 禁止快取 SQL_NO_CACHE
    • 10.6.3. 關閉快取 set session query_cache_type=off

10.1. 什麼是資料庫快取?

這裡講的快取是資料庫本身的快取,並不是外部快取例如Redis/Memcache等等。

資料庫的資料分為冷資料和熱資料庫,通俗的講冷資料是儲存在磁碟上不經常查詢的資料;而熱資料是頻繁查詢的資料,這部分資料會被快取到記憶體中。

10.2. 為什麼快取資料呢?

因為頻繁查詢相同結果集的資料時,每次到磁碟上查詢資料是非常耗時的,所以資料庫將頻繁查詢且返回相同結果集的資料放到記憶體中,可以減少磁碟訪問操作。

10.3. 什麼時候使用資料庫快取

頻繁訪問且返回相同結果集的情況下使用快取。

偶爾查詢一次且間隔時間較長的情況下不要使用快取。

尺寸較大的結果集不建議使用快取,因為資料太大太大,快取不足以儲存,會導致頻繁載入與銷燬,命中率低。

通常資料庫預設情況是開啟快取的,也就是說正常的select查詢,如果符合快取規則就會經過快取。

當一條SQL查詢時如果結果集在記憶體中稱作“命中”

10.4. 涉及快取的地方有哪些

資料庫本身,檢視資料庫快取狀態

資料庫應用程式介面(ODBC、JDBC......)

10.5. 誰來控制資料庫快取

通常DBA只能控制資料庫快取是否開啟,分配多少記憶體給快取使用,過期銷燬時間,以及策略等等.

上面我已經說過,通常資料庫預設都開啟快取,所以更多的時候我們的操作是禁用快取。這就需要開發人員來通過特定的SQL操作來控制資料庫快取。

10.6. 怎麼控制資料庫快取

以 MySQL 為例

mysql> show variables like '%query_cache%'; 
+------------------------------+---------+| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     || query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    || query_cache_size             | 1048576 |
| query_cache_type             | OFF     || query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.04 sec)

編輯 my.cnf 檔案,加入配置項 query_cache_type=1 然後重啟mysql服務

mysql> show variables like '%query_cache%'; 
+------------------------------+---------+| Variable_name                | Value   |
+------------------------------+---------+
| have_query_cache             | YES     || query_cache_limit            | 1048576 |
| query_cache_min_res_unit     | 4096    || query_cache_size             | 1048576 |
| query_cache_type             | ON      || query_cache_wlock_invalidate | OFF     |
+------------------------------+---------+
6 rows in set (0.00 sec)

query_cache_type | ON 表示快取已經開啟。

10.6.1. SQL_CACHE 快取

預設情況 select 查詢操作只要符合資料庫快取規則那麼結果集就會被快取,如果你的資料庫沒有開啟快取,請參考下面

set session query_cache_type=on;flush tables;show status like 'qcache_q%';select sql_cache * from member where id=1;show status like 'qcache_q%';select sql_cache * from member where id=1;show status like 'qcache_q%';

例 10.1. 演示 SQL_CACHE

mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

mysql> select sql_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 1     |+-------------------------+-------+1 row in set (0.01 sec)

mysql> select sql_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 1     |+-------------------------+-------+1 row in set (0.01 sec)

我們可以看到 Qcache_queries_in_cache 值由0轉為1表示快取已經生效。

10.6.2. 禁止快取 SQL_NO_CACHE

這裡我們主要講怎樣禁止快取,使查詢出的結果集不進入快取。

SELECT SQL_NO_CACHE * FROM table where id=xxxx

下面的用法比較安全,切換到其他資料庫也能正常工作

SELECT /*!40001 SQL_NO_CACHE */ * FROM table
set session query_cache_type=on;flush tables;show status like 'qcache_q%';select sql_no_cache * from member where id=1;show status like 'qcache_q%';select sql_no_cache * from member where id=1;show status like 'qcache_q%';

例 10.2. 演示 SQL_NO_CACHE

mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

mysql> select sql_no_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

mysql> select sql_no_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

使用 sql_no_cache 查詢 Qcache_queries_in_cache 值始終是 0

10.6.3. 關閉快取 set session query_cache_type=off

我們使用 set session query_cache_type=off 可以關閉本次查詢快取。

set session query_cache_type=off;flush tables;show status like 'qcache_q%';select sql_cache * from member where id=1;show status like 'qcache_q%';select sql_cache * from member where id=1;show status like 'qcache_q%';

例 10.3. 演示 query_cache_type=off 關閉查詢快取

mysql> set session query_cache_type=off;
Query OK, 0 rows affected (0.00 sec)

mysql> 
mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

mysql> select sql_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)

mysql> select sql_cache * from member where id=1;
+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+| id | age | ctime               | ip_address | mobile | mtime | name | picture | sex  | status | wechat |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+|  1 |   1 | 2017-08-24 17:05:43 | 1          | NULL   | NULL  | 1    | 1       | 1    | Enable | NULL   |+----+-----+---------------------+------------+--------+-------+------+---------+------+--------+--------+1 row in set (0.00 sec)

mysql> show status like 'qcache_q%';
+-------------------------+-------+| Variable_name           | Value |
+-------------------------+-------+
| Qcache_queries_in_cache | 0     |+-------------------------+-------+1 row in set (0.00 sec)