【问题标题】:MyISAM vs InnoDB for quick inserts and a composite unique keyMyISAM vs InnoDB 用于快速插入和复合唯一键
【发布时间】:2016-11-10 09:28:04
【问题描述】:

上下文:我正在创建一个多线程应用程序,它将非常频繁地插入/更新行。

最初我有下表:

#TABLE 1
CREATE TABLE `example` (
  `id` BIGINT(20) NOT NULL,
  `state` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`, `state`))
ENGINE = MyISAM;

然而,在做了一些研究之后,我发现 MySQL 对 MyISAM 表使用表级锁定,允许一次只允许一个会话更新这些表 (source)。不适合频繁更改表的多线程应用程序。

因此,建议我从复合主键切换到自动生成的主键,该主键具有唯一的 id/state 索引。这将允许快速插入,同时仍然强制执行 id/state 的唯一组合。

#TABLE 2
CREATE TABLE `example` (
  `key` BIGINT(20) NOT NULL,
  `id` BIGINT(20) NOT NULL,
  `state` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`key`),
  UNIQUE INDEX `ID_STATE` (`id` ASC, `state` ASC))
ENGINE = MyISAM;

然而,InnoDB 避免了表锁定,而是使用行级锁定 (source),所以我想切换到以下内容:

#TABLE 3
CREATE TABLE `example` (
  `key` BIGINT(20) NOT NULL,
  `id` BIGINT(20) NOT NULL,
  `state` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`key`),
  UNIQUE INDEX `ID_STATE` (`id` ASC, `state` ASC))
ENGINE = InnoDB;

但是在阅读了 InnoDB 之后,我发现 InnoDB 使用聚集索引来组织数据,而二级索引需要多次查找。一个用于二级索引,另一个用于主键 (source)。因此,我正在讨论切换到以下内容:

#TABLE 4
CREATE TABLE `example` (
  `id` BIGINT(20) NOT NULL,
  `state` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`id`, `state`))
ENGINE = InnoDB;

我想知道我的所有假设是否正确:

  1. MyISAM 表为 INSERTS、UPDATES 和 DELETES 锁定整个表,只允许一个会话一次更新这些表
  2. InnoDB 处理带有复合主键的 INSERTS 比 MyISAM 更快。这是因为 InnoDB 与 MyISAM 不同,它不会锁定整个表来扫描和保留新的主键。
  3. 使用 InnoDB 时,我应该创建复合主键而不是复合唯一索引,因为二级索引需要多次查找。
  4. 我应该使用表 4

【问题讨论】:

  • (2) 是一个不合逻辑的
  • 你说得对,我已经更新它以更好地阐明我的意思。

标签: mysql innodb myisam composite-primary-key


【解决方案1】:

1-是,2-是,3-是,4-是。

还有……

  • 你真的需要BIGINT吗? INT UNSIGNED 中的 40 亿个值还不够吗? (并节省一半的空间。)大概id 是其他表的PK?如果是这样,该表也需要更改。
  • state 可以标准化吗?还是变成了ENUM?再次节省空间。

第 3 项比提到的更糟糕,因为需要锁定两个唯一的键。

【讨论】:

  • 你能解释一下你所说的“比提到的更糟糕”是什么意思吗?您是说创建复合二级索引需要的不仅仅是两次查找吗?附言都是好点。我从没想过BIGINT(10) 是 100 亿,INT UNSIGNED 是 40 亿。
  • BIGINT是一个64位数字+/- 8 billion billion(10)什么都没有
猜你喜欢
  • 2011-10-17
  • 2011-11-05
  • 2011-07-25
  • 2012-05-15
  • 2012-03-01
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多