错误代码 1117 列太多;MySQL 对表的列限制

OHL*_*ÁLÁ 39 mysql table

我有一个包含 1699 列的表,当我尝试插入更多列时,我得到了,

错误代码:1117。列太多

在这个表中,我只有 1000 行。对我来说,最重要的是列数。桌子上有什么限制吗?我想创建 2000 列。那可能吗?

Rol*_*DBA 39

为什么你需要创建一个甚至 20 列的表,更不用说 2000 了???

当然,非规范化数据可以防止必须执行 JOIN 来检索多列数据。但是,如果您有超过 10 列,您应该停下来想想在数据检索期间会发生什么。

如果 2000 列表经历 SELECT * FROM ... WHERE,您将在处理过程中生成大型临时表,获取不必要的列,并创建许多场景,其中通信数据包 ( max_allowed_pa​​cket ) 在每次查询时都会被推到边缘。

在我早期作为开发人员的时候,我于 1995 年在一家公司工作,当时 DB2 是主要的 RDBMS。该公司有一个包含 270 列和数十个索引的表,并且在检索数据时存在性能问题。他们联系了 IBM 并让顾问查看了他们系统的架构,包括这张单片表。该公司被告知“如果您在接下来的 2 年内不规范化这个表,DB2 将在执行 Stage2 处理的查询(任何需要对非索引列进行排序的查询)上失败。” 这被告知一家价值数万亿美元的公司,以规范一个 270 列的表。2000 列表更是如此。

就 mysql 而言,您必须通过设置与 DB2 Stage2 Processing 相当的选项来弥补这种糟糕的设计。在这种情况下,这些选项将是

如果您有 TB 的 RAM,则调整这些设置以弥补数十个(更不用说数百个)列的存在效果很好。

如果您使用 InnoDB,这个问题会成倍增加,因为您将不得不处理MVCC(多版本并发控制),试图通过事务隔离来保护每个 SELECT、UPDATE 和 DELETE 的大量列。

结论

没有任何替代品或创可贴可以弥补糟糕的设计。请为了您将来的理智起见,今天将该表正常化!!!


小智 25

我无法想象数据模型可以在正确规范化的表中合法包含 2000 列的任何内容。

我的猜测是您可能正在执行某种“填空”非规范化模式,您实际上将所有不同类型的数据存储在一个表中,而不是将数据分解为单独的表并建立关系,您有各种字段记录给定行中存储的数据“类型”,并且 90% 的字段为 NULL。尽管如此,想要达到 2000 列......哎呀。

解决您的问题的方法是重新考虑您的数据模型。如果您要存储大量与给定记录关联的键/值数据,为什么不以这种方式对其进行建模?就像是:

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>
);
Run Code Online (Sandbox Code Playgroud)

然后要获取与给定“主”记录关联的所有传感器条目,您只需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>
Run Code Online (Sandbox Code Playgroud)

如果您需要每个传感器的详细信息,然后进一步加入。


Jac*_*las 20

这是一个带有 2000 个传感器的测量系统

忽略所有关于规范化的评论 - 您所要求的可能是明智的数据库设计(在理想世界中)并且完全规范化,这是非常不寻常的,正如其他地方所指出的,RDBMS 通常根本不是为这么多列而设计的.

虽然您没有达到 MySQL 的硬限制,但链接中提到的其他因素之一可能会阻止您达到更高的水平。

正如其他人建议的那样,您可以通过使用子表来解决此限制id, sensor_id, sensor_value,或者更简单地说,您可以创建第二个表以仅包含第一个不适合的列(并使用相同的 PK)

  • @a_horse - 您正在做出我怀疑是否有效的假设。很有可能传感器的数量基本上是固定的,所有的都是同时读取的,并且每次都返回数据。在这种情况下,每个传感器一列不是“错误”,只是考虑到数据库的限制是不切实际的。我喜欢假设提问者不是白痴,除非得到证明,而且 iUngi 面对 SF 人群非常无益的回答,他们做出了有尊严的回应。 (11认同)
  • 使用子表不是“解决方法”。为每个传感器设置一列简直就是糟糕(错误)的设计。这就像在 HR 系统中为每个员工设置一列,或者在管理汽车模型的数据库中为每个汽车制造商设置一列。 (3认同)
  • @Jack Douglas:即使您的所有这些假设都是正确的(我非常怀疑),从长远来看,将每个传感器值存储在自己的列中也会引起麻烦。诸如“昨天和今天之间传感器 10 到 50 和 25 到 100 的平均值是多少”之类的查询呢?或“上周一哪个传感器的读数最高?”。尝试使用 2000 列为此编写查询。从长远来看,使用规范化表可以解决比现在 2000 列解决方案更多的问题。 (2认同)
  • 当然,如果传感器存储相关值 - 我假设它们是不相关的(例如,它们都在测量不同种类的事物,而不是在不同位置基本上相同的事物)。您可能会怀疑这一点,但只有 OP 才能确定——这在医学或科学领域并非不可能。 (2认同)

小智 16

MySQL 5.0 列数限制(强调):

每个表有 4096 列的硬限制,但给定表的有效最大值可能更少。确切的限制取决于几个相互作用的因素。

  • 每个表(无论存储引擎如何)的最大行大小为 65,535 字节。存储引擎可能会对此限制设置额外的约束,从而减少有效的最大行大小。

    最大行大小限制了列的数量(可能还有大小),因为所有列的总长度不能超过此大小。

...

单个存储引擎可能会施加额外的限制来限制表列数。例子:

  • InnoDB 最多允许 1000 列。


Ric*_*mes 9

首先是更多的火焰,然后是一个真正的解决方案......

我大多同意已经向你投掷的火焰。

我不同意键值规范化。查询结果很糟糕;性能更差。

避免直接问题(列数限制)的一种“简单”方法是“垂直分区”数据。假设有 5 个表,每个表有 400 列。它们都具有相同的主键,除了一个可能是 AUTO_INCREMENT。

也许更好的是决定十几个最重要的字段,将它们放入“主”表中。然后以某种逻辑方式将传感器分组并将它们放入多个并行表中。通过适当的分组,您可能不必一直连接所有表。

您是否正在索引任何值?你需要搜索它们吗?可能你在日期时间搜索?

如果您需要索引很多列 - punt。

如果您需要索引一些 - 将它们放入“主表”中。

这是真正的解决方案(如果适用)...

如果您不需要索引大量传感器,则不要创建列!是的,你听到了。相反,将它们收集到 JSON 中,压缩 JSON,将其存储到 BLOB 字段中。您将节省大量空间;您将只有一张表,没有列限制问题;等等。您的应用程序将解压缩,然后使用 JSON 作为结构。你猜怎么着?您可以拥有结构——您可以将传感器分组为数组、多级内容等,就像您的应用程序所希望的那样。另一个“功能”——它是开放式的。如果添加更多传感器,则无需更改表。JSON 如果那样灵活的话。

(压缩是可选的;如果您的数据集很大,它将有助于磁盘空间,从而提高整体性能。)

  • 这是实际的最佳答案。可以评论说,也许他应该研究没有那么多专栏,但是对于接受的答案是“不要那样做”并不能回答问题。即使这个人真的不需要那么多专栏,也许其他人发现这个 Q 确实需要那么多,并且需要一个真正的答案。 (2认同)