MySQL虚拟列:一个被低估的MySQL特性

前言

最近在做订单系统重构时,遇到了一个有趣的问题。

系统里有很多地方都要计算订单的总价(数量×单价),这个计算逻辑分散在各个服务中,产生了不少相似甚至重复的代码。

代码评审时,同事提出了一个建议 —— 使用MySQL的虚拟列来统一处理这类计算,在调研后我们一致决定采纳。

经过一段时间的生产实践,也逐渐摸清了虚拟列的套路,这里就和大家分享一下这个特性的使用心得。

耐心看完,你一定有所收获。

MySQL 5.7版本引入的虚拟列(Generated Columns)允许我们定义一个基于其他列计算得出的列。

它有点像Excel中的计算列,但更加强大和灵活。

虚拟列分为两种类型:

  1. VIRTUAL(虚拟列):在读取时实时计算,不占用存储空间
  2. STORED(存储列):在数据写入时计算并存储,会占用实际存储空间

基本语法

创建虚拟列的语法不难:

-- 例如,计算订单总价CREATE TABLE orders (quantity INT,unit_price DECIMAL(10,2),total_price DECIMAL(10,2) GENERATED ALWAYS AS (quantity * unit_price) VIRTUAL);

虚拟列还是比较好用的,但是也得注意,不是所有的场景都适合使用,这里先讲适合的。

适合使用虚拟列的场景

  1. 可以简化查询和业务操作的,避免在多个查询中重复编写相同的表达式

-- 例如,计算订单总价CREATE TABLE orders (quantity INT,unit_price DECIMAL(10,2),total_price DECIMAL(10,2) GENERATED ALWAYS AS (quantity * unit_price) VIRTUAL);
  1. 需要确保计算值始终正确且一致

-- 自动计算年龄CREATE TABLE persons (birth_date DATE,age INT GENERATED ALWAYS AS (YEAR(CURDATE()) - YEAR(birth_date)) VIRTUAL);
  1. 从JSON列中提取特定字段或者做一些判断
CREATE TABLE products (attributes JSON,product_name VARCHAR(100) GENERATED ALWAYS AS (attributes->>'$.name') VIRTUAL
);
  1. 利用虚拟列创建索引,提高查询性能

这个特性需要MySQL 8.0+


CREATE TABLE users (full_name VARCHAR(100),first_name VARCHAR(50) GENERATED ALWAYS AS (SUBSTRING_INDEX(full_name, ' ', 1)) VIRTUAL,INDEX (first_name));

不适合使用虚拟列的场景

  1. 计算成本过高、过于复杂的表达式会影响性能
  2. 频繁更新的表,则不适用VIRTUAL列,毕竟在每次查询时都会重新计算
  3. 存储空间严重受限时,谨慎使用使用STORED类型时,因为STORED列会增加存储空间
  4. MySQL 5.7 以下不支持虚拟列
  5. 计算依赖于不确定性函数(如NOW()、RAND())的,也不能使用

虚拟列的限制

  1. 不能在虚拟列中使用子查询
  2. 不能引用自增列
  3. 不能使用存储函数或用户定义的函数
  4. 不能使用不确定函数(如NOW())
  5. 不能将虚拟列作为外键
  6. 不能设置默认值

性能考虑

  1. VIRTUAL列:查询时计算,适合计算简单、不频繁查询的列
  2. STORED列:写入时计算,适合计算复杂、频繁查询的列
  3. 索引:只能在STORED列上创建索引(MySQL 8.0+支持在VIRTUAL列上创建索引)

总结

MySQL虚拟列为我们提供了一个优雅的解决方案,可以将部分计算逻辑从应用层转移到数据层,既保证了数据的一致性,又简化了应用层代码。

在我们的订单系统中,目前有不少字段都用上了虚拟列,确实代码会更加清晰,维护成本也有相应降低。

当然,是否使用虚拟列需要根据具体场景来判断。

对于简单的计算逻辑,特别是需要在多处使用的计算结果,虚拟列是个不错的选择。
但对于复杂的业务逻辑,还是建议放在应用层处理为好。

