Del*_*lmo 3 mysql calculated-columns
我在 MySQL 5.7 中有一个包含几十列的表。其中之一是生成列(存储的,而不是虚拟的),它使用一个大表达式来计算基于列 A、B 和 C 的值,所以我猜当插入新行时,MySQL 需要一点额外的时间来计算值或更新。
我的简单问题是:
当我更新一行上的其他列(F、G 等)时,是否也会触发计算?
您能给我发送一些参考资料(链接)来证明您的答案吗?
谢谢
编辑:
我已经阅读了@Barmar建议的MySQL官方文档:
存储:插入或更新行时计算并存储列值。
正如你所看到的,它说插入或更新,但我猜更新实际上意味着:如果相关列被更新,因为我认为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;
Run Code Online (Sandbox Code Playgroud)
第一个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
Run Code Online (Sandbox Code Playgroud)
第二个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
Run Code Online (Sandbox Code Playgroud)
不幸的是,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
Run Code Online (Sandbox Code Playgroud)
如果您使用 eg ,也会发生同样的情况update test set x = x,这不会更改任何行。
update_generated_read_fields和update_generated_write_fields是评估生成字段的表达式的相关函数。gencolconst您还可以看到,更新中未计算常量表达式。
另外不幸的是(正如旁注),该表上触发器的纯粹存在将导致对update_generated_write_fields生成的列的第二次调用和第二次评估(如果它们已第一次更新) - 如果例如,它是一个insert触发器,而您正在执行一个update,任何触发器的纯粹存在就足够了。