Mysql table 的更好结构以获得 Mysql 性能

Better structure of Mysql table for Mysql performance

我在 Mysql 性能方面评估更好的 table 结构,假设我有下面提到的 2 个 table 结构

Reference table structure 1 :

CREATE TABLE `references_1` (
  `id` bigint(30) NOT NULL AUTO_INCREMENT,
  `entity_id` int(11) DEFAULT NULL,
  `reference_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `reference_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_on_entity_id` (`entity_id`),
  KEY `index_mappings_on_reference_id_and_reference_type` (`reference_id`,`reference_type`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

mysql> select * from references_1 where entity_id = 1;
+----+-----------+--------------+------------------+
| id | entity_id | reference_id | reference_type   |
+----+-----------+--------------+------------------+
|  1 |         1 | 25636826     | reference_type_1 |
|  2 |         1 | 2563XCDA6826 | reference_type_2 |
|  3 |         1 | 16992176     | reference_type_3 |
|  4 |         1 | 4521882      | reference_type_4 |
+----+-----------+--------------+------------------+
4 rows in set (0.00 sec)


Reference table structure 2 :


CREATE TABLE `references_2` (
  `id` bigint(30) NOT NULL AUTO_INCREMENT,
  `entity_id` int(11) DEFAULT NULL,
  `reference_type_1` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `reference_type_2` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `reference_type_3` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `reference_type_4` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_on_entity_id` (`entity_id`),
  KEY `index_on_reference_type_1` (`reference_type_1`),
  KEY `index_on_reference_type_2` (`reference_type_2`),
  KEY `index_on_reference_type_3` (`reference_type_3`),
  KEY `index_on_reference_type_4` (`reference_type_4`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

mysql> select * from references_2 where entity_id = 1;
+----+-----------+------------------+------------------+------------------+------------------+
| id | entity_id | reference_type_1 | reference_type_2 | reference_type_3 | reference_type_4 |
+----+-----------+------------------+------------------+------------------+------------------+
|  2 |         1 | 25636826         | 2563XCDA6826     | 16992176         | 4521882          |
+----+-----------+------------------+------------------+------------------+------------------+

       

请分享您的观点,提前致谢。

版本:

查询:

select * 来自 references_1 其中 entity_id = 1; //假设 entity_id 有索引。

INSERT(写操作)性能如何 w.r.t 两个 table 结构?

MySQL 的 InnoDB 存储引擎(默认)将行存储在固定大小的页面中(默认为每页 16KB)。一定数量的行适合单个页面,具体取决于行大小。 IE。如果行较小,每页适合更多行。

页是从存储器加载到 RAM 的数据增量。因此,如果您的查询引用该页面上的一行,则整个页面都会加载到 RAM 中,然后同一页面上的所有行都可以更快地访问。

不会拆分单个行。它将存储在同一页中(除了非常长的 varchar 或 text/blob 列,它们可以扩展到其他页)。

假设相同 entity_id 的行可能组合在一起,那么您的两个 table 设计之间的存储和性能差异确实非常接近。的确,在第一个设计中,您有额外的行,因此会有额外的 identity_id 实例。但这些只是一个 bigint 和一个 int,所以开销不大。其他列将使用相同的存储空间。

其他注意事项:

您是否期望将引用类型扩展到 5 种或更高?第二种设计要求您使用 ALTER TABLE.

添加一列

引用类型需要 varchar 吗?您可以将它编码为 tinyint 或 ENUM 吗?这将节省 space.

另一方面,使用您的第二个设计可以节省更多 space,因为引用类型只是元数据的一部分。因此他们只取 space 一次,而不是每一行。

考虑 references_1 的这种变化:

CREATE TABLE `references_3` (
  `entity_id` int(11) DEFAULT NULL,
  `reference_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `reference_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (entity_id, reference_type),
  KEY `id_type` (`reference_id`,`reference_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

备注:

  • 我更改了 PK,假设该对是唯一的。
  • id 是否被任何其他 table 引用?
  • 我支持 Bill 关于 ENUM、存储 space、第 5 类型等的评论
  • 请参阅“pivot-table”了解如何将 4 行显示为 1 行。