希望这篇文章能帮助大家更好地理解和使用MySQL虚拟列这个实用的特性。

如果你的项目中有类似的场景,不妨尝试一下这个功能,也欢迎使用过的朋友来交流下心得。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/909083.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

音频导入规范

一般音频可以交给策划来导入提交,需要遵循一些规范,下面是我们实际项目用到的一些规范 1、Force To Mono: 勾选,强制单声道。(可以减少音效文件的内存占用) 2、Normalize: 勾选,引…

使用html写一个倒计时页面

一个使用 HTML、CSS 和 JavaScript 实现的倒计时页面,包含动态效果和响应式布局: 功能特点: 动态效果: 每个时间单元带有 hover 动画(悬浮时轻微上浮)倒计时数字实时更新,精确到秒结束时自动更换背景颜色并显示提示信息响应式设计: 适配移动端屏幕(屏幕宽度小于600px…

spring boot源码和lib分开打包

1.项目通过maven引入的jar多了之后&#xff0c;用maven打出的jar会非常庞大&#xff0c;我的是因为引入了ffmpeg的相关jar,所以&#xff0c;每次上传服务更新都要传输好久&#xff0c;修改maven打包方式&#xff0c;改为源码和lib分离模式 2.maven的pom.xml配置如下 <build…

计算机网络笔记(三十)——5.2用户数据报协议UDP

5.2.1UDP概述 一、UDP 的定义 用户数据报协议 (User Datagram Protocol, UDP) 是传输层的无连接、不可靠协议。它提供最小化的协议机制&#xff0c;仅支持数据报的简单传输&#xff0c;不保证数据顺序或可靠性。 二、UDP 的核心特点 无连接 通信前无需建立连接&#xff0c;直…

Java异步编程之消息队列疑难问题拆解

前言 在Java里运用消息队列实现异步通信时&#xff0c;会面临诸多疑难问题。这里对实际开发中碰到的疑难为题进行汇总及拆解&#xff0c;使用RabbitMQ和Kafka两种常见的消息队列中间件来作为示例&#xff0c;给出相应的解决方案&#xff1a; 一、消息丢失问题 消息在传输过程…

香橙派3B学习笔记10:snap打包C/C++程序与动态链接库(.so)

esnap打包C/C程序与动态链接库&#xff08;.so&#xff09; 之前已经学会了snap基本的打包程序&#xff0c;现在试试打包C/C程序与动态链接库&#xff08;.so&#xff09; ssh &#xff1a; orangepi本地ip 密码 &#xff1a; orangepi 操作系统发行版&#xff1a; 基于 Ubun…

【Python工具开发】k3q_arxml 简单但是非常好用的arxml编辑器,可以称为arxml杀手包

k3q_arxml 介绍 仓库地址1 仓库地址2 极简的arxml编辑库&#xff0c;纯python实现 用法 from pprint import pp # 可以美化打印对象&#xff0c;不然全打印在一行 import k3q_arxml # 加载arxml文件 io_arxml k3q_arxml.IOArxml(filepaths[test/model_merge.arxml])# 打印…

【CSS-8】深入理解CSS选择器权重:掌握样式优先级的关键

CSS选择器权重是前端开发中一个基础但极其重要的概念&#xff0c;它决定了当多个CSS规则应用于同一个元素时&#xff0c;哪条规则最终会被浏览器采用。理解权重机制可以帮助开发者更高效地编写和维护CSS代码&#xff0c;避免样式冲突带来的困扰。 1. 什么是CSS选择器权重&…

大语言模型原理与书生大模型提示词工程实践-学习笔记

&#x1f4d8; 第五期书生葡语实战营讲座总结 &#x1f399; 主讲人&#xff1a;王明&#xff08;东部大学 数据挖掘实验室 博士生&#xff09; 一、大语言模型的生成原理 架构基础&#xff1a;采用 Transformer&#xff08;Decoder-only&#xff09;架构&#xff0c;如 GPT …

李沐 《动手学深度学习》 | 实战Kaggle比赛:预测房价

文章目录 1.下载和缓存数据集2.数据预处理读取样本预处理样本数值型特征处理特征标准化的好处离散值处理转换为张量表示 训练K折交叉验证模型选择最终模型确认及结果预测代码总结提交到Kaggle 房价预测比赛链接&#xff1a;https://www.kaggle.com/c/house-prices-advanced-reg…

一键部署Prometheus+Grafana+alertmanager对网站状态进行监控

在建设监控体系的过程中&#xff0c;针对一个系统的监控是多维度的&#xff0c;除了服务器资源状态、中间件状态、应用状态外&#xff0c;对系统访问状态的监控也是很有必要&#xff0c;可以在系统访问出现异常时第一时间通知到我们。本文介绍使用 Docker-compose 方式一键部署…

康谋方案 | 高精LiDAR+神经渲染3DGS的完美融合实践

目录 一、从点云到高精地图的重建 1、数据采集 2、点云聚合 3、高精地图建模 4、三维建模与装饰 二、颠覆性革新&#xff1a;NeRF 与 3DGS 重建 1、仅需数日&#xff0c;完成街景重建 2、进一步消除 Domain gap&#xff0c;场景逼真如实地拍摄 3、降本增效&#xff0c…

MySQL-事务(TRANSACTION-ACID)管理

目录 一、什么是事务&#xff1f; 1.1.事务的定义 1.2.事务的基本语句 1.3.事务的四大特性&#xff08;ACID&#xff09; 二、数据库的并发控制 2.1.什么是并发及并发操作带来的影响&#xff1f; 2.2.并发操作带来的隔离级别 三、使用事务的场景 3.1.银行转账场景示例 3.2.模拟…

centos系统docker配置milvus教程

本人使用的是京东云服务器配置milvus 参考教程&#xff1a;https://blog.csdn.net/withme977/article/details/137270087 首先确保安装了docker 、docker compose docker -- version docker-compose --version创建milvus工作目录 mkdir milvus # 进入到新建的目录 cd milvu…

什么是JSON ?从核心语法到编辑器

一、什么是JSON &#xff1f; JSON&#xff0c;即 JavaScript 对象表示法&#xff0c;是一种轻量级、跨语言、纯文本的数据交换格式 。它诞生于 JavaScript 生态&#xff0c;但如今已成为所有编程语言通用的 “数据普通话”—— 无论前端、后端&#xff0c;还是 Python、Java&…

计算机网络(7)——物理层

1.数据通信基础 1.1 物理层基本概念 物理层(Physical Layer)是所有网络通信的物理基础&#xff0c;它定义了在物理介质上传输原始比特流(0和1)所需的机械、电气、功能、过程和规程特性 1.2 数据通信系统模型 信源&#xff1a;生成原始数据的终端设备&#xff0c;常见形态包括…

深度学习基础知识总结

1.BatchNorm2d 加速收敛&#xff1a;Batch Normalization 可以使每层的输入保持较稳定的分布&#xff08;接近标准正态分布&#xff09;&#xff0c;减少梯度更新时的震荡问题&#xff0c;从而加快模型训练速度。 减轻过拟合&#xff1a;批归一化引入了轻微的正则化效果&#…

iOS 抖音首页头部滑动标签的实现

抖音首页的头部滑动标签(通常称为"Segmented Control"或"Tab Bar")是一个常见的UI组件&#xff0c;可以通过以下几种方式实现&#xff1a; 1. 使用UISegmentedControl 最简单的实现方式是使用系统自带的UISegmentedControl&#xff1a; let segmentedCo…

ThreadLocal实现原理

ThreadLocal 是 Java 中实现线程封闭&#xff08;Thread Confinement&#xff09;的核心机制&#xff0c;它通过为每个线程创建变量的独立副本来解决多线程环境下的线程安全问题。 Thread └── ThreadLocalMap (threadLocals) // 每个线程持有的专属Map├── Entry[] tab…

【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境

如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境&#xff1f; 在 Python 开发中&#xff0c;为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具&#xff0c;能高效创建不同 Python 版本的 Poetry 虚拟环境&#xff0c;接下来…