我正在从事一个涉及大量数据库写入的项目(70%的插入和30%的读取)。这个比率还包括我认为是一个读一个写的更新。读取可能是脏的(例如,在读取时我不需要100%准确的信息)。 该任务每小时将处理超过100万个数据库事务。
我在网上读了一堆关于MyISAM和InnoDB之间区别的东西,对于我将用于这个任务的特定数据库/表来说,MyISAM似乎是显而易见的选择。从我看来,InnoDB在需要事务时是很好的,因为它支持行级锁。
有人有这种负载(或更高)的经验吗?MyISAM是正确的选择吗?
我正在从事一个涉及大量数据库写入的项目(70%的插入和30%的读取)。这个比率还包括我认为是一个读一个写的更新。读取可能是脏的(例如,在读取时我不需要100%准确的信息)。 该任务每小时将处理超过100万个数据库事务。
我在网上读了一堆关于MyISAM和InnoDB之间区别的东西,对于我将用于这个任务的特定数据库/表来说,MyISAM似乎是显而易见的选择。从我看来,InnoDB在需要事务时是很好的,因为它支持行级锁。
有人有这种负载(或更高)的经验吗?MyISAM是正确的选择吗?
当前回答
InnoDB offers:
ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)
在InnoDB中,一行中除TEXT和BLOB外的所有数据最多占用8000字节。InnoDB没有全文索引。在InnoDB中,COUNT(*)s(当WHERE, GROUP BY或JOIN不使用时)执行速度比MyISAM慢,因为行数没有存储在内部。InnoDB将数据和索引存储在一个文件中。InnoDB使用缓冲池来缓存数据和索引。
MyISAM提供:
fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)
MyISAM has table-level locking, but no row-level locking. No transactions. No automatic crash recovery, but it does offer repair table functionality. No foreign key constraints. MyISAM tables are generally more compact in size on disk when compared to InnoDB tables. MyISAM tables could be further highly reduced in size by compressing with myisampack if needed, but become read-only. MyISAM stores indexes in one file and data in another. MyISAM uses key buffers for caching indexes and leaves the data caching management to the operating system.
总的来说,我推荐InnoDB用于大多数用途,MyISAM仅用于特殊用途。InnoDB现在是MySQL新版本的默认引擎。
其他回答
我曾经在一个使用MySQL的大容量系统上工作过,我也尝试过MyISAM和InnoDB。
我发现MyISAM中的表级锁定对我们的工作负载造成了严重的性能问题,这听起来与您的工作负载类似。不幸的是,我还发现在InnoDB下的性能也比我希望的要差。
最后,我通过分割数据解决了争用问题,这样插入就进入了一个“热”表,而选择从不查询热表。
这也允许删除(数据是时间敏感的,我们只保留X天的价值)发生在“陈旧”的表上,这些表同样不会被选择查询触及。InnoDB在批量删除方面的性能似乎很差,所以如果你打算清除数据,你可能想要以这样一种方式来构造它,即旧数据在一个陈旧的表中,可以简单地删除而不是对其进行删除。
当然,我不知道你的应用程序是什么,但希望这能让你对MyISAM和InnoDB的一些问题有一些了解。
根据我的经验,MyISAM是一个更好的选择,只要你不做delete、update、大量的单个INSERT、事务和全文索引。顺便说一句,CHECK TABLE太可怕了。随着表的行数越来越老,你不知道它什么时候会结束。
我知道这不会受欢迎,但我还是这么说:
myISAM缺乏对数据库基本要素的支持,如事务和引用完整性,这通常会导致应用程序出现故障/ bug。如果您的数据库引擎甚至不支持这些基础知识,那么您不可能不学习正确的数据库设计基础知识。
在数据库世界中不使用引用完整性或事务就像在软件世界中不使用面向对象编程一样。
InnoDB已经存在了,使用它吧!尽管myISAM是所有遗留系统的默认引擎,但MySQL开发人员最终还是同意在新版本中将其更改为默认引擎。
不,无论您是在读写还是有什么性能考虑,使用myISAM都会导致各种各样的问题,比如我刚刚遇到的这个问题:我正在执行数据库同步,同时其他人访问了一个访问myISAM表的应用程序。由于缺乏事务支持,这个引擎的可靠性也很差,导致整个数据库崩溃,我不得不手动重启mysql!
在过去15年的开发中,我使用了许多数据库和引擎。在此期间,myISAM在我身上崩溃了十几次,其他数据库只有一次!那是一个microsoft SQL数据库,其中一些开发人员编写了错误的CLR代码(公共语言运行时-基本上是在数据库内部执行的c#代码),顺便说一下,这并不是数据库引擎的错误。
我同意这里的其他答案,即高质量的高可用性、高性能应用程序不应该使用myISAM,因为它不起作用,它不够健壮或不够稳定,无法带来无挫折的体验。详见Bill Karwin的回答。
附注:我喜欢myISAM的粉丝们投反对票,但不能告诉你这个答案的哪一部分是错误的。
有点晚了…但这是我几个月前写的一篇相当全面的文章,详细介绍了MYISAM和InnoDB之间的主要区别。喝杯茶(或者一块饼干),好好享受吧。
MyISAM和InnoDB之间的主要区别在于引用完整性和事务。还有其他区别,如锁定、回滚和全文搜索。
参照完整性
Referential integrity ensures that relationships between tables remains consistent. More specifically, this means when a table (e.g. Listings) has a foreign key (e.g. Product ID) pointing to a different table (e.g. Products), when updates or deletes occur to the pointed-to table, these changes are cascaded to the linking table. In our example, if a product is renamed, the linking table’s foreign keys will also update; if a product is deleted from the ‘Products’ table, any listings which point to the deleted entry will also be deleted. Furthermore, any new listing must have that foreign key pointing to a valid, existing entry.
InnoDB是一个关系DBMS (RDBMS),因此具有引用完整性,而MyISAM没有。
事务和原子性
表中的数据使用数据操作语言(DML)语句进行管理,例如SELECT、INSERT、UPDATE和DELETE。事务将两个或多个DML语句组合到一个工作单元中,因此可以应用整个工作单元,也可以不应用任何工作单元。
MyISAM不支持事务,而InnoDB支持。
如果在使用MyISAM表时操作中断,操作将立即中止,受影响的行(甚至是每行中的数据)仍然受到影响,即使操作没有完成。
如果一个操作在使用InnoDB表时被中断,因为它使用事务,具有原子性,任何没有完成的事务都不会生效,因为没有提交。
表锁vs行锁
当对MyISAM表执行查询时,所查询的整个表将被锁定。这意味着后续查询只会在当前查询完成后执行。如果您正在读取一个大的表,并且/或者有频繁的读和写操作,这可能意味着大量的查询积压。
当对InnoDB表执行查询时,只有涉及的行被锁定,表的其余部分仍可用于CRUD操作。这意味着查询可以在同一个表上同时运行,前提是它们不使用同一行。
这个特性在InnoDB中被称为并发。尽管并发性很好,但对于选择的表范围有一个主要缺点,即在内核线程之间切换时会产生开销,您应该对内核线程设置一个限制,以防止服务器停止。
事务和回滚
当你在MyISAM中运行一个操作时,更改被设置;在InnoDB中,这些更改可以回滚。用于控制事务的最常用命令是COMMIT、ROLLBACK和SAVEPOINT。1. COMMIT -你可以写多个DML操作,但是只有在COMMIT时更改才会被保存。ROLLBACK -你可以放弃任何尚未提交的操作。SAVEPOINT—设置ROLLBACK操作可以回滚到的操作列表中的一个点
可靠性
MyISAM不提供数据完整性——硬件故障、不干净的关机和取消的操作都可能导致数据损坏。这将需要完全修复或重新构建索引和表。
另一方面,InnoDB使用事务日志、双写缓冲区和自动校验和验证来防止损坏。在InnoDB做任何更改之前,它会将事务之前的数据记录到一个名为ibdata1的系统表空间文件中。如果出现崩溃,InnoDB会通过重放这些日志自动恢复。
全文索引
InnoDB直到MySQL 5.6.4版本才支持FULLTEXT索引。在撰写本文时,许多共享主机提供商的MySQL版本仍然低于5.6.4,这意味着InnoDB表不支持FULLTEXT索引。
然而,这并不是使用MyISAM的正当理由。最好换一个支持最新版本MySQL的主机提供商。并不是说使用FULLTEXT索引的MyISAM表不能转换为InnoDB表。
结论
总之,InnoDB应该是您的默认存储引擎选择。在满足特定需求时选择MyISAM或其他数据类型。
人们经常谈论性能、读写、外键等等,但在我看来,存储引擎还有一个必须具备的特性:原子更新。
试试这个:
Issue an UPDATE against your MyISAM table that takes 5 seconds. While the UPDATE is in progress, say 2.5 seconds in, hit Ctrl-C to interrupt it. Observe the effects on the table. How many rows were updated? How many were not updated? Is the table even readable, or was it corrupted when you hit Ctrl-C? Try the same experiment with UPDATE against an InnoDB table, interrupting the query in progress. Observe the InnoDB table. Zero rows were updated. InnoDB has assured you have atomic updates, and if the full update could not be committed, it rolls back the whole change. Also, the table is not corrupt. This works even if you use killall -9 mysqld to simulate a crash.
性能当然是可取的,但不丢失数据更重要。