首页 > 数据库 >MySQL 大表改列

MySQL 大表改列

时间:2024-10-07 10:11:10浏览次数:8  
标签:Column 索引 虚拟 MySQL mod ALTER 改列 大表

前言

作为一个 MySQL DBA,和大表打交道的次数想必不少,大表上的 ALTER 操作一般影响都很大,平时会用 Online DDL 工具来辅助操作,但是本文会介绍一种特殊的技巧来应对一部分大表上的 ALTER 需求。

解决方案

从标题可以看出来,这次会用到 MySQL 5.7 的新功能:Generated Column,这种虚拟列在添加的时候耗时在秒级以内,也不需要 rebuild 表,对磁盘空间和数据库服务器资源的压力几乎没有,在应对一些紧急情况和比较严峻的资源场景的时候偶尔会发挥出奇效~

案例 1

背景

业务的新需求,在超过 5000 万行的大表上需要调整一个有唯一索引的 VARCHAR 列,从大小写不敏感变为大小写敏感,且调整完之后仍旧需要唯一索引。

PS:实际案例,脱敏改造了一下。

简要分析

MySQL 在判断大小写是否敏感的时候,依据的是字符集的 collation 设置,默认情况下是大小写不敏感的。

以前文的环境为例,加上唯一索引之后,再试试插入新数据:

测试效果

可以发现 Adam 和 adam 会被认为是相同的值,MySQL 的一致性校验会报错。

解决这个 collation 的办法还是不少的:SQL 加上 collation 的 keyword,视实际的业务场景评估 ALTER 操作的可能性等等。而 Generated Column 这个特性提供了另外一种解决思路:创建一个虚拟的列,把唯一索引设置在这个虚拟列上,然后业务 SQL 使用这个虚拟列来查询。

实践一下

在测试表上创建一个新的虚拟列,然后加上唯一索引。

ALTER TABLE stu ADD COLUMN cs_sname varchar(16) COLLATE utf8mb4_bin GENERATED ALWAYS AS (sname);
ALTER TABLE stu ADD UNIQUE unq_csname(cs_sname);

看看表结构:

表结构示例

这时候再插入一些数据,看看实际效果:

效果演示

可以看到,在不 rebuild 表,也不变更列属性的情况下,这个业务需求就已经实现了。如果 sname 这一列还需要继续使用的话,记得加上普通索引。

总结一下

通过一个 0.00 秒的 ALTER 语句,在无需额外磁盘空间,仅付出理论上少量的 CPU 算力的代价之下,这个大表上变更列的需求就这么解决了。相比较于耗时耗力的风险评估以及 Online DDL,这个新技巧体现出了巨大的有事。

不过要特别注意一点,这种行为会带来一定的维护和理解成本,切忌滥用

案例 2

背景

虚构案例,函数索引

简要分析

MySQL 的功能性一直是饱受诟病,函数索引在其他 RDBMS 上都有支持,但是 MySQL 这边一直都得通过各种奇怪的手段来间接实现,或者是直接在代码层计算完之后再查询。

在 MySQL 5.7 之后,利用 Generated Column 肯定是可以实现函数索引的:用函数计算的结果生成一个虚拟列,然后再使用虚拟列查询。

不过在这种常规的思路之外,其实 MySQL 还多做了“一点点的改进”。来简单实践一下,看看这个“改进”是什么。

实践一下

仍旧使用上文中的表,使用 mod 函数建立一个虚拟列:

ALTER TABLE stu ADD COLUMN num_mod int GENERATED ALWAYS AS (mod(total,10));

效果如下:

实际效果

所以按照常规的思路,业务查询在需要用到函数的时候,应该要使用虚拟列num_mod。例如:

select * from stu where num_mod=4
Explain 结果

那么“一点点改进”是什么呢?不需要数据库端做任何变动,改改 SQL 看看效果:

Explain 结果

可以看到 MySQL 已经可以直接识别到 where 条件中的函数,然后利用虚拟列的索引来执行查询,而不再需要专门修改 SQL 去使用虚拟列了。

总结一下

仅从效果来看,只需要隐藏虚拟列的存在,MySQL 基本也可以认为是“支持”函数索引了,不过可能 Oracle 比较懒,没有去做这个事情吧,只能靠 DBA 去手动支持一下了。

结语

Generated Column 可以随意自定义“规则”的特点给了它极大的可能性,在面对一些棘手的场景时,Generated Column 也许就是让难题迎刃而解的画龙点睛之笔。

