MySQL中MyISAM為什么比InnoDB查詢快


大家都知道在MySQL中,MyISAM比InnoDB查詢快,但很多人都不知道其中的原理。

今天我們就來聊聊其中的原理,另外也驗證下是否MyISAM比InnoDB真的查詢快。

在探索其中原理之前,我們先驗證下查詢速度。


驗證

下面我們一起來驗證兩個問題:

 

1、通過主鍵查詢,MyISAM是否比InnoDB查詢快?

2、通過非主鍵字段查詢,MyISAM是否比InnoDB查詢快?


驗證前准備

訂單表結構:

CREATE TABLE `trade` (
`id` INT(11) NULL DEFAULT NULL,
`trade_no` INT(11) NULL DEFAULT NULL,
UNIQUE INDEX `id` (`id`),
INDEX `trade_no` (`trade_no`)
)
COMMENT='訂單'
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;

分別創建不同引擎的表trade_myisam、trade_innodb,並插入10萬條測試數據,如下:

 


這里我們字段都采用Int類型,是為了方便我們,使用區間查詢,來驗證查詢速度。


驗證思路

1、分別通過id、trade_no查詢10000~20000區間的記錄,並獲得查詢所花費時間。

2、循環查詢100次,並取得查詢耗費時間平均值。

3、通過對比查詢 耗費 時間平均值,來判斷性能。


下面我們一起來驗證下,文章開頭的兩個問題:

1、主鍵查詢

C#實現主鍵查詢Id在10000~20000區間,查詢耗費時間平均值代碼如下:

using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
    //查詢次數
    var queryTime = 1000;
​
    //InnoDB數據引擎:
主鍵查詢
    //開始時間
    var startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_innodb where id>=10000 and id<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成時間
    var endTime = DateTime.Now;
    //耗時
    var spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("InnoDB主鍵查詢1000次平均耗時:
" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
​
    //MyISAM數據引擎:
主鍵查詢
    //開始時間
    startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_myisam where id>=10000 and id<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成時間
    endTime = DateTime.Now;
    //耗時
    spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("MyISAM主鍵查詢1000次平均耗時:
" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
​
    conn.Close();
}

運行結果:

通過上面的圖片,可以看到結果: MyISAM查詢性能確實比較Innodb快。


2、非主鍵查詢

C#實現費主鍵查詢trade_no在10000~20000區間,查詢耗費時間平均值代碼如下:

using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
    //查詢次數
    var queryTime = 1000;
​
    //InnoDB數據引擎:
非主鍵查詢
    //開始時間
    var startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_innodb where trade_no>=10000 and trade_no<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成時間
    var endTime = DateTime.Now;
    //耗時
    var spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("InnoDB非主鍵查詢1000次平均耗時:
" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
​
    //MyISAM數據引擎:
非主鍵查詢
    //開始時間
    startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_myisam where trade_no>=10000 and trade_no<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成時間
    endTime = DateTime.Now;
    //耗時
    spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("MyISAM非主鍵查詢1000次平均耗時:
" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
​
    conn.Close();
}

運行結果:

通過上面的圖片,可以看到結果: MyISAM查詢性能確實比較Innodb快。


對比結果

通過我們的驗證來看,不管是主鍵還是非主鍵查詢,MyISAM查詢性能確實比較Innodb快。 查詢速度不一樣,肯定是MyISAM與InnoDB有什么區別,下面我們一起來看看它們的區別。


MyISAM與InnoDB區別

 

通過上面表格對比, InnoDB在做SELECT的時候,要維護的東西比MYISAM引擎多很多,影響查詢速度有:

 

1)數據塊,InnoDB要緩存,MyISAM只緩存索引塊,  這中間還有換進換出的減少;

2)InnoDB尋址要映射到塊,再到行,MyISAM記錄的直接是文件的OFFSET,定位比InnoDB要快

3)InnoDB還需要維護MVCC一致; 雖然你的場景沒有,但他還是需要去檢查和維護

MVCC (Multi-Version Concurrency Control)多版本並發控制 。


索引區別:

 

MyISAM與InnoDB索引存儲方式是不一樣的(關於索引請查看《細說MySql索引原理》)。

 

InnoDB 的表是根據主鍵進行展開的 B+tree 的聚集索引。 MyISAM則非聚集型索引,MyISAM存儲會有兩個文件,一個是索引文件,另外一個是數據文件,其中索引文件中的索引指向數據文件中的表數據。

 

聚集型索引並不是一種單獨的索引類型,而是一種存儲方式,InnoDB 聚集型索引實際上是在同一結構中保存了 B+tree 索引和數據行。 當有聚簇索引時,它的索引實際放在葉子頁中。

 

下面我們通過2張圖,我們就能直觀看到這兩個引擎,索引結構的區別:

 

 

維護MVCC

InnoDB引擎還有需要實現MVCC,這里面也是損耗一定的性能的。 Innodb是通過每一行記錄有2個額外的隱藏值來實現,這兩個值一個記錄這行數據何時被創建,另外一個記錄這行數據何時過期(或者被刪除)。

 

但是InnoDB並不存儲這些事件發生時的實際時間,相反它只存儲這些事件發生時的系統版本號。 這是一個隨着事務的創建而不斷增長的數字。 每個事務在事務開始時會記錄它自己的系統版本號。 每個查詢必須去檢查每行數據的版本號與事務的版本號是否相同。


最后

通過我們的驗證來看,不管是主鍵還是非主鍵查詢,MyISAM查詢性能確實比較Innodb快。 但是MyISAM不支持事務,在實現業務方面有很多麻煩的事情。

 

關於我們開發中,選擇哪個數據引擎的問題。 平常在我們業務系統中,InnoDB數據引擎完全可以滿足我們的需求,這兩個引擎查詢性能差別還是比較小的,完全沒必要為了這點性能,給我們帶來更多的工作量MyISAM引擎更多是用於存儲數據倉庫,只有查詢少量插入的業務場景中,比如系統日志。

 

歡迎關注公眾號【編程樂趣】,了解更多MySQL知識

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM