更新行时是否总是触发生成列的计算?
Is the computation of generated column triggered always when update a row?
我在 MySQL 5.7 中有一个 table,有几十个列。其中之一是生成的列(存储的,而不是虚拟的),它使用一个大的表达式来计算基于列 A、B 和 C 的值,所以我猜 MySQL 需要一点额外的时间来计算值插入或更新了新行。
我的简单问题是:
当我更新一行中的其他列(F、G 等)时,是否也触发了计算?
你能给我一些参考资料(链接)来证明你的答案吗?
谢谢
编辑:
我已经阅读了@Barmar 建议的 MySQL official documentation:
STORED: Column values are evaluated and stored when rows are inserted
or updated.
如您所见,它说 inserted 或 updated 但我猜 updated实际上意味着:if related columns are updated 因为我认为 MySQL 足够聪明,如果这些列没有更新则不会执行计算。这其实就是我想确认的假设。
- STORED: Column values are evaluated and stored when rows are inserted or updated.
这清楚地表明,当您更新行中的其他列时会触发计算。
对于 update
语句,MySQL 将仅在指定要修改引用的列时重新评估生成的存储列(注意:不一定 changed,就在要修改的列列表中)。您可以验证这一点,例如使用调试版本。
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_fields
和 update_generated_write_fields
是评估生成字段表达式的相关函数。您还可以看到 gencolconst
的常量表达式未在更新中求值。
同样不幸的是(作为旁注),table 上触发器的纯粹存在将导致对 update_generated_write_fields
的第二次调用和生成列的第二次评估,如果它们是第一次更新——例如是否更新并不重要。一个 insert
触发器而你正在做一个 update
,任何触发器的纯粹存在就足够了。
我在 MySQL 5.7 中有一个 table,有几十个列。其中之一是生成的列(存储的,而不是虚拟的),它使用一个大的表达式来计算基于列 A、B 和 C 的值,所以我猜 MySQL 需要一点额外的时间来计算值插入或更新了新行。
我的简单问题是:
当我更新一行中的其他列(F、G 等)时,是否也触发了计算?
你能给我一些参考资料(链接)来证明你的答案吗?
谢谢
编辑:
我已经阅读了@Barmar 建议的 MySQL official documentation:
STORED: Column values are evaluated and stored when rows are inserted or updated.
如您所见,它说 inserted 或 updated 但我猜 updated实际上意味着:if related columns are updated 因为我认为 MySQL 足够聪明,如果这些列没有更新则不会执行计算。这其实就是我想确认的假设。
- STORED: Column values are evaluated and stored when rows are inserted or updated.
这清楚地表明,当您更新行中的其他列时会触发计算。
对于 update
语句,MySQL 将仅在指定要修改引用的列时重新评估生成的存储列(注意:不一定 changed,就在要修改的列列表中)。您可以验证这一点,例如使用调试版本。
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_fields
和 update_generated_write_fields
是评估生成字段表达式的相关函数。您还可以看到 gencolconst
的常量表达式未在更新中求值。
同样不幸的是(作为旁注),table 上触发器的纯粹存在将导致对 update_generated_write_fields
的第二次调用和生成列的第二次评估,如果它们是第一次更新——例如是否更新并不重要。一个 insert
触发器而你正在做一个 update
,任何触发器的纯粹存在就足够了。