MySQL 中 Varchar(50) 和 varchar(500) 区别是什么?

一. 问题描述

我们在设计表结构的时候,设计规范里面有一条如下规则:

  • 对于可变长度的字段,在满足条件的前提下,尽可能使用较短的变长字段长度。

为什么这么规定?我在网上查了一下,主要基于两个方面

  • 基于存储空间的考虑

  • 基于性能的考虑

网上说Varchar(50)varchar(500)存储空间上是一样的,真的是这样吗?

基于性能考虑,是因为过长的字段会影响到查询性能?

本文我将带着这两个问题探讨验证一下

二.验证存储空间区别

1.准备两张表

CREATE TABLE `category_info_varchar_50` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(50) NOT NULL COMMENT '分类名称',`is_show` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否展示:0 禁用,1启用',`sort` int(11) NOT NULL DEFAULT '0' COMMENT '序号',`deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_name` (`name`) USING BTREE COMMENT '名称索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分类';CREATE TABLE `category_info_varchar_500` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(500) NOT NULL COMMENT '分类名称',`is_show` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否展示:0 禁用,1启用',`sort` int(11) NOT NULL DEFAULT '0' COMMENT '序号',`deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除',`create_time` datetime NOT NULL COMMENT '创建时间',`update_time` datetime NOT NULL COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_name` (`name`) USING BTREE COMMENT '名称索引'
) ENGINE=InnoDB AUTO_INCREMENT=288135 DEFAULT CHARSET=utf8mb4 COMMENT='分类';

2.准备数据

给每张表插入相同的数据,为了凸显不同,插入100万条数据

DELIMITER $$
CREATE PROCEDURE batchInsertData(IN total INT)
BEGINDECLARE start_idx INT DEFAULT 1;DECLARE end_idx INT;DECLARE batch_size INT DEFAULT 500;DECLARE insert_values TEXT;SET end_idx = LEAST(total, start_idx + batch_size - 1);WHILE start_idx <= total DOSET insert_values = '';WHILE start_idx <= end_idx DOSET insert_values = CONCAT(insert_values, CONCAT('(\'name', start_idx, '\', 0, 0, 0, NOW(), NOW()),'));SET start_idx = start_idx + 1;END WHILE;SET insert_values = LEFT(insert_values, LENGTH(insert_values) - 1); -- Remove the trailing commaSET @sql = CONCAT('INSERT INTO category_info_varchar_50 (name, is_show, sort, deleted, create_time, update_time) VALUES ', insert_values, ';');PREPARE stmt FROM @sql;EXECUTE stmt;SET @sql = CONCAT('INSERT INTO category_info_varchar_500 (name, is_show, sort, deleted, create_time, update_time) VALUES ', insert_values, ';'); PREPARE stmt FROM @sql;EXECUTE stmt;SET end_idx = LEAST(total, start_idx + batch_size - 1);END WHILE;
END$$
DELIMITER ;CALL batchInsertData(1000000);

3.验证存储空间

查询第一张表SQL

SELECTtable_schema AS "数据库",table_name AS "表名",table_rows AS "记录数",TRUNCATE ( data_length / 1024 / 1024, 2 )  AS "数据容量(MB)",TRUNCATE ( index_length / 1024 / 1024, 2 )  AS "索引容量(MB)" 
FROMinformation_schema.TABLES 
WHEREtable_schema = 'test_mysql_field' and TABLE_NAME = 'category_info_varchar_50'
ORDER BYdata_length DESC,index_length DESC;

查询结果

图片

查询第二张表SQL

SELECTtable_schema AS "数据库",table_name AS "表名",table_rows AS "记录数",TRUNCATE ( data_length / 1024 / 1024, 2 )  AS "数据容量(MB)",TRUNCATE ( index_length / 1024 / 1024, 2 )  AS "索引容量(MB)" 
FROMinformation_schema.TABLES 
WHEREtable_schema = 'test_mysql_field' and TABLE_NAME = 'category_info_varchar_500'
ORDER BYdata_length DESC,index_length DESC;

查询结果

图片

4.结论

两张表在占用空间上确实是一样的,并无差别

三.验证性能区别

1.验证索引覆盖查询

select name from category_info_varchar_50 where name = 'name100000'
-- 耗时0.012s
select name from category_info_varchar_500 where name = 'name100000'
-- 耗时0.012s
select name from category_info_varchar_50 order by name;
-- 耗时0.370s
select name from category_info_varchar_500 order by name;
-- 耗时0.379s

通过索引覆盖查询性能差别不大

1.验证索引查询

