InnoDB和MyISAM之间的主要区别是什么?


245

InnoDB和MyISAM之间的主要区别是什么?


23
如果需要数据库引擎,请使用InnoDB。 您无法将两者进行比较
杰里米·斯坦

尽管以下许多答案是正确的,但恕我直言,它们并不能将事情归结为清楚。这个站点可以,要点是:InnoDB是行级锁定,MyISAM是表级锁定。通常,这意味着MyISAM对于OLAP(分析,主要是读取)会更好,而InnoDB对于OLTP(事务,主要是写入,或至少很多写入)会更好。
麦克威廉姆森

Answers:


159

我看到的第一个主要区别是InnoDB实现行级锁,而MyISAM只能执行表级锁。您会在InnoDB中发现更好的崩溃恢复。但是,FULLTEXT直到v5.6为止,它都没有搜索索引,MyISAM也没有。InnoDB还实现事务,外键和关系约束,而MyISAM不实现。

该列表可以走得更远。但是,它们在彼此的有利与不利方面都有其独特的优势。在某些情况下,它们每个都比另一个更适合。

总结一下(TL; DR):

  • InnoDB具有行级锁定,MyISAM只能执行完整表级锁定。
  • InnoDB具有更好的崩溃恢复。
  • MyISAM具有FULLTEXT搜索索引,而InnoDB直到MySQL 5.6(2013年2月)才开始。
  • InnoDB实现事务,外键和关系约束,而MyISAM不实现。

亲爱的先生,那么最终该用什么呢?MyISAM还是InnoDB?完全困惑...我的网站正在使用mysql,我需要决定这一点。
sqlchild 2012年

3
取决于应用程序,写下具有所需功能的列表(例如,全文搜索,外键...),然后尝试确定一项(尝试对每个功能进行评分,然后计算分数)。您将无法全部拥有它们,但是由您决定最需要巫婆功能。
poelinca 2012年

2
我编辑了他的帖子以进行澄清。
Mathias Lykkegaard Lorenzen 2013年

1
@MathiasLykkegaardLorenzen谢谢,这就是我们喜欢
stackexchange

version 5.6.4InnoDB开始支持FULLTEXT搜索。dev.mysql.com/doc/refman/5.6/en/fulltext-restrictions.html
做白日梦

85

尚未提及的另一个主要区别是如何完成每个存储引擎的缓存。

MYISAM

使用的主要机制是密钥缓存。它仅从.MYI文件缓存索引页。要调整密钥缓存的大小,请运行以下查询:

SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.4999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1))
recommended_key_buffer_size FROM
(SELECT LEAST(POWER(2,32),KBS1) KBS
FROM (SELECT SUM(index_length) KBS1
FROM information_schema.tables
WHERE engine='MyISAM' AND
table_schema NOT IN ('information_schema','mysql')) AA ) A,
(SELECT 2 PowerOf1024) B;

这将使对MyISAM键缓存(推荐设置的key_buffer_size鉴于你目前的数据集()查询将限制在4G(4096M推荐)。对于32位操作系统,是4GB的极限。对于64位,8GB。

创新数据库

使用的主要机制是InnoDB缓冲池。它从访问的InnoDB表中缓存数据和索引页。要确定您的InnoDB缓冲池的大小,请运行以下查询:

SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.49999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1)) recommended_innodb_buffer_pool_size
FROM (SELECT SUM(data_length+index_length) KBS FROM information_schema.tables
WHERE engine='InnoDB') A,
(SELECT 2 PowerOf1024) B;

给定当前数据集,这将为InnoDB缓冲池(innodb_buffer_pool_size)的大小提供推荐设置。

不要忘记调整InnoDB日志文件(ib_logfile0和ib_logfile1)的大小。MySQL源代码对所有InnoDB日志文件的合并大小设置了上限,必须小于4G(4096M)。为了简单起见,仅给出两个日志文件,以下是如何调整它们的大小:

  • 步骤1)将innodb_log_file_size = NNN添加到/etc/my.cnf(NNN应为innodb_buffer_pool_size的25%或2047M,以较小者为准)
  • 第2步) service mysql stop
  • 第三步 rm /var/log/mysql/ib_logfile[01]
  • 步骤4)service mysql start(重新创建了ib_logfile0和ib_logfile1)

警告

在两个查询的末尾是一个内联查询 (SELECT 2 PowerOf1024)B

  • (SELECT 0 PowerOf1024) 以字节为单位给出设置
  • (SELECT 1 PowerOf1024) 以千字节为单位给出设置
  • (SELECT 2 PowerOf1024) 以兆字节给出设置
  • (SELECT 3 PowerOf1024) 以千兆字节给出设置
  • 不能接受小于0或大于3的幂

