MySQL MEMORY 引擎及性能比對

2022-01-06 數據分析與開發

(點擊上方公眾號,可快速關注)

來源:十字螺絲釘

blog.chinaunix.net/uid-23284114-id-5775352.html

如有好文章投稿,請點擊 → 這裡了解詳情

同事諮詢MySQL MEMORY引擎的細節,能否滿足需求。沒有太多了解,這裡做個系統總結。

MEMORY存儲引擎創建的表數據只能保存在內存。

MySQL宕機、硬體故障或者意外掉電,都會造成MEMORY引擎表丟失數據。所以,MEMORY表中的數據來源於其他表(可落盤永久保存)用於只讀適用,或者用於臨時工作起到數據周轉。

MEMORY 存儲引擎特性

[a] Implemented in the server (via encryption functions). Data-at-rest tablespace encryption is available in MySQL 5.7 and later.

[b] Implemented in the server, rather than in the storage engine.

[c] Implemented in the server, rather than in the storage engine.

來源: https://dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html

何時使用MEMORY

性能特性

內存表受限於單線程執行和表級鎖引起的爭用。在負載增加時限制了可擴展性,特別是寫操作。

儘管內存表在內存中處理,在繁忙的服務網上,並不一定比InnoDB表更快,如一般查詢或者讀寫場景。特別是,多個會話執行update操作會造成性能低下。

根據不同的SQL查詢,需要創建內存表的默認hash索引(基於唯一鍵的單個值查詢),或者B-tree索引(等值查詢、不等值查詢或者範圍查詢)。

內存表的物理特性

每張內存表會在硬碟上創建一個文件,用於保存表結構(沒有數據)。文件名為以內存表名開始,.frm結尾。

特性

內存表的DDL操作

創建臨時表

CREATE TABLE t (i INT) ENGINE = MEMORY;

基於非內存表創建內存表,並將數據拉入到內存表中

mysql> CREATE TABLE test ENGINE=MEMORY

    ->     SELECT ip,SUM(downloads) AS down

    ->     FROM log_table GROUP BY ip;

mysql> SELECT COUNT(ip),AVG(down) FROM test;

mysql> DROP TABLE test;

內存表的最大受限於 max_heap_table_size 參數,默認為16MB。根據場景需自己調整該參數。

索引

MEMORY存儲引擎支持HASH和BTREE索引。

CREATE TABLE lookup

    (id INT, INDEX USING HASH (id))

    ENGINE = MEMORY;

CREATE TABLE lookup

    (id INT, INDEX USING BTREE (id))

    ENGINE = MEMORY;

每張內存表可創建64個索引,每個索引最大支持16個列,一個key的長度最大值為3072bytes。

如果一個內存表hash索引的鍵值有很高的重複度,更新鍵值、刪除操作速度都會顯著降低。這種速度下降的程度與鍵值重複度成正比。您可以使用BTREE索引來規避這個問題。

內存表可以有非唯一鍵(這是hash索引不常用的功能)。

索引列中可包含NULL值。

加載數據

MySQL啟動時,加入--init-file選項,將下列命令加入到這個文件中,保證啟動後內存表中有數據。

INSERT INTO ... SELECT 

LOAD DATA INFILE

內存表和複製(Replication)

伺服器重啟會導致內存表數據丟失。如果是主庫,從庫沒有意識到主庫表中數據已被情況,所以在從庫你看到的是過期數據。

重啟後,主從庫如何同步內存表數據?

當主庫使用內存表,主庫啟動後,一條DELETE語句會寫入到主庫的binary log中,從庫接到命令後清空內存表。

主庫重啟期間,從庫還是有讀取到過期數據的情況。為了避免這種情況,主庫啟動時加入--init-file參數,這樣主庫啟動自動將數據加載到內存表中。(官方文檔寫的不嚴謹,我認為僅限於內存表只讀場景。如果不是只讀,即使加入--init-file參數也無法保證主庫內存表數據一致)。

管理內存使用情況

伺服器必須有足夠內存,來滿足多張內存表的使用。

如果從內存表中刪除單獨的行,並不會回收內存。當整個內存表刪除時,才回收內存。同一張內存表,之前刪除行佔用的空間,會被新的行復用。執行DELETE、TRUNCATE TABLE來釋放內存表佔用空間,如果表不在使用可使用DROP TABLE命令。釋放正在使用的內存表佔用的內存,可以使用 ALTER TABLE XX ENGINE=MEMORY  強制重建表。

內存表1行記錄佔用內存計算公式

SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)

+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)

+ ALIGN(length_of_row+1, sizeof(char*))