select * from category_info_varchar_50 where name = 'name100000'
--耗时 0.012s
select * from category_info_varchar_500 where name = 'name100000'
--耗时 0.012s
select * from category_info_varchar_50 where name in('name100','name1000','name100000','name10000','name1100000',
'name200','name2000','name200000','name20000','name2200000','name300','name3000','name300000','name30000','name3300000',
'name400','name4000','name400000','name40000','name4400000','name500','name5000','name500000','name50000','name5500000',
'name600','name6000','name600000','name60000','name6600000','name700','name7000','name700000','name70000','name7700000','name800',
'name8000','name800000','name80000','name6600000','name900','name9000','name900000','name90000','name9900000') 
-- 耗时 0.011s -0.014s 
-- 增加 order by name 耗时 0.012s - 0.015sselect * from category_info_varchar_50 where name in('name100','name1000','name100000','name10000','name1100000',
'name200','name2000','name200000','name20000','name2200000','name300','name3000','name300000','name30000','name3300000',
'name400','name4000','name400000','name40000','name4400000','name500','name5000','name500000','name50000','name5500000',
'name600','name6000','name600000','name60000','name6600000','name700','name7000','name700000','name70000','name7700000','name800',
'name8000','name800000','name80000','name6600000','name900','name9000','name900000','name90000','name9900000') 
-- 耗时  0.012s -0.014s 
-- 增加 order by name 耗时 0.014s - 0.017s

索引范围查询性能基本相同, 增加了order By后开始有一定性能差别;

3.验证全表查询和排序

全表无排序

图片

图片

全表有排序
select * from category_info_varchar_50 order by  name ;
--耗时 1.498s
select * from category_info_varchar_500 order by  name  ;
--耗时 4.875s

图片

图片

结论:

全表扫描无排序情况下,两者性能无差异,在全表有排序的情况下, 两种性能差异巨大;

分析原因
varchar50 全表执行sql分析

图片

我发现86%的时花在数据传输上,接下来我们看状态部分,关注Created_tmp_files和sort_merge_passes

图片

图片

Created_tmp_files为3

sort_merge_passes为95

varchar500 全表执行sql分析

图片

增加了临时表排序

图片

图片

Created_tmp_files 为 4

sort_merge_passes为645

关于sort_merge_passes, Mysql给出了如下描述:

Number of merge passes that the sort algorithm has had to do. If this value is large, you may want to increase the value of the sort_buffer_size.

其实sort_merge_passes对应的就是MySQL做归并排序的次数,也就是说,如果sort_merge_passes值比较大,说明sort_buffer和要排序的数据差距越大,我们可以通过增大sort_buffer_size或者让填入sort_buffer_size的键值对更小来缓解sort_merge_passes归并排序的次数。

四.最终结论

至此,我们不难发现,当我们最该字段进行排序操作的时候,Mysql会根据该字段的设计的长度进行内存预估, 如果设计过大的可变长度, 会导致内存预估的值超出sort_buffer_size的大小, 导致mysql采用磁盘临时文件排序,最终影响查询性能

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

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

相关文章

C# Winform 用户控件,扩展控件,自定义控件综合实例

Control类是Windows窗体控件的基类&#xff0c;它提供了在 Windows 窗体应用程序中进行可视显示所需的基础结构&#xff0c;可以通过继承来扩展熟悉的用户控件和现有控件的功能。本列介绍三种不同自定义控件以及怎么创建他们。 自定义控件分类 用户控件&#xff1a;基本控件的…

IT入门知识博客文章大纲第二部分《编程语言》(2/10)

目录 IT入门知识博客文章大纲第二部分《编程语言》 1.引言 2.编程语言概述 2.1 编程语言的发展历程 2.2 编程范式 3.常见的编程语言 3.1 Python 3.2 Java 3.3 C 3.4 JavaScript 3.5 Ruby 4.编程语言的选择 4.1 技术需求 4.2 团队技能 4.3 社区和生态系统 4.4 可…

Python也能“零延迟“通信吗?ZeroMQ带你开启高速模式!

目录 1、零基础入门ZeroMQ 🚀 1.1 ZeroMQ简介与安装 1.2 基础概念:Socket类型详解 1.3 实战演练:Hello World示例 2、深入浅出消息模式 🔌 2.1 请求-应答模式( REQ/REP ) 2.2 发布-订阅模式( PUB/SUB ) 2.3 推送-拉取模式( PUSH/PULL ) 3、Python实战ZeroM…

Aptos Builder Jam 亚洲首站|议程公布,无限畅想 Aptos 生态未来

作为一个新兴的 Layer1 公链&#xff0c;Aptos 自诞生之日起的理想便是 “A Layer 1 for everyone” 当 Web3 深陷熊市阴影之时&#xff0c;Aptos 奋力为开发者找到了全新的技术路径&#xff0c;正有 200 项目正在开发&#xff0c;并且已有大量 DeFi 项目落实部署工作&#xff…

shell文本三剑客 awk 和 grep

awk 前言 AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。 Linux中最常用的文本处理工具有grep&#xff0c;sed&#xff0c;awk。行内将之称为文本三剑客&#xff0c;就功能量和效率来看&#xff0c;awk是当之无愧的文本三…

强化学习-tutorial

