2012-03-30 43 views
8

我有一個mysql表,其中有超過3000萬條記錄最初與myisam一起存儲。下面是表的說明:Mysql中Innodb和Myisam之間的性能差異

describe_table

我會跑反對此表下面的查詢一般需時約30秒才能完成。我會每次更改@eid以避免數據庫或磁盤緩存。

select count(fact_data.id) 
    from fact_data 
    where [email protected] 
     and fact_data.metric_id=1 

我然後轉換此表的InnoDB不進行任何其他更改,之後同樣的查詢第二,每一次我運行該查詢返回下英寸即使當我隨機設置@eid以避免緩存時,查詢也會在一秒之內返回。

我一直在研究兩種存儲類型之間的差異,試圖解釋性能的戲劇性改進,但一直未能拿出任何東西。事實上,我讀到的大部分內容都表明Myisam應該更快。

我正在運行的查詢是針對本地數據庫的,在測試時沒有其他進程打到數據庫。

回答

15

這是一個驚人的大的性能差異,但我可以想到一些可能有助於做出的事情。

MyISAM在歷史上被認爲比InnoDB更快,但是對於InnoDB的最新版本來說,對於更小的一組用例來說這是真實的。對於只讀表的表掃描,MyISAM通常更快。在大多數其他用例中,我通常會發現InnoDB更快。通常快很多倍。在我使用MySQL的大部分時間裏,表鎖都是MyISAM的死亡跪拜。

MyISAM在其關鍵緩衝區中緩存索引。也許你已經將關鍵緩衝區設置得太小了,因爲它不能有效地緩存你的有點大表的索引。

MyISAM依靠操作系統緩存來自OS磁盤緩存中.MYD文件的表數據。如果操作系統內存不足,它將開始轉儲其磁盤緩存。這可能會迫使它繼續讀取磁盤。

InnoDB將索引和數據緩存在其自己的內存緩衝區中。如果將innodb_flush_method設置爲O_DIRECT,則可以告訴操作系統不要使用其磁盤緩存,儘管OS X不支持該操作。

InnoDB通常在16kb頁面中緩衝數據和索引。根據您在查詢之間如何更改@eid的值,由於從以前的查詢中讀取磁盤,它可能已經緩存了一個查詢的數據。

確保您創建了相同的索引。使用解釋來檢查MySQL是否正在使用索引。由於您包含了describe的輸出,而不是show create table或show indexes,所以我無法確定entity_id是否是組合索引的一部分。如果它不是組合索引的第一部分,則不會使用它。

如果你正在使用MySQL的一個比較現代的版本,運行查詢之前運行以下命令:

組分析= 1;

這將打開您的會話的查詢分析。運行查詢後,運行

顯示配置文件;

這會向您顯示配置文件可用的查詢列表。我認爲它默認保持最後20個。假設您的查詢是第一個,請運行:

顯示查詢1的配置文件;

然後,您將看到運行查詢的每個階段的持續時間。這對於確定什麼(例如表鎖,排序,創建臨時表等)導致查詢緩慢非常有用。

6

我的第一個懷疑是原始的MyISAM表和/或索引隨着時間的推移變得碎片化,導致性能慢慢下降。 InnoDB表不會有同樣的問題,因爲你已經在其中創建了所有的數據(所以它將全部順序存儲在磁盤上)。

你可以通過重建MyISAM表來測試這個理論。最簡單的方法是使用「空」ALTER TABLE語句:

ALTER TABLE mytable ENGINE = MyISAM; 

然後檢查性能以查看它是否更好。

另一種可能性是如果數據庫本身只是針對InnoDB性能而不是MyISAM進行調優。例如,InnoDB使用innodb_buffer_pool_size parameter來知道應該分配多少內存用於在內存中存儲緩存的數據和索引。但MyISAM使用key_buffer參數。如果你的數據庫有一個大的innodb緩衝池和一個小的關鍵緩衝區,那麼InnoDB的性能會比MyISAM的性能好,特別是對於大型表。

+0

創建一個新的MyISAM表並對該表進行計時的合理簡單測試可以證實這種猜測。 – 2012-03-30 17:43:36

1

什麼是您的索引定義,您可以通過這些方法爲MyISAM創建索引,其中索引字段在您認爲不會使用時不會使用。