当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 生成列更新后索引值什么时候刷新

MySQL 生成列更新后索引值什么时候刷新

来源:17golang原创 2026-10-06 11:36:55 0浏览 收藏

MySQL 生成列没有单独的“刷新索引”按钮。依赖它的普通列发生变化时,STORED 生成列会在这次行写入中重新计算并保存,相关二级索引项也随同一条写入维护;VIRTUAL 生成列本身不落盘,读取时计算,但建立在它上的 InnoDB 二级索引仍需要在依赖列变化时维护。事务提交和优化器是否选择索引,是另外两个问题。

官方文档:https://dev.mysql.com/doc/refman/8.4/en/create-table-generated-columns.html

要点速览
  • STORED 在插入或更新时计算并保存,VIRTUAL 在读取路径计算;未改变依赖列的 UPDATE 不会凭空产生新的生成值。
  • 生成列有索引时,索引维护属于行写入的一部分,不需要执行 REBUILD、REFRESH 或手工回填。
  • 看到旧值先查事务可见性和实际依赖列,再查索引定义;EXPLAIN 只说明优化器是否选用索引,不证明索引是否刷新。

先分清生成列到底什么时候计算

VIRTUAL 的值不存储在行中,读取时根据表达式计算;没有指定关键字时,生成列默认是 VIRTUAL。STORED 则在行插入或依赖列更新时计算并保存,因此会额外占用行空间。两者都不能像普通列一样写入任意值,显式赋值只允许使用 DEFAULT。

MySQL 生成列 VIRTUAL 与 STORED 的计算时机静态说明图
图1:生成列计算时机说明图。VIRTUAL 在读取路径计算,STORED 在写入路径计算并保存;这是静态关系图,不是数据库截图。
类型值在什么时候计算是否占行存储能否建立索引
VIRTUAL读取时不保存列值InnoDB 支持其二级索引
STORED插入或更新时保存计算结果可以建立索引

用最小表观察值的更新路径

下面同时放置两种生成列,便于观察它们的语义差异。应用只更新 price 或 quantity,不要把生成列放进普通的赋值列表。

CREATE TABLE order_line (
  id BIGINT PRIMARY KEY,
  price DECIMAL(10, 2) NOT NULL,
  quantity INT NOT NULL,
  -- STORED:依赖列写入时计算并保存结果。
  line_total DECIMAL(12, 2)
    GENERATED ALWAYS AS (price * quantity) STORED,
  -- VIRTUAL:读取时根据相同表达式计算,不保存列值。
  line_total_virtual DECIMAL(12, 2)
    GENERATED ALWAYS AS (price * quantity) VIRTUAL,
  -- 两个索引都由 MySQL 在行变更时维护。
  INDEX idx_line_total (line_total),
  INDEX idx_line_total_virtual (line_total_virtual)
);

INSERT INTO order_line (id, price, quantity)
VALUES (1, 12.50, 2);

-- 只改变依赖列;生成列不能在这里写入任意新值。
UPDATE order_line
SET quantity = 3
WHERE id = 1;

-- 提交后重新读取,两列都应按 price * quantity 得到 37.50。
SELECT id, price, quantity, line_total, line_total_virtual
FROM order_line
WHERE id = 1;

这里的“刷新”发生在 UPDATE 维护记录的过程中:quantity 改变后,MySQL 重新评价表达式;STORED 写回新的 line_total,两个索引也同步维护。VIRTUAL 不会留下一个新的物理列值,但它的索引仍然必须反映新的表达式结果。

依赖列改变时索引项怎样跟着维护

要把三个层次分开看。第一层是生成列值有没有按表达式变化;第二层是当前事务或其他事务什么时候能看见这个变化;第三层才是优化器是否觉得索引值得用。前两层正确,并不保证每次 EXPLAIN 都选择该索引。

MySQL 生成列值、二级索引项、事务可见性和优化器选择关系图
图2:生成列索引维护边界图。值维护、事务可见性和优化器选用是三个相邻但不同的判断层,不代表某次真实执行结果。

例如下面的查询用于观察访问路径,而不是手动触发刷新:

-- 让优化器评估生成列索引是否适合这个条件。
EXPLAIN SELECT id, price, quantity
FROM order_line
WHERE line_total = 37.50;

-- 核对表定义,确认索引确实绑定到目标生成列。
SHOW CREATE TABLE order_line;

如果新事务已经提交但执行计划仍走全表扫描,优先检查条件是否与生成列表达式匹配、列类型和隐式转换是否改变了表达式形状、索引是否可见,以及统计信息是否能代表当前数据分布。不要把“没用索引”误判成“索引没刷新”。

看似没有刷新时按四层排查

  1. 先看依赖列。确认 UPDATE 实际改变了表达式引用的列;把列赋回原值时,MySQL 可能识别为没有实际变化。
  2. 再看事务。当前事务能看到自己的写入,其他事务要受隔离级别和提交时机影响。长事务读到旧版本,不等于索引维护失败。
  3. 再看定义。用 SHOW CREATE TABLE 核对生成表达式、STORED/VIRTUAL 类型和索引列,避免应用连到了另一张表或另一套 schema。
  4. 最后看计划。用 EXPLAIN 判断优化器选择;它反映成本估算和表达式匹配,不是索引物理内容的刷新日志。

如果变更的是生成列表达式本身,而不是依赖列的值,就进入 DDL 语义:例如修改 STORED 表达式可能需要重建数据;这和普通 UPDATE 后的索引项维护不是同一条路径。生产变更前应先查看对应版本的 ALTER TABLE 说明和执行计划。

检查清单:不要把三个问题混在一起

现象先验证什么正确判断
SELECT 看到新生成值依赖列、提交状态值计算路径正常
其他事务仍看到旧值事务隔离与快照可能是可见性,不是索引问题
EXPLAIN 没选生成列索引条件表达式、统计信息、索引可见性可能是优化器成本决策
修改了生成列表达式ALTER TABLE 执行方式属于 DDL 变更,可能涉及重建

因此,标题里的“什么时候刷新”可以落成一句可执行的判断:普通依赖列改变时,生成列和它的索引在该行写入过程中维护;STORED 的列值在写入时保存,VIRTUAL 的列值在读取时计算;提交后其他事务何时看见,以及查询是否使用索引,分别按事务和优化器规则判断。

相关问题

可以直接 UPDATE 生成列吗?

不能写入任意计算结果。MySQL 对生成列的显式赋值只允许使用 DEFAULT,实际业务应更新表达式依赖的普通列。

VIRTUAL 生成列没有存储值,为什么还能建索引?

列值本身不作为普通行字段保存,但 InnoDB 可以维护基于该表达式结果的二级索引;依赖列变化时,索引项仍要同步调整。

索引没有被 EXPLAIN 选中,是否说明刷新失败?

不说明。EXPLAIN 展示的是优化器对当前条件、统计信息和成本的选择。先用 SELECT 验证值,再用 SHOW CREATE TABLE 核对定义,最后分析访问路径。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
繁花动漫官网的12ms和99.9%稳定性可信吗?指标核对说明繁花动漫官网的12ms和99.9%稳定性可信吗?指标核对说明
上一篇
繁花动漫官网的12ms和99.9%稳定性可信吗?指标核对说明
Go InsecureSkipVerify 开启后怎么保留自定义证书校验
下一篇
Go InsecureSkipVerify 开启后怎么保留自定义证书校验
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    345次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    408次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    405次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    369次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    190次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码