上下文:我正在创建一个多线程应用程序,该应用程序将非常频繁地插入/更新行。
最初我有下表:
#TABLE 1
CREATE TABLE `example` (
`id` BIGINT(20) NOT NULL,
`state` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`, `state`))
ENGINE = MyISAM;
但是,在进行了一些研究之后,我发现MySQL对MyISAM表使用表级锁定,一次只允许一个会话更新这些表(来源)。不适合频繁更改表的多线程应用程序。
因此,有人建议我从复合主键切换到自动生成的主键,该主键具有 id/state 的唯一索引。这将允许快速插入,同时仍然强制执行 id/状态的唯一组合。
#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 避免了表锁,而是使用行级锁定(源),因此我想切换到以下内容:
#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使用聚簇索引组织数据,二级索引需要多次查找。一个用于二级索引,另一个用于主键(源)。因此,我正在讨论切换到以下内容:
#TABLE 4
CREATE TABLE `example` (
`id` BIGINT(20) NOT NULL,
`state` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`, `state`))
ENGINE = InnoDB;
我想知道我所有的假设是否正确:
- MyISAM表锁定整个表以进行插入,更新和删除,一次只允许一个会话更新这些表
- InnoDB处理具有复合主键的插入比MyISAM更快。这是因为与MyISAM不同,InnoDB不会锁定整个表以扫描和保留新的主键。
- 使用 InnoDB 时,我应该创建一个复合主键而不是复合唯一索引,因为二级索引需要多次查找。
- 我应该使用表 4
1-是, 2-是, 3-是, 4-是.
也。。。
- 你真的需要
BIGINT
吗? 40亿个价值INT UNSIGNED
还不够吗? (并节省一半的空间。 大概其他表的PKid
? 如果是这样,该表也需要更改。 state
可以规范化吗? 还是变成了ENUM
? 再次节省空间。
第 3 项比提到的更糟糕,因为需要锁定两个唯一键。