【问题标题】:Performance difference between Innodb and Myisam in MysqlMysql中Innodb和Myisam的性能差异
【发布时间】:2012-04-14 09:58:50
【问题描述】:

我有一个 mysql 表,其中包含超过 3000 万条记录,这些记录最初是使用 myisam 存储的。以下是对该表的说明:

我将对这个表运行以下查询,这通常需要大约 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 应该更快。

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

【问题讨论】:

    标签: mysql database innodb myisam


    【解决方案1】:

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

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

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

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

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

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

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

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

    设置分析 = 1;

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

    显示个人资料;

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

    显示查询 1 的配置文件;

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

    【讨论】:

      【解决方案2】:

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

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

      ALTER TABLE mytable ENGINE = MyISAM;
      

      然后检查性能,看看是否更好。

      另一种可能性是,如果数据库本身只是针对 InnoDB 性能而不是 MyISAM 进行了调整。例如,InnoDB 使用innodb_buffer_pool_size parameter 来了解应该分配多少内存来在内存中存储缓存数据和索引。但是 MyISAM 使用 key_buffer 参数。如果你的数据库有一个大的 innodb 缓冲池和一个小的 key buffer,那么 InnoDB 的性能会比 MyISAM 的性能好,尤其是对于大表。

      【讨论】:

      • 创建一个新的 MyISAM 表并针对该表计时查询的合理简单测试可以证实这一猜测。
      【解决方案3】:

      您的索引定义是什么,您可以通过多种方式为 MyISAM 创建索引,当您认为它们会使用时,您的索引字段不会被使用。

      【讨论】:

        猜你喜欢
        • 2013-04-08
        • 2015-05-23
        • 2012-03-01
        • 1970-01-01
        • 2011-05-14
        • 2012-03-29
        • 2011-04-18
        • 2012-01-13
        • 2011-09-17
        相关资源
        最近更新 更多