结语

没有什么可以替代常识。如果内存有限,混合使用存储引擎或其组合,则必须针对不同的情况进行调整。

  • 如果您有2GB RAM和16GB InnoDB,请分配512M作为innodb_buffer_pool。
  • 如果您有2GB RAM和4GB MyISAM索引,请分配512M作为key_buffer_size。
  • 如果您有2GB RAM和4GB MyISAM索引以及16GB InnoDB,则将512M分配为key_buffer_size,将512M分配为innodb_buffer_pool_size。

可能的情况是无止境的!

请记住,无论分配多少,都要为DB连接和操作系统留出足够的RAM。


那些是坏公式!
里克·詹姆斯

(糟糕-别忘了不能有段落)...我将添加一个“答案”。
里克·詹姆斯

Rolando的缓存大小公式不切实际。-不需要2的幂。-在32位操作系统上不可能有4GB。-这是我将它们设置为以下内容的摘要mysql.rjweb.org/doc.php/memory(它解决了影响内存使用的其他各种设置。)
Rick詹姆斯

2
@Rick:2的幂是用来以不同单位显示答案。做(SELECT 2 PowerOfTwo)设置答案的显示,以MB为单位。执行(SELECT 3 PowerOfTwo)设置以GB为单位的显示。(SELECT 1 PowerOfTwo)以KB显示。(SELECT 0 PowerOfTwo)以字节为单位显示。这就是(SELECT 2 PowerOfTwo)所做的。因此,仅需显示,而不在体系结构中施加任何假定值。
RolandoMySQLDBA 2011年

2
@Rick:你知道吗?实际上,出于两个非常重要的原因,我将给您+1。1)您的URL确认我的答案是正确的,因为4GB是分配给key_buffer_size的最大数字。2)您的答案以及URL,对于内存非常低的计算机来说很有意义。我将在应得的贷方给您信用。
RolandoMySQLDBA 2011年

60

InnoDB提供:

  • ACID交易
  • 行级锁定
  • 外键约束
  • 自动崩溃恢复
  • 表压缩(读/写)
  • 空间数据类型(无空间索引)

在InnoDB中,除了TEXT和BLOB之外,一行中的所有数据最多可以占用8,000个字节。在MySQL 5.6(2013年2月)之前,InnoDB中不提供全文索引。在InnoDB中的COUNT(*)S(时WHEREGROUP BYJOIN不使用)执行比的MyISAM因为行计数不内部存储慢。InnoDB将数据和索引都存储在一个文件中。InnoDB使用缓冲池来缓存数据和索引。

MyISAM提供:

  • 快速COUNT(*)S(时WHEREGROUP BYJOIN不使用)
  • 全文索引(更新:MySQL 5.6中的InnoDB支持)
  • 较小的磁盘空间
  • 很高的表压缩率(只读)
  • 空间数据类型和索引(R树)(更新:MySQL 5.7中的InnoDB支持)

MyISAM具有表级锁定,但没有行级锁定。没有交易。没有自动崩溃恢复,但是它确实提供了修复表功能。没有外键约束。与InnoDB表相比,MyISAM表在磁盘上的大小通常更紧凑。如果需要,可以通过使用myisampack进行压缩来进一步高度减小MyISAM表的大小,但该表将变为只读状态。MyISAM将索引存储在一个文件中,将数据存储在另一个文件中。MyISAM使用密钥缓冲区来缓存索引,并将数据缓存管理留给操作系统。

总的来说,我会建议将InnoDB用于大多数用途,并将MyISAM仅用于特殊用途。现在,InnoDB是新MySQL版本中的默认引擎。


5
我阅读了您的答案,并将其与此处已有的其他人进行了比较。您是唯一提及BLOB的人。他们通常被认为是理所当然的。您也是唯一提及myisampack的人,myisampack是快速读取MyISAM表的无名英雄之一。您的今天是+1 !!!
RolandoMySQLDBA 2011年

2
示例是压缩的只读表,在其中您可以通过完全替换表来对其进行不频繁更新。
dabest1

30

还有一件事:您只需拍摄文件系统快照即可备份InnoDB表。备份MyISAM需要使用mysqldump,并且不能保证是一致的(例如,如果您插入父表和子表,则可能在备份中仅找到子表的行)。

基本上,如果您有另一个数据副本,并且仅将其缓存在MySQL中(例如,允许从PHP网站访问数据的标准方法),那么MyISAM很好(即,它比平面CSV文件或用于查询和查询的日志文件更好)并发访问)。如果数据库是数据的实际的“底本”,如果你正在做的INSERT,并UPDATE使用来自用户的真实数据,那么它是愚蠢的使用比InnoDB的其他任何东西,在任何形式的大规模的MyISAM是不可靠和难以管理,你会减少myisamchk一半的时间,而不会提高性能。

