优化存储 Space:许多行和列具有相同的值
Optimising Storage Space: Many rows & columns with the same values
我有多个 table,每个存储 1 亿多行数据。对于任何给定的列,只有几个可能的唯一值,因此许多列具有重复值。
当我最初设计模式时,我决定使用辅助链接 tables 来存储实际值,以优化数据库所需的存储 space。
例如:
而不是像这样存储用户代理的 table:
- id(整数)
- user_agent (varchar)
我正在使用 2 个 table,如下所示:
Table 1
- id(整数)
- user_agent_id (int)
Table 2
- id(整数)
- user_agent (varchar)
当有 1 亿多行时,我发现此模式节省了大量存储空间 space 因为只有几百个可能的用户代理,而这些字符串构成了大部分数据。
我运行要解决的问题是:
使用链接的 tables 在许多不同的 tables 中存储如此多的字符串数据会增加开发方面的开销,并且由于需要连接,所以查询数据的速度会慢得多。
我的问题是:
有没有一种方法可以将所有列放在一个 table 中,并强制 mysql 不复制具有重复值的列所需的存储空间?我开始认为必须有一些内置的方法来处理这种情况,但我在研究中没有发现任何东西。
如果我有 10 个唯一值的列和 1 亿多行,为什么 MySQL 将每个值(包括重复项)都保存在存储中而不只是对唯一值的引用?
谢谢!
If I have 10 unique values for a column and 100 million+ rows why would MySQL save every value including the duplicates fully in storage rather than just a reference to the unique values?
MySQL 无法预测您将始终只有 10 个唯一值。您告诉它存储 VARCHAR,因此它必须假设您要存储 any 字符串。如果要用一个数字来枚举所有可能的字符串,那么这个数字实际上需要比字符串本身长。
要解决您的问题,您可以使用引用查找的数字 ID 来优化存储 table。由于查找中不同字符串的数量 table 有数百个,因此您至少需要使用一个 SMALLINT(16 位整数)。您不需要使用与 INT(32 位整数)一样大的数字。
在查找 table 中,将该 id 声明为主键。这应该使连接尽可能快。
如果您想直接进行反向联接 — 为特定用户代理查询 100M 行 table,然后在您的 large table 中索引 smallint 列。这将需要更多存储 space 来创建索引,因此请确保在创建索引之前每个 table 中都需要该类型的查询。
另一个建议:获取更大的存储空间。
经过一些挖掘和测试,我发现似乎是最好的解决方案:使用 varchar 列本身创建索引和外键约束,而不是使用 ID 字段。
INNODB 支持带有 varchar 和 int 的外键:https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
这是一个例子:
user_agents table:
- user_agent(varchar,和唯一索引)
user_requests table:
- id
- user_agent(varchar,外键约束引用user_agentstableuser_agent列)
- other_columns 等...
我发现当使用 varchar 本身作为外键时 mysql 会自行优化存储,并且只会为磁盘上的每个唯一 user_agent 存储 1 个 varchar。添加 1000 万+ user_requests 行向磁盘添加的信息非常少。
我还注意到它比在 link table 中使用 ID 更有效,就像在原始 post 中一样。 MySQL 似乎在幕后做了一些魔术,并且可以 link 磁盘上信息很少的列。它的存储效率至少比存储所有字符串本身高 100 倍,比 linking 使用 ID 的效率高几倍。您还可以获得外键和级联的所有好处。在任一方向查询列都不需要连接,因此查询也非常快!
干杯!
我有多个 table,每个存储 1 亿多行数据。对于任何给定的列,只有几个可能的唯一值,因此许多列具有重复值。
当我最初设计模式时,我决定使用辅助链接 tables 来存储实际值,以优化数据库所需的存储 space。
例如:
而不是像这样存储用户代理的 table:
- id(整数)
- user_agent (varchar)
我正在使用 2 个 table,如下所示:
Table 1
- id(整数)
- user_agent_id (int)
Table 2
- id(整数)
- user_agent (varchar)
当有 1 亿多行时,我发现此模式节省了大量存储空间 space 因为只有几百个可能的用户代理,而这些字符串构成了大部分数据。
我运行要解决的问题是: 使用链接的 tables 在许多不同的 tables 中存储如此多的字符串数据会增加开发方面的开销,并且由于需要连接,所以查询数据的速度会慢得多。
我的问题是: 有没有一种方法可以将所有列放在一个 table 中,并强制 mysql 不复制具有重复值的列所需的存储空间?我开始认为必须有一些内置的方法来处理这种情况,但我在研究中没有发现任何东西。
如果我有 10 个唯一值的列和 1 亿多行,为什么 MySQL 将每个值(包括重复项)都保存在存储中而不只是对唯一值的引用?
谢谢!
If I have 10 unique values for a column and 100 million+ rows why would MySQL save every value including the duplicates fully in storage rather than just a reference to the unique values?
MySQL 无法预测您将始终只有 10 个唯一值。您告诉它存储 VARCHAR,因此它必须假设您要存储 any 字符串。如果要用一个数字来枚举所有可能的字符串,那么这个数字实际上需要比字符串本身长。
要解决您的问题,您可以使用引用查找的数字 ID 来优化存储 table。由于查找中不同字符串的数量 table 有数百个,因此您至少需要使用一个 SMALLINT(16 位整数)。您不需要使用与 INT(32 位整数)一样大的数字。
在查找 table 中,将该 id 声明为主键。这应该使连接尽可能快。
如果您想直接进行反向联接 — 为特定用户代理查询 100M 行 table,然后在您的 large table 中索引 smallint 列。这将需要更多存储 space 来创建索引,因此请确保在创建索引之前每个 table 中都需要该类型的查询。
另一个建议:获取更大的存储空间。
经过一些挖掘和测试,我发现似乎是最好的解决方案:使用 varchar 列本身创建索引和外键约束,而不是使用 ID 字段。
INNODB 支持带有 varchar 和 int 的外键:https://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html
这是一个例子:
user_agents table:
- user_agent(varchar,和唯一索引)
user_requests table:
- id
- user_agent(varchar,外键约束引用user_agentstableuser_agent列)
- other_columns 等...
我发现当使用 varchar 本身作为外键时 mysql 会自行优化存储,并且只会为磁盘上的每个唯一 user_agent 存储 1 个 varchar。添加 1000 万+ user_requests 行向磁盘添加的信息非常少。
我还注意到它比在 link table 中使用 ID 更有效,就像在原始 post 中一样。 MySQL 似乎在幕后做了一些魔术,并且可以 link 磁盘上信息很少的列。它的存储效率至少比存储所有字符串本身高 100 倍,比 linking 使用 ID 的效率高几倍。您还可以获得外键和级联的所有好处。在任一方向查询列都不需要连接,因此查询也非常快!
干杯!