【原創】InnoDB 和TokuDB的讀寫分析與比較

renke發表於2021-09-09


我們知道,在MySQL單機版本里面最流行的也是唯一支援全事務的引擎為INNODB。 其特點是資料本身是用B-TREE來組織,資料本身即是龐大的根據主鍵聚簇的B-TREE索引。 所以在這點上,寫入速度就會有些降低,因為要每次寫入要用一次IO來做索引樹的重排。 特別是當資料量本身比記憶體大很多的情況下,CPU本身被磁碟IO糾纏的做不了其他事情了。  這時我們要考慮如何減少對磁碟的IO來排解CPU的處境,那麼如何做呢? (當然,如果資料足夠放到記憶體裡面,這些事情大可不必考慮。)

1. 可以把INNODB 個PAGE增大?(預設16KB)但是增大也就帶來了一些缺陷。 比如,對磁碟進行CHECKPOINT的時間將延後。

2. 把日誌檔案放到更快速的磁碟上?比如SSD?

其實這時,我們可以考慮用另外一個知名的引擎TokuDB。 誰叫MySQL 天生支援隨意可插拔呢!

TokuDB 其實本身資料儲存用到了B-TREE的變形版本Fractal-Tree。 Fractal-Tree 也就是在B-Tree原來的非葉子節點增加了一個快取,無論對這個樹怎麼操作,都是一個模式:即父親節點的快取滿了,就流淌到兒子節點,然後兒子節點的快取滿了後,再次流淌到孫子節點等等一系列最後到了葉子節點,然後等到葉子節點的PAGE足夠大的時候,進行CHECK POINT。當然不管如何做快取,每次事務後,還是得首先重新整理到REDO 日誌,要不資料一致性就很難保證了。

接下來,這裡測試下同樣的環境InnoDB和TokuDB的效能差異。當然,我沒有做壓力測試,只是簡單的手動執行了幾次SQL而已。

(5.6.10-enterprise-commercial-advanced-log MySQL Enterprise Server - Advanced Edition (Commercial))

用來匯入的檔案大概為35M。

1. INNODB.

對應的引數:

 innodb_buffer_pool_size=32M

 bulk_insert_buffer_size=20M

 query_cache_size = 0

匯入效能:(InnoDB在這裡慢在CPU一直忙於IO置換。)

mysql> load data infile '/tmp/t3_push.csv' into table t3_push;

Query OK, 955527 rows affected (30 min 44.03 sec)

Records: 955527  Deleted: 0  Skipped: 0  Warnings: 0

讀效能:(讀的效能還是很好的,這裡用到5.6的ICP以及MRR特性。)

mysql> select count(*) from t3_push where rank1 < 20 and rank2 < 30;       

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

| count(*) |

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

|       49 |

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

1 row in set (0.06 sec)

調大

innodb_buffer_pool=128M

mysql> load data infile '/tmp/t3_push.csv' into table t3_push;

Query OK, 955527 rows affected (38.72 sec)

Records: 955527  Deleted: 0  Skipped: 0  Warnings: 0

調大後,其實匯入效能還是不錯的。

2. TokuDB.

(5.5.30-tokudb-7.1.0-e-log TokuDB Enterprise Server (GPL) )

對應的引數:

 tokudb_cache_size=32M

 tokudb_loader_memory_size=20M

 query_cache_size = 0

寫效能:(這裡IO次數很少,所以匯入速度很快。)

mysql> load data infile '/tmp/t3_push.csv' into table t3_push;

Query OK, 955527 rows affected (19.73 sec)

Records: 955527  Deleted: 0  Skipped: 0  Warnings: 0

讀效能:(讀的速度比INNODB稍微慢了些。)

mysql> select count(*) from t3_push where rank1 < 20 and rank2 < 30;  

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

| count(*) |

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

|       49 |

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

1 row in set (0.54 sec)

mysql> select count(*) from t3_push where rank1 < 200 and rank2 < 300;       

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

| count(*) |

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

|     5759 |

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

1 row in set (4.13 sec)

但是TokuDB可以給二級索引變聚簇,所以這點上如果只讀的話,還是會比InnoDB快。

給列rank2 加聚簇索引,

mysql> alter table t3_push add clustering index idx_rank2(rank2);

Query OK, 0 rows affected (6.79 sec)

Records: 0  Duplicates: 0  Warnings: 0

現在所有的基於索引idx_rank2 的查詢都是瞬間的。

mysql> select count(*) from t3_push where rank1 < 20 and rank2 < 30;

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

| count(*) |

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

|       49 |

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

1 row in set (0.00 sec)

mysql> select count(*) from t3_push where rank1 < 200 and rank2 < 300;       

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

| count(*) |

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

|     5759 |

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

1 row in set (0.01 sec)

©著作權歸作者所有:來自51CTO部落格作者david_yeung的原創作品,如需轉載,請註明出處,否則將追究法律責任

MySQL最佳化InnoDBMySQL效能最佳化


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/430/viewspace-2820680/,如需轉載,請註明出處,否則將追究法律責任。

相關文章