【问题标题】:Create new column every hour with unique name每小时创建一个具有唯一名称的新列
【发布时间】:2021-05-31 04:14:08
【问题描述】:

我正在使用 MariaDB 5.2,需要每小时创建一个新列,该列需要一个唯一的名称。我有如下代码,以时间为例:

CREATE EVENT IF NOT EXISTS calculation
ON SCHEDULE EVERY 1 HOUR STARTS '2021-01-01 00:00:00'
DO
SET @stmt := CONCAT('ALTER TABLE myTable ADD myColumn_', CURDATE() + 0, ' SMALLINT(5);');
PREPARE stmt from @stmt;
EXECUTE stmt;

不幸的是@stmt 没有重新计算。它在第一次运行时计算一次。然后在之后的每次迭代中,它将继续使用与以前相同的值。如何让它重新计算?我正在使用 MariaDB 5.2。

还值得一提的是,如果我只是运行:

SET @stmt := CONCAT('ALTER TABLE myTable ADD myColumn_', CURDATE() + 0, ' SMALLINT(5);');
PREPARE stmt from @stmt;
EXECUTE stmt;

.. 然后它第一次工作没有错误(变量仍然不会为以后的迭代重新计算)。但是,一旦我添加了 CREATE EVENT 代码,我就会收到一个错误:“SQL 错误(1064):您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册以获取正确的语法以在附近使用'NULL' 在第 1 行。”我运行它时没有“计算”事件,所以我不明白第一行怎么可能是空的。

【问题讨论】:

  • 这是一个非常难以置信的要求。要么规范化你的模式,要么不需要 RDBMS。

标签: mysql variables events mariadb scheduler


【解决方案1】:

CURDATE() 只返回日期,而不是日期时间。也就是说,它只有年月日部分。

例子:

mysql> select curdate();
+------------+
| curdate()  |
+------------+
| 2021-05-30 |
+------------+

我可以每天运行任意次数,它总是返回相同的值,因为日期不会改变(直到你过了午夜)。

我不得不评论说,每小时添加一列是一个非常糟糕的主意。几天之内,您将制作一个包含数百列的表格。表中的列数存在实际限制。

此外,如果表增长到几百万行,您还必须考虑添加一列可能需要一个多小时。如果执行 ALTER TABLE 需要一个多小时,并且您每小时运行一次事件,您打算如何工作?

你真的需要完全放弃这个想法,重新思考你存储数据的方式。

例如,每小时添加一个,而不是一列。

【讨论】:

  • 哦,好的。但是如果我最终得到 700 万行呢?因为情况是这样的:假设我有 10,000 名成员,我每小时从他们那里收集一个数据点,稍后用于创建图表。有一个表格可以实时计算这些数据点。然后每隔一小时我就会从该表中复制一列并将其粘贴到另一个表中。这将是添加列的地方。我曾考虑将其添加为新行,但这意味着我不会说 10,000 行,最多 744 列,而是大约 700 万行
  • .. 每个会员号将重复约 700 次,每个日期将重复约 10,000 次。换句话说,我的桌子变大了 3 倍,其中三分之二只是重复的
  • 我使用具有 十亿 行的 MySQL 表。 MariaDB 的可扩展性在这方面应该类似于 MySQL。我创建了 700 万行表来运行 测试
  • 真的吗?那么,所有这些重复项都可以吗?只添加列不是更好吗?
  • 这取决于你。我不能说它是从不首选的解决方案,因为每个规则都有一些例外。但我更喜欢不需要我每小时 ALTER TABLE 的解决方案。
【解决方案2】:

您似乎混淆了表格和代码。

一个表应该有一个或多或少固定的结构和固定的列数。由于您似乎正在处理某种形式的时间序列数据,因此将您的表格安排为您的密钥的一部分是时间戳而密钥的另一部分是您的项目的密钥的形式会更聪明。

最简单的方法是以著名的旧 unix 格式生成时间戳,即自纪元以来的秒数,对于 unix 而言,意味着自 1970 年以来的秒数。让客户端从中计算日期和时间。这也可以确保您使用 UTC 存储时区没有问题。

这样做使您能够根据键值选择数据,并且可以重复使用您的查询。

根据您最初的想法,您需要更改每个范围的代码。这将很难维护,并且由于每小时发生的表锁定,它也不会扩展。这个问题也将很快得到解决,因为您将达到最大列数。

【讨论】:

  • 我喜欢这个主意。但是,即使我确实将数据添加为行,我仍然需要以某种方式将日期/时间放入单元格/字段中(作为与成员编号的串联或单独在另一列中)。如果我在像上面这样的事件中写下 CURRENT_TIMESTAMP() 等内容,它会给我一个错误,说该值已经存在,即它计算一次 CURRENT_TIMESTAMP(),然后在每个时间间隔后分配它。所以我仍然遇到无法强制它重新计算每次迭代的时间的问题。
  • 也许一个允许我将每个数据点添加为数组中的元素的数据库会更好?然后我可以将它添加到末尾并轻松删除第一个元素。我不知道这是否是一个好的决定,因为我怀疑某种 javascript 对象中的数组会非常慢。
  • 或者也许我可以在我的网络服务器中创建一个算法来生成时间戳并将其分配给数据库?不过,我必须从我的网络应用程序运行事件调度程序,我不知道这是否是一个坏方法?
  • 让它变得简单,只需使用自 1970 年以来的秒数数据。日期/时间的格式是客户的事情。忘记改变应该插入的表。
猜你喜欢
  • 2014-07-27
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
  • 2016-11-16
相关资源
最近更新 更多