ALIGN()表示一個round-up因子,其會導致行長度等於char指針大小的精確倍數。sizeof(char*)在32位機器上是4,64位則為8。

前面提到, max_heap_table_size 系統變量決定了內存表的最大尺寸。在創建內存之前,可設置該變量控制每個內存表的最大尺寸。(不建議修改全局 max_heap_table_size 的大小,否則所有會話的內存表最大尺寸都為該值 )。

下面的例子創建了2個內存表,最大尺寸為1M和2M

mysql> SET max_heap_table_size = 1024*1024;

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;

Query OK, 0 rows affected (0.01 sec)

mysql> SET max_heap_table_size = 1024*1024*2;

Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;

Query OK, 0 rows affected (0.00 sec)

伺服器重啟後,每個表的尺寸都變成了全局  max_heap_table_size 變量的值大小。

壓測結果

通過sysbench壓測,InnoDB 寫性能完爆MEMORY引擎,MEMORY的讀性能略高於InnoDB。InnoDB的綜合性能更好,足夠滿足日常使用。考慮到MEMORY引擎的雷點太多,建議不使用MEMORY引擎。

看完本文有收穫?請轉發分享給更多人

關注「資料庫開發」,提升 DB 技能

相關焦點

  • Mysql innodb 存儲引擎的性能優化
    ,但是關於資料庫方面的翻譯的不好,大家就看看吧,翻譯本文只是想更 清楚的了解mysql 優化上的一些基本原則,而國內對於這個沒有完整的資料。設計你的schema,索引和查詢,以及選擇正確的存儲引擎是常用的優化手段。1.2. 在有些情況下存儲引擎的選擇會影響到schema和索引1.3. 我們這裡不會覆蓋到一般的schema設計方法,但是會主要聚焦到Innodb存儲引擎。2. 每個存儲引擎都是不同的2.1. MySQl提供多種存儲引擎可供選擇2.2.
  • Mysql 資料庫引擎
    它還支持一些第三方的存儲引擎,例如TokuDB(高寫性能高壓縮存儲引擎)、Infobright(列式存儲引擎)。Mysql中 MyISAM和 InnoDB的區別有哪些?區別:1. InnoDB支持事務,MyISAM不支持事務。這是 MySQL 將默認存儲引擎從 MyISAM變成 InnoDB的重要原因之一;2.
  • 聊一聊MySQL的存儲引擎
    MySQL區別於其他資料庫的重要特點就是,其插件式(pluggable)的表存儲引擎。引擎(engine)是外來音譯詞,習慣上認為是發動機,好像和資料庫搭不上關係。最早MySQL的存儲引擎稱為「數據表處理器」,可能是聽起來太老土,後來才改成高大上的存儲引擎。存儲引擎的功能是接收上層傳下來的指令,然後對表中的數據進行讀取或寫入的操作。
  • MySQL性能優化的21條最佳經驗
    這樣一樣,MySQL資料庫引擎會在找到一條數據後停止搜索,而不是繼續往後查少下一條符合記錄的數據。下面的示例,只是為了找一下是否有「中國」的用戶,很明顯,後面的會比前面的更有效率。使用 VARCHAR 類型來當主鍵會使用得性能下降。另外,在你的程序中,你應該使用表的ID來構造你的數據結構。而且,在MySQL數據引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設置變得非常重要,比如,集群,分區……在這裡,只有一個情況是例外,那就是「關聯表」的「外鍵」,也就是說,這個表的主鍵,通過若干個別的表的主鍵構成。我們把這個情況叫做「外鍵」。
  • MySQL 變量及性能狀態查看知識技巧
    如何查看查看MySQL性能?  現在大家對MySQL的監控通常有兩種做法,一是連接到mysql資料庫內部,使用show status,show variables,flush status 來查看mysql的各種性能指標;二是直接使用mysqladmin查看其性能指標。
  • CUBRID和MySQL使用SSD前後性能測試對比
    使用CUBRID的公司可以得到更好的性能,高可靠性,靈活性,擴展性和高可用性,為其重要客戶提供7*24小時的持續服務」  CUBRID被韓國IT業的領頭企業NHN公司大量的使用,該公司部署了超過一萬臺CUBRID伺服器,看來它的確和MySQL有得一比,本文主要測試兩者的性能,我們同時在HDD硬碟和SSD硬碟上完成了測試,為了保證公平,每個資料庫(CUBRID和MySQL)都安裝在兩臺伺服器上
  • 這 4 款 MySQL 調優工具 yyds
    對於正在運行的mysql,性能如何,參數設置的是否合理,帳號設置的是否存在安全隱患,你是否瞭然於胸呢?俗話說工欲善其事,必先利其器,定期對你的MYSQL資料庫進行一個體檢,是保證資料庫安全運行的重要手段,因為,好的工具是使你的工作效率倍增!
  • 關於MySQL內存洩露如何排查的一些思路
    :268435456@@innodb_log_buffer_size:8388608@@tmp_table_size:16777216@@read_buffer_size:131072@@sort_buffer_size:1048576@@join_buffer_size:1048576@@read_rnd_buffer_size:2097152
  • 2021001期:Sysbench多線程性能測試工具
    :文件磁碟io的測試memory:內存分配及傳輸速度thread:線程調度測試mutex:POSIX的鎖測試OLTP:資料庫性能,主要支持MYSQL, PgSQL, Oracle 這3種資料庫安裝詳看git, 當前操作的Sysbench版本是1.0.17命令1sysbench [options
  • MySQL系列:count(*) 性能問題
    1count( * )的實現方式首先要明確的是,不同的引擎中count( * )有不同的實現方式。MyISAM 引擎把一個表的總行數存在磁碟上,因此執行count( * )的時候會直接返回這個數,效率非常高;InnoDB 引擎就會麻煩點,它執行count( * )的時候,需要把數據一行一行地從引擎裡面讀出來,然後再累積計數。
  • MySQL 入門 | 周末送資料
    ;2、伺服器通過使用雙層處理模型執行每條語句;3、客戶機通常不需要關心哪些引擎參與SQL語句處理,這種獨立於引擎的SQL語句的一些例外情況包括:- CREATE TABLE具有ENGINE選項,可基於每個表指定要使用的引擎;- ALTER TABLE具有ENGINE選項,允許將錶轉換為使用不同的存儲引擎;- 某些索引類型僅適用於特定存儲引擎
  • 總結MySQL 8種性能優化方式
    例子資料庫下載解壓後包含world.sql文件,使用mysql客戶端的source命令運行後,會創建包含前述三張表的world資料庫> create index idx_name on t(name);mysql> show index from name;
  • MYSQL的運行機制
    執行一條sql的時候,比如:mysql> select * from T whereID=10;
  • MySQL Cluster 搭建及配置
    NDB是一種in-memory的存儲引擎,它具有可用性高和數據一致性好的特點。MySQL Cluster可由多臺伺服器組成的、同時對外提供數據管理服務的分布式集群系統。通過合理的配置,可以將服務請求在多臺物理機上分發實現負載均衡 ;同時內部實現了冗餘機制,在部分伺服器宕機的情況下,整個集群對外提供的服務不受影響,從而能達到99.999%以上的高可用性。
  • Mysql資料庫的使用方法
    一、資料庫的基本概念1、 常用的兩種引擎: (1) InnoDB引擎:        1)支持ACID,簡單地說就是支持事務完整性、一致性;        2)支持行鎖,以及類似ORACLE的一致性讀,多用戶並發;        3)獨有的聚集索引主鍵設計方式,可大幅提升並發讀寫性能;
  • 雲伺服器如何安裝mysql
    1) 添加 mysql 用戶和 mysql 用戶組命令如下:[root@localhost ~]# groupadd mysql#添加mysql用戶組[root@localhost ~]# useradd -g mysql mysql#添加mysql用戶,同時指定mysql用戶的初始組是mysql組這裡添加的 mysql 用戶和用戶組是稍後用來給
  • 一篇解決面試常問的MySQL性能優化
    存儲引擎Storage engine:MySQL中的數據、索引以及其他對象是如何存儲的,是一套文件系統的實現。(從磁碟取數據是最影響性能的)join對join語句匹配關係(on)涉及的欄位建立索引能夠提高效率索引覆蓋如果要查詢的欄位都建立過索引,那麼引擎會直接在索引表中查詢而不會訪問原始數據(否則只要有一個欄位沒有建立索引就會做全表掃描),這叫索引覆蓋。
  • OpenResty、PHP-fpm與NodeJs操作MySQL的性能對比
    的投遞今天agentzh在微博上公布了一些OpenResty 與 php-fpm、Nodejs操作MySQL的性能評測數據。agentzh:我剛才在對比測試大結果集查詢時,發現NodeJS在使用 node-mysql庫訪問MySQL時,上下文切換次數居高不下,都快趕上 php-fpm + php-mysql了。
  • 案例|MySQL OOM排查之旅
    However when this is used with "Dynamic range access method", as range optimizer gets invoked multiple times, mysql ends up consuming a lot of memory.
  • 基於MySQL的高性能資料庫應用開發
    在NT的控制臺窗口中,進入MySQL的執行目錄(c:\mysql\bin),執行 ---- C:\mysql\bin\mysqld-shareware --standalone ---- 則MySQL的資料庫引擎啟動。