我有一张包含1699列的表格,当我尝试插入更多列时,
错误代码:1117。列太多
在此表中,我只有1000行。对我来说,最重要的是列数。桌子上有什么限制吗?我想创建2000列。那可能吗?
我有一张包含1699列的表格,当我尝试插入更多列时,
错误代码:1117。列太多
在此表中,我只有1000行。对我来说,最重要的是列数。桌子上有什么限制吗?我想创建2000列。那可能吗?
Answers:
为什么您需要创建一个甚至有20列的表,更不用说2000了?
授予的,非规范化的数据可以避免必须执行JOIN来检索数据的许多列。但是,如果列数超过10,则应该停下来思考在数据检索过程中可能发生的情况。
如果2000列表经过SELECT * FROM ... WHERE,您将在处理期间生成大型临时表,获取不需要的列,并创建许多情况,在这些情况下,通信包(max_allowed_packet)将在每次查询时都处于边缘。
在开发初期,我在1995年曾在一家公司工作,当时DB2是主要的RDBMS。该公司有一个包含270列,数十个索引的表,并且在检索数据时遇到性能问题。他们联系了IBM,并请顾问检查了他们系统的体系结构,包括一张整体表。该公司被告知:“如果您在未来两年内不对该表进行规范化,那么DB2将在执行Stage2处理的查询(任何需要对未索引列进行排序的查询)上失败。” 有人告诉一家价值数万亿美元的公司,以规范化270列表。2000列表还有多少呢?
在mysql方面,您必须通过设置与DB2 Stage2处理相当的选项来补偿这种不良设计。在这种情况下,这些选项是
如果您具有TB的RAM,则对这些设置进行Tweeking来弥补数十列(更不用说数百列)的存在了。
如果您使用InnoDB,此问题会成倍增加,因为您将不得不处理MVCC(多版本并发控制),试图通过事务隔离来保护每个SELECT,UPDATE和DELETE的大量列。
结论
没有替代品或创可贴可以弥补糟糕的设计。请为了您将来的理智,今天将这张桌子归一化!!!
我很难想象任何数据模型可以在正确规范化的表中合法包含2000列的地方。
我的猜测是,您可能正在执行某种“填补空白”的非规范化模式,实际上您是在一张表中存储所有不同种类的数据,而不是将数据分解为单独的表并建立关系,您有多个字段来记录给定行中存储的数据的“类型”,而您90%的字段为NULL。即使如此,还是要达到2000列... yikes。
解决您的问题的方法是重新考虑您的数据模型。如果要存储大量与给定记录关联的键/值数据,为什么不这样建模呢?就像是:
CREATE TABLE master (
id INT PRIMARY KEY AUTO_INCREMENT,
<fields that really do relate to the
master records on a 1-to-1 basis>
);
CREATE TABLE sensor_readings (
id INT PRIMARY KEY AUTO_INCREMENT,
master_id INT NOT NULL, -- The id of the record in the
-- master table this field belongs to
sensor_id INT NOT NULL,
value VARCHAR(255)
);
CREATE TABLE sensors (
id INT PRIMARY KEY AUTO_INCREMENT,
<fields relating to sensors>
);
然后,要获取与给定的“主”记录关联的所有传感器条目,只需输入即可SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>
。如果需要获取master
表中记录的数据以及该记录的所有传感器数据,则可以使用联接:
SELECT master.*,sensor_readings.sensor_id,sensor_readings.value
FROM master INNER JOIN sensor_readings on master.id=sensor_readings.master_id
WHERE master.id=<some ID>
如果需要每个传感器的详细信息,则可以进一步加入。
这是一个具有2000个传感器的测量系统
忽略所有关于标准化的喊话-您所要求的可能是明智的数据库设计(在理想的世界中)并且标准化得很好,这是非常不寻常的,而且正如其他地方指出的那样,RDBMS通常不是为这么多列而设计的。
尽管您没有达到MySQL的硬性限制,但链接中提到的其他因素之一可能是阻止您进一步发展的原因。
就像其他人建议的那样,您可以通过使用带有的子表来解决此限制id, sensor_id, sensor_value
,或更简单地说,您可以创建第二个表以仅包含不适合第一个表的列(并使用相同的PK)
MySQL 5.0列数限制(添加了重点):
每个表有4096列的硬限制,但是对于给定的表,有效最大值可能会更少。确切的限制取决于几个相互作用的因素。
每个表(与存储引擎无关)的最大行大小为65,535字节。存储引擎可能会对此限制施加其他限制,从而减小有效的最大行大小。
最大行大小限制了列数(可能还有大小),因为所有列的总长度不能超过该大小。
...
各个存储引擎可能会施加其他限制表数的限制。例子:
- InnoDB最多允许1000列。
首先是更多的燃烧,然后是一个真正的解决方案...
我大体上同意已经向您扑来的火焰。
我不同意键值标准化。查询最终变得可怕。性能更差。
避免当前问题(列数限制)的一种“简单”方法是“垂直分区”数据。假设有5个表,每个表有400列。它们都将具有相同的主键,除了一个可能是AUTO_INCREMENT。
也许最好决定最重要的十二个字段,然后将它们放入“主”表中。然后以某种逻辑方式将传感器分组,然后将它们放入几个并行表中。使用正确的分组,您可能不必一直都联接所有表。
您是否在索引任何值?您需要搜索它们吗?您可能在日期时间搜索?
如果您需要索引很多列-平底锅。
如果您需要索引一些-将它们放入“主表”中。
这是真正的解决方案(如果适用)...
如果您不需要索引大量的传感器,则不要创建列!是的,你听到了我的声音。取而代之的是,将它们收集到JSON中,压缩JSON,并将其存储到BLOB字段中。您将节省大量空间;您将只有一个表,没有列限制问题;等等。您的应用程序将解压缩,然后使用JSON作为结构。你猜怎么了?您可以拥有结构-您可以将传感器分组为数组,多级内容等,就像您的应用程序希望的那样。另一个“功能”-它是开放式的。如果添加更多传感器,则无需更改表。JSON(如果灵活)的话。
(压缩是可选的;如果您的数据集很大,它将有助于磁盘空间,从而提高整体性能。)
JSON
避免“列太多”;索引选定的列有助于提高性能。
我认为这是大数据世界中的一种可能方案,在这种情况下,您可能不会执行传统的select *类型的查询。我们在客户级别的预测建模世界中处理此问题,我们在数千个维度上对客户进行建模(所有维度的值为0或1)。当您在同一行中同时具有风险因素和同一行中的结果标记时,这种存储方式使下游模型构建活动等更加容易。这可以从具有父子结构的存储立场上标准化,但是下游的预测模型将需要将其转换回平面模式。我们使用redshift进行列存储,因此在加载数据时,您的1000+列实际上以列格式存储...
此设计存在时间和地点。绝对。规范化不是解决每个问题的方法。