(我的个人经验:MyISAM中的2 TB数据库)。


29

游戏有点晚了……但是这是我几个月前写的一篇非常全面的文章,详细介绍了MYISAM和InnoDB之间的主要区别。拿起一杯(可能还有饼干),然后享用。


MyISAM和InnoDB之间的主要区别在于引用完整性和事务。还有其他区别,例如锁定,回滚和全文本搜索。

参照完整性

参照完整性可确保表之间的关系保持一致。更具体地说,这意味着当一个表(例如清单)具有指向另一个表(例如产品)的外键(例如产品ID)时,当指向该表的更新或删除发生时,这些更改将级联到链接中表。在我们的示例中,如果产品被重命名,则链接表的外键也会更新;如果从“产品”表中删除了产品,则指向已删除条目的所有列表也会被删除。此外,任何新列表都必须具有指向有效的现有条目的外键。

InnoDB是一个关系型DBMS(RDBMS),因此具有参照完整性,而MyISAM没有。

交易与原子性

使用数据操作语言(DML)语句(例如SELECT,INSERT,UPDATE和DELETE)来管理表中的数据。一个事务将两个或多个DML语句组合在一起成为一个工作单元,因此要么应用整个单元,要么不应用。

MyISAM不支持事务,而InnoDB支持。

如果在使用MyISAM表时操作被中断,则该操作将立即中止,并且即使操作未完成,受影响的行(甚至每一行中的数据)仍会受到影响。

如果在使用InnoDB表时操作被中断,因为该操作使用具有原子性的事务,则任何未完成的事务都不会生效,因为不会进行提交。

表锁定与行锁定

当查询针对MyISAM表运行时,查询所在的整个表将被锁定。这意味着后续查询仅在当前查询完成后才执行。如果您正在读取一个大表,并且/或者频繁进行读写操作,那么这可能意味着大量的查询积压。

当查询针对InnoDB表运行时,只有所涉及的行被锁定,该表的其余部分仍可用于CRUD操作。这意味着查询可以在同一表上同时运行,前提是它们不使用同一行。

InnoDB中的此功能称为并发。就并发性而言,最大的缺点是它适用于选定的表范围,因为在内核线程之间进行切换会产生开销,因此您应该对内核线程设置一个限制,以防止服务器停机。

交易和回滚

当您在MyISAM中运行操作时,将进行更改。在InnoDB中,这些更改可以回滚。用于控制事务的最常见命令是COMMIT,ROLLBACK和SAVEPOINT。1. COMMIT-您可以编写多个DML操作,但所做的更改仅在进行COMMIT时保存。2. ROLLBACK-您可以丢弃尚未提交的所有操作3. SAVEPOINT-在以下列表中设置一个点ROLLBACK操作可以回滚到的操作

可靠性

MyISAM不提供数据完整性-硬件故障,不正常关机和取消的操作都可能导致数据损坏。这将需要完全修复或重建索引和表。

另一方面,InnoDB使用事务日志,双重写入缓冲区以及自动校验和和验证来防止损坏。在InnoDB进行任何更改之前,它会将事务之前的数据记录到名为ibdata1的系统表空间文件中。如果发生崩溃,InnoDB将通过重播这些日志来自动恢复。

全文索引

在MySQL版本5.6.4之前,InnoDB不支持FULLTEXT索引。在撰写本文时,许多共享的托管服务提供商的MySQL版本仍低于5.6.4,这意味着InnoDB表不支持FULLTEXT索引。

但是,这不是使用MyISAM的有效理由。最好更改为支持MySQL最新版本的托管服务提供商。并不是使用FULLTEXT索引的MyISAM表不能转换为InnoDB表。

结论

总之,InnoDB应该是您选择的默认存储引擎。当它们满足特定需要时,请选择MyISAM或其他数据类型。


1
谢谢,非常有益和清晰的摘要。
informatik01

18

以我的经验,最大的不同是每个引擎处理锁定的方式。InnoDB使用行锁定,而MyISAM使用表锁定。根据经验,我将InnoDB用于写入大量表,而将MyISAM用于读取大量表。

其他重要差异包括:

  1. InnoDB支持事务和外键。MyISAM没有。
  2. MyISAM使用全文索引。
  3. MyISAM在执行数据完整性方面做得很差。

过时了-InnoDB现在有FULLTEXTSPATIAL。InnoDB对于读取和写入繁重的负载都很有用。
瑞克·詹姆斯

8

我倾向于将MyISAM视为MySQL的“默认”表选择,因此我将指出大多数InnoDB用户的不同之处

  • 行级锁定
  • 外键执行
  • 交易支持
  • 高使用率系统的性能下降

