我应该在MySQL数据库中使用MyISAM还是InnoDB表?

13

我在数据库中有以下两个表(索引不完整,将根据使用的引擎而定):

表格1:

CREATE TABLE `primary_images` (
  `imgId` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  `imgTitle` varchar(255) DEFAULT NULL,
  `view` varchar(45) DEFAULT NULL,
  `secondary` enum('true','false') NOT NULL DEFAULT 'false',
  `imgURL` varchar(255) DEFAULT NULL,
  `imgWidth` smallint(6) DEFAULT NULL,
  `imgHeight` smallint(6) DEFAULT NULL,
  `imgDate` datetime DEFAULT NULL,
  `imgClass` enum('jeans','t-shirts','shoes','dress_shirts') DEFAULT NULL,
  `imgFamily` enum('boss','lacoste','tr') DEFAULT NULL,
  `imgGender` enum('mens','womens') NOT NULL DEFAULT 'mens',
  PRIMARY KEY (`imgId`),
  UNIQUE KEY `imgDate` (`imgDate`)
)

表格2:

CREATE TABLE `secondary_images` (
  `imgId` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  `primaryId` smallint(6) unsigned DEFAULT NULL,
  `view` varchar(45) DEFAULT NULL,
  `imgURL` varchar(255) DEFAULT NULL,
  `imgWidth` smallint(6) DEFAULT NULL,
  `imgHeight` smallint(6) DEFAULT NULL,
  `imgDate` datetime DEFAULT NULL,
  PRIMARY KEY (`imgId`),
  UNIQUE KEY `imgDate` (`imgDate`)
)

将使用Table 1创建缩略图库,并连接到更大的图片版本。 imgClassimgFamilyimgGender将精确显示缩略图。

Table 2包含与Table 1中相应内容相关的图像。因此,使用primaryId将Table 1中的单个图像与Table 2中的一个或多个图像相关联。这就是我考虑使用InnoDB的外键功能的地方,但我也熟悉MyISAM中索引的同样的功能。

不深入了解其余字段,imgDate用于排序结果。

最后但并非最不重要的是,我应该提到这个数据库是“只读”的。所有数据都将由我输入。据告知,如果数据库是只读的,则应使用MyISAM,但我希望您可以为我的情况提供一些启示。


这个问题引发了辩论...应该迁移到Programmers吗...??? - IAbstract
@IAbstract - 你提到了我不知道的事情,但如果你能详细说明,我很乐意配合。 - stefmikhail
http://Programmers.StackExchange.com 比 StackOverflow 更主观。问题的提出方式会引发关于哪个更好的辩论...通常这些问题已经被关闭了。但是由于现在存在 Programmers 并允许在问题中有更多的主观性,似乎更合适...在我看来。 - IAbstract
4个回答

26

默认情况下始终使用InnoDB。

在MySQL 5.1及以后的版本中,应该使用InnoDB。在MySQL 5.1中,您应该启用InnoDB插件。在MySQL 5.5中,默认情况下启用了InnoDB插件,因此只需使用它即可。

多年前的建议是,在许多场景下MyISAM更快。但是,如果您使用当前版本的MySQL,则不再如此。

可能存在一些奇特的边角案例,其中MyISAM对于某些工作负载(例如表扫描或高容量仅插入工作)表现略好,但默认选择应该是InnoDB,除非您可以证明 MyISAM更好。

InnoDB的优点除了通常提到的支持事务和外键之外还包括:

  • InnoDB比MyISAM更能抵抗表损坏。
  • 行级锁定。在MyISAM中,读者会阻塞写者,反之亦然。
  • 支持大型数据和索引缓冲池。MyISAM关键字缓冲区仅用于索引。
  • MyISAM已经停滞不前;所有未来的开发都将在InnoDB中进行。

另请参见我的回答:MyISAM versus InnoDB


我不需要FULLTEXT索引(因为我理解它们)。但是你认为Emil Vikström所说的是什么呢?他说我将不会在写入时使用InnoDB提供的好处?就像我说的,所有查询都将是读取查询,那么使用MyISAM不是更快吗?或者这会有那么大的差别吗? - stefmikhail
另外,您认为在我的情况下使用外键是否有益?还是因为我主要是读取而不是写入,所以外键不会产生太大的影响?或者它们是否相关? - stefmikhail
1
在我看来,速度和外键的问题是次要的;当你的服务器 或者 应用程序崩溃时,你不想让你的表被破坏。这就排除了 MyISAM。 - Bill Karwin
嗨@Bill Karwin,“在MyISAM中,读者会阻塞写者,反之亦然”-这是因为MyISAM使用表级锁定,也就是说,它锁定了整个表本身,对吧?谢谢。 - user19481364
@Daniel,一般来说是正确的,但还存在一些特殊情况。例如,在某些条件下,MyISAM可以允许并发会话插入到表的末尾。 - Bill Karwin

4

MyISAM无法让您执行mysql级别的检查。例如,如果您想将imgId在两个表中作为单个事务更新:

START TRANSACTION;
UPDATE primary_images SET imgId=2 WHERE imgId=1;
UPDATE secondary_images SET imgId=2 WHERE imgId=1;
COMMIT;

另一个缺点是完整性检查。使用InnoDB,您可以执行一些错误检查,例如避免在字段UNIQUE KEY imgDateimgDate)中出现重复值。相信我,这确实很方便,而且错误率更低。我的观点是,MyISAM适用于玩耍,而某些更为严肃的工作应该依赖于InnoDB。
希望能帮到您。

2

需要考虑以下几点:

  1. 你是否需要事务支持?
  2. 你是否会使用外键?
  3. 某个表上是否会有很多写操作?

如果对于以上任何一个问题的回答是“是”,那么你应该选择使用InnoDB。 否则,你需要回答以下问题:

  1. 你的表有多大?
  2. 它们包含多少行数据?
  3. 你的数据库引擎的负载情况如何?
  4. 你希望运行哪种类型的查询?

除非你的表非常大且你期望数据库承载大量负载,否则两种引擎都可以胜任。

我更喜欢MyISAM,因为它可以很好地扩展各种数据大小和负载。


很高兴再次见到你,回答我的另一个问题。为了回答你的问题:我需要学习更多关于事务支持的知识才能确定是否需要它。你能简要告诉我它是什么吗?我认为外键会有助于连接表格。表格不会被写入,除了我自己插入数据之外。因此,写入速度不是问题。我的表格永远不会超过1000行;可能永远不会超过500行。我将执行几个不同的查询。将它们包含在上面是否有帮助? - stefmikhail

-1
我想添加一些人们可能会受益的内容:我刚刚创建了一个InnoDB表(除了将排序规则更改为Unicode外,保留所有默认设置),并将其填充了约30万条记录(行)。 像SELECT COUNT(id) FROM table这样的查询会挂起直到给出错误消息,而不返回结果; 我已经用数据克隆了这个表到一个新的MyISAM表中,和其他大型SELECT查询一起,能够快速返回结果,并且一切正常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接