繁体   English   中英

Mysql中Innodb和Myisam之间的性能差异

[英]Performance difference between Innodb and Myisam in Mysql

我有一个mysql表,其中有超过3000万条记录最初与myisam一起存储。 这是表格的描述:

describe_table

我将针对此表运行以下查询,通常需要大约30秒才能完成。 我每次都会更改@eid以避免数据库或磁盘缓存。

select count(fact_data.id) 
    from fact_data 
    where fact_data.entity_id=@eid 
        and fact_data.metric_id=1

然后我将此表转换为innoDB而不进行任何其他更改,之后相同的查询现在每次运行查询时返回一秒钟。 即使我随机设置@eid以避免缓存,查询也会在一秒钟内返回。

我一直在研究这两种存储类型之间的差异,试图解释性能的显着改善,但却未能提出任何建议。 事实上,我读到的大部分内容都表明Myisam应该更快。

我正在运行的查询是针对本地数据库的,在测试时没有其他进程访问数据库。

这是一个惊人的巨大性能差异,但我可以想到一些可能有所贡献的事情。

MyISAM在历史上被视为比InnoDB更快,但对于InnoDB的最新版本,对于更小,更小的用例集来说也是如此。 对于只读表的表扫描,MyISAM通常更快。 在大多数其他用例中,我通常发现InnoDB更快。 通常快很多倍。 在我使用MySQL的大部分时间里,表锁是MyISAM的丧钟。

MyISAM在其密钥缓冲区中缓存索引。 也许您已经将密钥缓冲区设置得太小,无法有效地为您的大型表缓存索引。

MyISAM依赖于OS来缓存OS磁盘缓存中的.MYD文件中的表数据。 如果操作系统内存不足,它将开始转储其磁盘缓存。 这可能会迫使它继续从磁盘读取。

InnoDB将索引和数据缓存在自己的内存缓冲区中。 如果将innodb_flush_method设置为O_DIRECT,则可以告诉操作系统不要使用其磁盘缓存,但OS X不支持此操作。

InnoDB通常在16kb页面中缓冲数据和索引。 根据您在查询之间更改@eid值的方式,由于来自先前查询的磁盘读取,它可能已经缓存了一个查询的数据。

确保以相同方式创建索引。 使用explain来检查MySQL是否正在使用索引。 由于您包含了describe的输出而不是show create table或show indexes from,我无法判断entity_id是否是复合索引的一部分。 如果它不是复合索引的第一部分,则不会使用它。

如果您使用的是相对现代版本的MySQL,请在运行查询之前运行以下命令:

set profiling = 1;

这将打开您的会话的查询分析。 运行查询后,运行

显示档案;

这将显示可用配置文件的查询列表。 我认为它默认保留最后20个。 假设您的查询是第一个,请运行:

显示查询1的配置文件;

然后,您将看到运行查询的每个阶段的持续时间。 这对于确定什么(例如,表锁,排序,创建临时表等)导致查询变慢非常有用。

我的第一个怀疑是原始的MyISAM表和/或索引随着时间的推移变得支离破碎,导致性能慢慢降低。 InnoDB表不会有同样的问题,因为你创建了它已经包含了所有数据(因此它将全部按顺序存储在磁盘上)。

你可以通过重建MyISAM表来测试这个理论。 最简单的方法是使用“null”ALTER TABLE语句:

ALTER TABLE mytable ENGINE = MyISAM;

然后检查性能以确定它是否更好。

另一种可能性是,数据库本身只是针对InnoDB性能而不是MyISAM进行调整。 例如,InnoDB使用innodb_buffer_pool_size parameter来知道应该分配多少内存来存储内存中的缓存数据和索引。 但MyISAM使用key_buffer参数。 如果您的数据库有一个大的innodb缓冲池和一个小的密钥缓冲区,那么InnoDB性能将比MyISAM性能更好,特别是对于大型表。

您的索引定义是什么,有些方法可以为MyISAM创建索引,在这些索引中您的索引字段将不会被使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM