2012-03-30 59 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创建索引,其中索引字段在您认为不会使用时不会使用。