我正在从事一个涉及大量数据库写入的项目(70%的插入和30%的读取)。这个比率还包括我认为是一个读一个写的更新。读取可能是脏的(例如,在读取时我不需要100%准确的信息)。 该任务每小时将处理超过100万个数据库事务。

我在网上读了一堆关于MyISAM和InnoDB之间区别的东西,对于我将用于这个任务的特定数据库/表来说,MyISAM似乎是显而易见的选择。从我看来,InnoDB在需要事务时是很好的,因为它支持行级锁。

有人有这种负载(或更高)的经验吗?MyISAM是正确的选择吗?


当前回答

几乎每次我开始一个新项目时,我都会问同样的问题,看看我是否能想出新的答案。

它最终归结为——我使用最新版本的MySQL并运行测试。

我有表,我想做键/值查找…就这些。我需要得到一个哈希键的值(0-512字节)。这个数据库上没有很多事务。表偶尔会更新(整个表),但是没有事务。

所以我们这里讨论的不是一个复杂的系统,我们讨论的是一个简单的查找,..以及如何(除了使表RAM常驻)优化性能。

我也在其他数据库(即NoSQL)上做测试,看看是否有任何地方我可以获得优势。我所发现的最大优势是键映射,但就查找而言,MyISAM目前是所有优势中的佼佼者。

虽然,我不会执行与MyISAM表的金融交易,但对于简单的查找,你应该测试它。通常是2倍到5倍的查询/秒。

试试吧,我欢迎辩论。

其他回答

根据我的经验,MyISAM是一个更好的选择,只要你不做delete、update、大量的单个INSERT、事务和全文索引。顺便说一句,CHECK TABLE太可怕了。随着表的行数越来越老,你不知道它什么时候会结束。

对于一个有更多写和读的负载,你将受益于InnoDB。因为InnoDB提供的是行锁而不是表锁,所以你的select可以是并发的,不仅仅是彼此之间的select,还有许多insert。但是,除非你打算使用SQL事务,否则将InnoDB提交刷新设置为2 (innodb_flush_log_at_trx_commit)。这将为您提供大量原始性能,否则将表从MyISAM转移到InnoDB时会损失这些性能。

Also, consider adding replication. This gives you some read scaling and since you stated your reads don't have to be up-to-date, you can let the replication fall behind a little. Just be sure that it can catch up under anything but the heaviest traffic or it will always be behind and will never catch up. If you go this way, however, I strongly recommend you isolate reading from the slaves and replication lag management to your database handler. It is so much simpler if the application code does not know about this.

最后,要注意不同的表负载。您不会在所有表上都有相同的读/写比率。一些接近100%读取的小表可以负担得起MyISAM。同样地,如果你有一些接近100%写的表,你可能会受益于INSERT DELAYED,但这只在MyISAM中支持(对于InnoDB表,DELAYED子句会被忽略)。

但基准是肯定的。

几乎每次我开始一个新项目时,我都会问同样的问题,看看我是否能想出新的答案。

它最终归结为——我使用最新版本的MySQL并运行测试。

我有表,我想做键/值查找…就这些。我需要得到一个哈希键的值(0-512字节)。这个数据库上没有很多事务。表偶尔会更新(整个表),但是没有事务。

所以我们这里讨论的不是一个复杂的系统,我们讨论的是一个简单的查找,..以及如何(除了使表RAM常驻)优化性能。

我也在其他数据库(即NoSQL)上做测试,看看是否有任何地方我可以获得优势。我所发现的最大优势是键映射,但就查找而言,MyISAM目前是所有优势中的佼佼者。

虽然,我不会执行与MyISAM表的金融交易,但对于简单的查找,你应该测试它。通常是2倍到5倍的查询/秒。

试试吧,我欢迎辩论。

底线:如果你离线工作,选择大量的数据,MyISAM可能会给你更好的(好得多)速度。

在某些情况下,MyISAM比InnoDB的效率要高得多:离线操作大型数据转储时(因为表锁)。

示例:我正在从NOAA转换一个csv文件(15M条记录),它使用VARCHAR字段作为键。InnoDB的运行时间很长,即使有大量的内存可用。

这是CSV的一个例子(第一个和第三个字段是键)。

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

因为我需要做的是运行观察到的天气现象的批量离线更新,我使用MyISAM表接收数据,并在键上运行join,这样我就可以清理传入的文件,并将VARCHAR字段替换为INT键(与原始VARCHAR值存储的外部表相关)。

人们经常谈论性能、读写、外键等等,但在我看来,存储引擎还有一个必须具备的特性:原子更新。

试试这个:

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.

性能当然是可取的,但不丢失数据更重要。