5
除了最新的MySQL版本不再使用MyISAM作为默认引擎。在5.5中,他们将默认值更改为InnoDB :)。我不同意InnoDB通常只会受到“性能打击”的说法。精心设计的InnoDB表具有正确的索引和正确配置的内存设置,可以使InnoDB表在MyISAM中的性能与相同的模式相同
TechieGurl 2011年

3
在许多“高使用率”情况下,InnoDB实际上比MyISAM 表现更好。MyISAM是解决特定问题的特定工具,而InnoDB在大多数情况下都可以为您提供更好的服务(因此,MySQL团队将其设置为默认引擎)。这是因为MyISAM是很长一段时间以来唯一的引擎,即使InnoDB成熟了,MySQL社区也逐渐习惯于默认使用MyISAM。
Nick Chammas

2
在MySQL 5.6开发周期的中途添加了对InnoDB的FULLTEXT搜索。现在引用的URL也涵盖了InnoDB。
Max Webster

5

MYISAM

MYISAM提供表级锁定,FULLTEXT搜索。MYISAM具有最灵活的AUTO_INCREMENTED列,可处理所有存储引擎。MYISAM不支持交易。

创新数据库

INNODB是事务安全的存储引擎。INNODB具有提交,回滚和崩溃恢复功能。INNODB支持外键引用完整性。


5

包括MySQL 5.6更改

INNODB储存引擎:

  • 它提供完全的ACID(原子性,一致性,隔离性,耐久性)合规性。多版本用于将事务彼此隔离。
  • 在MySQL服务器或运行该服务器的主机崩溃后,InnoDB提供自动恢复。
  • InnoDB支持外键和参照完整性,包括级联的删除和更新。
  • MySQL 5.6建立在InnoDB平台上,该平台已完全集成为默认存储引擎
  • 持久优化器统计信息:提高InnoDB索引统计信息的准确性,并在MySQL重新启动时保持一致。
  • 修剪InnoDB表缓存:为了减轻具有大量表的系统上的内存负载,InnoDB现在释放与打开的表关联的内存。LRU算法选择最长的表而不被访问。
  • 支持全文搜索:一种特殊的索引FULLTEXT索引可帮助InnoDB处理涉及基于文本的列及其所包含的单词的查询和DML操作。这些索引在物理上表示为整个InnoDB表。
  • 在全文搜索中,InnoDB似乎比MyISAM快得多

因此,MyISAM如果您已经升级到5.6,那么使用Engine 没有意义,否则请不要等待升级到MySQL 5.6。

使用MySQL 5.6的InnoDB VS MyISAM性能


2

我的ISAM

MyISAM是MySQL的存储引擎。在MySQL 5.5之前,它是MySQL的默认存储引擎。它基于较旧的ISAM存储引擎。MyISAM针对具有大量读取操作,很少写入或根本不写入的环境进行了优化。MyISAM允许快速读取的原因是其索引的结构:每个条目都指向数据文件中的一条记录,并且指针从文件的开头偏移。这样可以快速读取记录,尤其是在格式为FIXED的情况下。因此,这些行具有恒定的长度。数据仓库是一个可能首选MyISAM的典型领域,因为它涉及对非常大的表的查询,并且在不使用数据库时(通常在晚上)进行此类表的更新。插入也很容易,因为新行会附加到数据文件的末尾。然而,删除和更新操作的问题更大:删除操作必须留一个空白,否则行的偏移量会发生变化;随着行的长度变短,更新也是如此;如果更新使行变长,则该行将被分割。要对行进行碎片整理并声明空白空间,OPTIMIZE TABLE命令必须执行。由于这种简单的机制,通常MyISAM索引统计信息非常准确。MyISAM的其他主要缺点是缺少事务支持和外键。

创新数据库

InnoDB是MySQL的存储引擎。MySQL 5.5及更高版本默认使用它。它提供了符合ACID的标准交易功能,以及外键支持(声明性参照完整性)。它FULLTEXT遵循OpenGIS标准实现SQL和XA事务,表空间,索引和空间操作。它是MySQL AB发行的大多数二进制文件中的标准配置,但某些OEM版本除外。该软件已获得Oracle Corporation的双重许可;它是根据GNU通用公共许可证发行的,但也可以授权给希望将InnoDB与专有软件结合的各方。

前叉

MariaDB有一个称为Aria的存储引擎,它被描述为“ MyISAM的崩溃安全替代品”。默认情况下,MariaDB和Percona Server使用名为XtraDB的InnoDB分支。XtraDB由Percona维护。Oracle InnoDB的更改会定期导入XtraDB,并添加了一些错误修复和其他功能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.