mysql - 更新行时是否总是触发生成列的计算?

标签 mysql calculated-columns

我在 MySQL 5.7 中有一个包含几十列的表。其中之一是生成列(存储的,而不是虚拟的),它使用一个大表达式来计算基于列 A、B 和 C 的值,所以我猜当插入新行时,MySQL 需要一点额外的时间来计算值或更新。

我的简单问题是:

当我更新一行上的其他列(F、G 等)时,计算也会触发吗?

您能给我发送一些引用资料(链接)来证明您的答案吗?

谢谢

编辑:

我已经读过MySQL official documentation @Barmar 建议:

STORED: Column values are evaluated and stored when rows are inserted or updated.

正如您所看到的,它说插入或更新,但我猜更新实际上意味着:如果相关列已更新因为我认为MySQL足够聪明,如果这些列没有更新,就不会执行计算。这实际上是我想确认的假设。

最佳答案

对于 update 语句,仅当指定引用的列被修改时,MySQL 才会重新评估生成的存储列(注意:不一定更改,只是在列表中要修改的列数)。您可以验证这一点,例如带有调试版本。

create table test (
  id int auto_increment primary key, 
  x int, 
  y int, 
  gencolx int as (2*x) stored, 
  gencolconst int as (2) stored
);

insert into test (x, y) values (2, 2);
update test set x = 4;
update test set y = 5;
update test set x = 4;

第一次更新将触发对依赖于x的生​​成列gencolx的评估:

THD::decide_logging_format: info: query: update test set x = 4
update_generated_read_fields: info: field 'gencolx' - skipped
update_generated_read_fields: info: field 'gencolconst' - skipped
update_generated_write_fields: info: field 'gencolx' - updated
update_generated_write_fields: info: field 'gencolconst' - skipped

第二个更新不会更新任何生成列中使用的列,因此不会重新计算它们:

THD::decide_logging_format: info: query: update test set y = 5
update_generated_read_fields: info: field 'gencolx' - skipped
update_generated_read_fields: info: field 'gencolconst' - skipped
update_generated_write_fields: info: field 'gencolx' - skipped
update_generated_write_fields: info: field 'gencolconst' - skipped

不幸的是,MySQL 不会检查该值是否实际上已更改,只是该列是否为目标列。因此,实际上使 x 的值保持不变的最后一个 更新 仍将导致对依赖生成列进行评估,因为列 x > 是要在 update 语句中修改的列:

THD::decide_logging_format: info: query: update test set x = 4
update_generated_read_fields: info: field 'gencolx' - skipped
update_generated_read_fields: info: field 'gencolconst' - skipped
update_generated_write_fields: info: field 'gencolx' - updated
update_generated_write_fields: info: field 'gencolconst' - skipped
mysql_update: info: 0 records updated

如果您使用例如,也会发生同样的情况更新测试集 x = x,这不会更改任何行。

update_ generated_read_fieldsupdate_ generated_write_fields 是评估生成字段表达式的相关函数。您还可以看到 gencolconst 的常量表达式在更新中未计算。

同样不幸的是(正如旁注),该表上触发器的纯粹存在将导致对 update_generate_write_fields 的第二次调用,并对生成的列进行第二次评估(如果它们已被执行)第一次更新 - 是否是例如并不重要一个insert触发器,并且您正在执行一个update,任何触发器的纯粹存在就足够了。

关于mysql - 更新行时是否总是触发生成列的计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42818910/

相关文章:

php - Service unavailable 服务暂时不可用错误

mysql - 在 Laravel eloquent 中执行 "findManyOrCreate"所需资源最少的是什么?

c# - 从 MsSQL 传输到 MySQL 错误

if-statement - 展开电源查询中上方或下方所有类似列的值

rowMeans 如果列名是数字

mysql - 如何将 SQL 查询结果存储在表列中

mysql - SQL查询使用EXISTS选择满足条件的记录

mysql - 将 MySQL 用于自动完成字段

r - 计算均值时处理 NaN

awk - 使用 awk 计算从第 2 列派生的第 1 列的百分比并将其添加到第 3 列