标签:Column,索引,虚拟,MySQL,mod,ALTER,改列,大表
From: https://www.cnblogs.com/ataoxz/p/18449798

相关文章

  • mysql数据库连接异常问题(总结)
    针对你提到的多种数据库连接问题,下面进行总结和建议,以避免未来再次遇到相同的问题:1.连接超时(AnattemptbyaclienttocheckoutaConnectionhastimedout)原因:网络不稳定数据源配置参数异常解决方案:优化网络环境:检查网络延迟和丢包率。考虑使用更稳定的网络......
  • 连接Mysql时出现的“no database selected”错误该如何解决?
    遇到“nodatabaseselected”错误通常是因为在尝试执行SQL查询时没有明确指定要使用的数据库。以下是解决这个问题的步骤:确认连接时已选择数据库在连接数据库之后,确保已经选择了具体的数据库。例如,在MySQL中,可以使用 USE<database_name>; 语句来选择一个数据库。USE......
  • MySQL遇到问题及解决方案
    针对MySQL遇到的问题及解决方案,可以按照以下步骤进行排查和解决:查看错误日志查看MySQL的日志文件,特别是error.log文件。命令行下可以通过 tail-f/var/lib/mysqlhostname.err 查看实时日志。检查数据库服务状态确认MySQL服务是否正在运行。bash systemctl......
  • 探索MySQL的InnoDB索引失效
    MySQL8+InnoDB- 序章索引失效,发生在已经建立索引,但是,查询(SELECT)时没有用到建立的(预期会用到)索引的情况下。失效原因有两个方面:1、建立索引的方式错误需要弄清楚 字段的#区分度(极其重要)这个概念。选择区分度高的建立索引。2、某些SELECT语句不支持使用索引注意,......
  • MySQL单表存多大的数据量比较合适
    前言经常使用MySQL数据库的小伙伴都知道,当单表数据量达到一定的规模以后,查询性能就会显著降低。因此,当单表数据量过大时,我们往往要考虑进行分库分表。那么如何计算单表存储多大的数据量合适?当单表数据达到多大的规模时,我们才要进行分库分表呢?MySQL存储方式首先我们要先了解一下......
  • 【2024计算机毕业设计】基于jsp+mysql+Spring+mybatis的SSM药品进货销售仓储信息管理
    运行环境:最好是javajdk1.8,我在这个平台上运行的。其他版本理论上也可以。IDE环境:Eclipse,Myeclipse,IDEA或者SpringToolSuite都可以,如果编译器的版本太低,需要升级下编译器,不要弄太低的版本tomcat服务器环境:Tomcat7.x,8.x,9.x版本均可操作系统环境:WindowsXP/7......
  • [MySQL]为什么大厂选择读已提交
    为什么读已提交的并发性更好在数据库中,锁的时间和范围是影响并发性的重要因素。已提交读(ReadCommitted)隔离级别与可重复读(RepeatableRead)的主要区别就在于它们在读取数据时对锁的使用方式不同。让我们详细看看为什么已提交读的锁的时间和范围更小。1.已提交读(ReadCommitte......
  • 本地环境PHP帝国备份王备份报错mysql_escape_string(): This function is
    在使用帝国备份王进行备份和恢复时,如果遇到PHP5.5环境下的报错,通常是因为一些旧的MySQL函数已经被弃用或移除。具体来说,mysql_escape_string 函数在PHP5.5中已经被废弃,应该使用 mysql_real_escape_string 替代。解决方案定位问题文件:找到 function.php 文件的位置。......
  • DBeaver 连接 mysql 报错:Public Key Retrieval is not allowed
    前言DBeaver连接mysql报错:PublicKeyRetrievalisnotallowed遇到"PublicKeyRetrievalisnotallowed"错误时,通常意味着你正在使用的身份验证方法需要加密连接,但是没有正确地配置客户端或服务器来支持这种加密。解决第一种可以在连接字符串中添加 allowPublicKey......
  • mysql 连接失败:message from server: "Host 'xx.xxx' is not allowed to connect to t
    前言mysql连接失败:messagefromserver:"Host'192.168.xx.xxx'isnotallowedtoconnecttothisMySQLserver"解决错误信息表明你尝试从IP地址192.168.xx.xxx连接到MySQL服务器,但是该IP地址没有被授权连接权限。为了解决这个问题,你需要确保你的MySQL用户权......