强化学习 当你发现收集有标注的数据困难&#xff0c;正确答案人类也不知道是什么的时候&#xff0c;往往是考虑使用RL的时候。尽管机器不知道答案是什么&#xff0c;但是机器会知道什么好&#xff0c;什么不好&#xff0c;通过与环境互动获得奖励。 过程 演算法解RL问题&…

【C++进阶】模板进阶与仿函数:C++编程中的泛型与函数式编程思想

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;栈和队列相关知识 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀模板进阶 &#x1f9e9;<&…

C语言概述与历史

引言 C语言是一门历史悠久且影响深远的编程语言。它不仅为后继的许多编程语言奠定了基础&#xff0c;同时因其高效性和灵活性在系统编程和嵌入式开发领域得到了广泛应用。本篇文章将全面介绍C语言的起源与发展、设计目标与理念&#xff0c;以及C语言的标准演化历程&#xff0c;…

MySQL Online DDL原理解读

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

boost asio异步服务器(3)增加发送队列实现全双工通信

增加发送节点 构造发送节点&#xff0c;管理发送数据。发送节点的类如下。 这个发送节点用于保证发送和接收数据的有效性。 增加发送队列 前边实现的是一个简单的echo服务器&#xff0c;也就是服务器将收到的内容发送给对应的客户端。但是在实际的服务器设计中&#xff0c;服务…

APP各种抓包教程

APP各种抓包教程 9/100 发布文章 wananxuexihu 未选择任何文件 new 前言 每当遇到一些 APP 渗透测试项目的时候&#xff0c;抓不了包的问题令人有点难受&#xff0c;但是抓不了包并不能代表目标系统很安全&#xff0c;那么接下来我会整理一下目前我所了解到的一些抓包方法 **声…

MySQL数据库管理(一)

目录 1.MySQL数据库管理 1.1 常用的数据类型​编辑 1.2 char和varchar区别 2. 增删改查命令操作 2.1 查看数据库结构 2.2 SQL语言 2.3 创建及删除数据库和表 2.4 管理表中的数据记录 2.5 修改表名和表结构 3.MySQL的6大约束属性 1.MySQL数据库管理 1.1 常用的数据类…

使用CSS常见问题解答卡片

常见问题解答卡片 效果展示 CSS 知识点 CSS 选择器的使用background 渐变背景色运用CSS 综合知识运用 页面整体布局 <div class"container"><h1>经常问的问题</h1><!-- 这里只是展示一个项目 --><div class"tab"><in…

Qwen-Agent:Qwen2加持,强大的多代理框架 - 函数调用、代码解释器以及 RAG!

✨点击这里✨&#xff1a;&#x1f680;原文链接&#xff1a;&#xff08;更好排版、视频播放、社群交流、最新AI开源项目、AI工具分享都在这个公众号&#xff01;&#xff09; Qwen-Agent&#xff1a;Qwen2加持&#xff0c;强大的多代理框架 - 函数调用、代码解释器以及 RAG&…

学会python——显示进度条(python实例五)

目录 1、认识Python 2、环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3、进度条显示 3.1 代码构思 3.2 代码示例 3.3 运行结果 4、总结 1、认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读…

QT QFileDialog文件选择对话框

QT QFileDialog文件选择对话框 选择txt或者cpp文件&#xff0c;读取内容并显示 参考&#xff1a; QT写入文件与读取文件内容_qt往一个文件写东西-CSDN博客 #include "QtFilePreview.h" #include "qfiledialog.h" #include "qfile.h" #includ…

制作自己的 @OnClick、@OnLongClick(告别 setOnClickListener,使用注解、反射和动态代理)

前言 前面我们说过 ButterKnife 这个库&#xff0c;这个库实现不仅实现了 View 的绑定&#xff0c;而且还提供了大量的注解如 BindView、OnClick、OnLongClick 等来简化开发过程中事件绑定。而这些功能的实现是通过 APT 也就是注解处理器&#xff0c;在编译期间生成 Java 代码…

MyBatis 的注解式开发

1. MyBatis 的注解式开发 文章目录 1. MyBatis 的注解式开发2. 准备工作3. Insert 插入/添加4. Delete 删除5. Update 更新/修改6. Select 查询7. 总结&#xff1a;8. 最后&#xff1a; MyBatis 中也提供了注解式开发方式&#xff0c;采用注解可以减少Sql映射文件的配置。 当然…

【React】useMemo

什么是 useMemo&#xff1f; useMemo 是 React 中的一个 Hook&#xff0c;它可以用来缓存计算结果&#xff0c;并在后续的渲染中重复利用这些计算结果。useMemo 接收两个参数&#xff1a;一个函数和一个依赖数组。当依赖数组中的任何一个值发生变化时&#xff0c;useMemo 会重新…

redis设计与实现(五)RDB与AOF持久化

RDB持久化 因为Redis是内存数据库&#xff0c;它将自己的数据库状态储存在内存里面&#xff0c;所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面&#xff0c;那么一旦服务器进程退出&#xff0c;服务器中的数据库状态也会消失不见。 为了解决这个问题&#xff0c;…