更新行时是否始终触发生成列的计算?

时间:2017-03-15 19:23:25

标签: mysql calculated-columns

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

我的简单问题是:

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

你能给我一些参考资料(链接)来证明你的答案。

由于

修改

我已经阅读了@Barmar建议的MySQL official documentation

  

STORED:插入行时评估和存储列值   或更新。

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

2 个答案:

答案 0 :(得分:0)

来自MySQL documentation

  
      
  • 已存储:插入或更新行时会评估和存储列值。
  •   

这清楚地表明,当您更新行上的其他列时会触发计算。

答案 1 :(得分:0)

对于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;

第一个update将触发对依赖于gencolx生成的列x的评估:

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

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

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不会检查该值是否实际已被更改,只要该列是目标列。因此,实际上保持update值不变的最后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

如果您使用例如同样的方式将会发生update test set x = x,不会改变任何行。

update_generated_read_fieldsupdate_generated_write_fields是评估生成字段表达式的相关函数。您还可以看到gencolconst的常量表达式未在更新中进行评估。

同样不幸的是(并且只是作为旁注),该表上触发器的纯粹存在将导致对update_generated_write_fields的第二次调用以及对所生成的列的第二次评估(如果它们已在第一次更新)时间 - 如果它是例如并不重要一个insert触发器,你正在做一个update,任何触发器的纯粹存在就足够了。