Mysql 替代多对多(连接)表以减小尺寸

Mysql 替代多对多(连接)表以减小尺寸,mysql,architecture,mariadb,many-to-many,Mysql,Architecture,Mariadb,Many To Many,我的项目有一个表,这是一个包含每个角色ID获得的成就ID的连接表。它工作得很好,但我关心的是它的大小:优化之前是6.1 GBs,优化之后是-4 GBs。这不是索引的大小 Data 3.1 GiB Index 901.5 MiB Overhead 2.5 MiB Effective 4.0 GiB Total 4.0 GiB 我现在看不到它对性能有任何影响,但我关心的是它的大小,特别是因为表经常更新,而且越来越大。即使它只有3列(由phpMyAdmin生成的定义):

我的项目有一个表,这是一个包含每个角色ID获得的成就ID的连接表。它工作得很好,但我关心的是它的大小:优化之前是6.1 GBs,优化之后是-4 GBs。这不是索引的大小

Data    3.1 GiB
Index   901.5   MiB
Overhead    2.5 MiB
Effective   4.0 GiB
Total   4.0 GiB
我现在看不到它对性能有任何影响,但我关心的是它的大小,特别是因为表经常更新,而且越来越大。即使它只有3列(由phpMyAdmin生成的定义):

创建表'ff\uu character\u acquisition'(
`characterid`int(10)UNSIGNED NOT NULL COMMENT'字符ID取自磁石URL(https://eu.finalfantasyxiv.com/lodestone/character/characterid/)',
`achievementid`smallint(5)UNSIGNED NOT NULL COMMENT`从磁石中获取的成就ID(https://eu.finalfantasyxiv.com/lodestone/character/characterid/achievement/detail/achievementid/)',
`时间`日期非空注释'根据磁石收到成果的日期'
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4\u unicode\u ci ROW\u FORMAT=COMPRESSED;
更改表格'ff\U字符\U成就`
使用BTREE添加主键(`characterid`、`achievementid`),
使用BTREE添加键“ach”(“achievementid”);
更改表格'ff\U字符\U成就`
在更新级联的删除级联上添加约束“char\u ach\u ach”外键(`achievementid`)引用“ff\u achievement`”(`achievementid`),
在更新级联的删除级联上添加约束`char\u ach\u char`外键(`characterid`)引用`ff\u character`(`characterid`);
犯罪
考虑到原始表是408KBs和707MBs,并且填充了大量其他数据(varchars和text-even),我希望连接表最多是2Gb,带有索引。是的,我可以删除date列,但是没有多大帮助:2.8而不是3.1GB。这对我来说似乎很奇怪,但这是MariaDB报告的值。
该表的目的是动态确定上所示的最稀有成就,并生成具有上所示成就的随机字符列表(例如)。我认为,就这一点而言,一张桌子4GB太多了。
因此,我的问题是,是否有某种方法可以存储相同的数据并方便地将其用于相同的目的,但占用的空间更小?
据我所知,可能可以将每个字符的成就ID存储为JSON字符串,但我肯定会失去约束(我更喜欢保留约束),并且我看不到一种易于使用的方法来搜索各个JSON,除非执行WHERE或全文搜索,这似乎不适合于此。

任何建议都将不胜感激。

请记住,将数据存储为JSON可能会使其变大,而不是变小

我通过将堆栈溢出的数据转储转换为JSON数据运行了一些测试,发现这导致数据大小增加了2-3倍。在这种情况下,整数比字符串更糟糕

请看我的演示文稿或。这也适用于MariaDB

行的大小应基于。四个字节表示INT,两个字节表示SMALLINT,三个字节表示DATE。正如你所知,有一点开销。我们称之为每行16字节。因此,要让它占据4GiB空间,必须有2.7亿行,对吗

这是一个公平的数据位,但它不是一个交易破坏者。在我的公司,我们有许多表,它们有超过10亿行,内容比几个整数大得多。如果桌子超过500吉布,我们开始有点担心。此时,备份或模式更改之类的操作变得太困难

可能有一些方法可以缩小这些行,比如使用SMALLINT而不是INT作为字符id。但是这些方法不可避免地会使数据的使用更加复杂

你必须扪心自问,这是否会有所不同。即使将数据类型的大小减半,很快就会累积两倍的行数,然后就会回到开始的位置


最后,您只需决定是否值得在存储和RAM中为该数据库投入足够的服务器容量。

请记住,存储数据时,JSON可能会使数据变大,而不是变小

我通过将堆栈溢出的数据转储转换为JSON数据运行了一些测试,发现这导致数据大小增加了2-3倍。在这种情况下,整数比字符串更糟糕

请看我的演示文稿或。这也适用于MariaDB

行的大小应基于。四个字节表示INT,两个字节表示SMALLINT,三个字节表示DATE。正如你所知,有一点开销。我们称之为每行16字节。因此,要让它占据4GiB空间,必须有2.7亿行,对吗

这是一个公平的数据位,但它不是一个交易破坏者。在我的公司,我们有许多表,它们有超过10亿行,内容比几个整数大得多。如果桌子超过500吉布,我们开始有点担心。此时,备份或模式更改之类的操作变得太困难

可能有一些方法可以缩小这些行,比如使用SMALLINT而不是INT作为字符id。但是这些方法不可避免地会使数据的使用更加复杂

你必须扪心自问,这是否会有所不同。即使将数据类型的大小减半,很快就会累积两倍的行数,然后就会回到开始的位置


最终,您只需决定是否值得在足够的服务器容量、存储和RAM方面投资该数据库。

大小分析

数据树和主键的3列占用了这么多:

  • 整数为4字节
  • SMALLINT为2字节
  • 日期为3字节
  • 总计(包括开销)约为40字节
因为单独的二级索引有两个