MySQL之Schema与数据类型优化(三)

news2025/1/17 1:03:08

Schema与数据类型优化

BLOB和TEXT类型

BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。
实际上它们分别属于两组不同的数据类型家族:字符类型是TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT;对应的二进制类型是TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB.BLOB是SMALLBLOB的同义词,TEXT是SMALLTEXT的同义词。
与其他类型不同,MySQL把每个BLOB和TEXT值当作一个独立的对象处理。存储引擎在存储时通常会做特殊处理。当BLOB和TEXT值太大时,InnoDB会使用专门的"外部"存储区域来进行存储,此时每个值在行内需要1~4个字节存储一个指针,然后再外部存储区域存储实际的值。
BLOB和TEXT家族之间仅有的不同时BLOB类型存储的是二进制数据,没有排序规则或字符集,而TEXT类型有字符集和排序规则。
MySQL对BLOB和TEXT列进行排序与其他类型是不同的:它只对每个列的最前max_sort_length字节而不是整个字符串做排序。如果只需要排序前面一小部分字符,则可以减小max_sort_length的配置,或者使用ORDER BY SUBSTRING(column, length).
MySQL不能将BLOB和TEXT列全部长度的字符串进行索引,也不能使用这些索引消除排序

磁盘临时表和文件排序

因为Memory引擎不支持BLOB和TEXT类型,所以,如果查询使用了BLOB或TEXT列并且需要使用隐式临时表,将不得不使用MyISAM磁盘临时表。即使只有几行数据也是如此(Percona Server的Memory引擎支持BLOB和TEXT类型,同样的场景下还是需要使用磁盘临时表)。这会导致严重的性能开销。即使配置MySQL将临时表存储再内存块设备上(RAM Disk),依然需要许多昂贵的系统调用。最好的解决方案是尽量避免使用BLOB和TEXT类型。如果实在无法避免,有一个技巧是在所有用到BLOB字段的地方都使用SUBSTRING(column, length)将列值转换为字符串(在ORDER BY 子句中也适用),这样就可以使用内存临时表了。但是要确保截取的子字符串足够短,不会使临时表的大小超过max_heap_table_size或tmp_table_size,超过以后MySQL会将内存临时表转换为MyISAM磁盘临时表。
最坏情况下的长度分配对于排序的时候也是一样的,所以这一招对于内存中创建大临时表和文件排序,以及在磁盘上创建大临时表和文件排序这两种情况都很有帮助。

例如,假设有一个1000万行的表,占用几个GB的磁盘空间。其中有一个uft8字符集的VARCHAR(1000)的列,每个字符最多使用3个字节,最坏情况下需要3000字节的空间。如果在ORDER BY 中用到这个列,并且查询扫描整个表,为了排序就需要超过30GB的临时表。
如果EXPLAIN执行计划的Extra列包含了"Using temporary",则说明这个查询使用了隐式临时表

使用枚举类型(ENUM)代替字符串类型

有时候可以使用枚举列代替常用的字符串类型。枚举列可以把一些不重复的字符串存储成一个预定义的集合。MySQL在存储枚举时非常紧凑,会根据列表值得数量压缩到一个或者两个字节中。MySQL会在内部将每个值在列表中得为止保存为整数,并且在表的.frm文件中保存"数字-字符串"映射关系的"查找表",
例如,

mysql> CREATE TABLE enum_test(e ENUM('fish', 'apple', 'dog') NOT NULL);
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO enum_test(e) VALUES('fish'), ('dog'),('apple');
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

这三行数据实际存储为整数,而不是字符串。可以通过在数字上下问环境检索看到这个双重属性:

mysql> SELECT e+0 FROM enum_test;
+-----+
| e+0 |
+-----+
|   1 |
|   3 |
|   2 |
+-----+
3 rows in set (0.05 sec)

如果使用数字作为ENUM枚举常量,这种双重性很容易导致混乱,例如ENUM(‘1’,‘2’,‘3’).建议尽量避免这么做。另外一个让人吃惊的地方时,枚举字段是按照内部存储的整数而不是定义的字符串进行排序的:

mysql> SELECT e FROM enum_test ORDER BY e;
+-------+
| e     |
+-------+
| fish  |
| apple |
| dog   |
+-------+
3 rows in set (0.05 sec)

一种绕过这种限制的方式是按照需要的顺序来定义枚举列。另外也可以在查询中使用FIELD()函数显式地指定排序顺序,但这会导致MySQL无法利用索引消除排序。


mysql> SELECT e FROM enum_test ORDER BY FIELD(e, 'apple', 'dog','fish');
+-------+
| e     |
+-------+
| apple |
| dog   |
| fish  |
+-------+
3 rows in set (0.07 sec)

如果在定义时就是按照字母的顺序,就没有必要这么做了。枚举最不好的地方是,字符串列表是固定的,添加或删除字符串必须使用ALTER TABLE,因此,对于一系列未来可能会改变的字符串,使用枚举不是一个好主意,除非能接受只在列表末尾添加元素,这样在MySQL5.1中就可以不用重建整个表来完成修改。
由于MySQL把每个枚举值保存为整数,并且必须进行查找才能转换为字符串,所以枚举列有一些开销。通常枚举的列表都比较小,所以开销还可以控制,但也不能保证一直如此。在特定情况下,把CHAR/VARCHAR列与枚举列进行关联可能会比直接关联(CHAR/VARCHAR)列更慢。
为了说明这个情况,读一个应用中的一张表进行了基准测试,看看在MySQL中执行上面说的关联的速度如何。该表有一个很大的主键:

CREATE TABLE webservicecalls(
day date NOT NULL,
account smallint NOT NULL,
service varchar(10) NOT NULL,
method varchar(50) NOT NULL,
calls int NOT NULL,
items int NOT NULL,
time float NOT NULL,
cost decimal(9,5) NOT NULL,
updated datetime,
PRIMARY KEY(day,account, service, method)
) ENGINE=InnoDB;

这个表有11万行数据,只有10MB大小,所以可以完全载入内存。service列包含了5个不同的值,平均长度为4个字符,method列包含了71个值,平均产犊为20个字符。
复制一下这个表,但是把service和method字段换成枚举类型,表结构如下:


CREATE TABLE webservicecalls_enum(
...omitted...
service ENUM(... VALUES omitted ...) NOT NULL,
method ENUM(... VALUES omitted ...) NOT NULL,
...omitted...
) ENGINE=InnoDB;

然后我们用主键列关联这两个表,下面是所使用的查询语句:

mysql> SELECT SQL_NO_CACHE COUNT(*) FROM webservicecalls JOIN webservicecalls USING(day, account,service,method);

用VARCHAR和ENUM分别测试了这个语句,结果如表所示
在这里插入图片描述

从上面的结果可以看到,当把列都转换成ENUM以后,关联变得很快。但是当VARCHAR列和ENUM列进行关联时则慢很多。在本例中,如果不是必须和VARCHAR列进行关联,那么转换这些列为ENUM就是个好主意。这是一个通用的设计时间,在"查找表"时采用整数主键而避免采用基于字符串的值进行关联。然而,转换列为枚举型还有另外一个好处。根据SHOW TABLE STATUS命令输出结果中Data_length列的值,把这两列转换为ENUM可以让表的大小缩小1/3.在某些情况下,即使可能出现ENUM和VARCHAR进行关联的情况,这也是值得的(这很可能可以节省IO)。同样,转换后主键也只有原来的一半大小了,因为这是InnoDB表,如果表上有其他索引,减小主键大小会使得非主键索引也变得更小。
在这里插入图片描述
(该图只是查询Data_length,与上面的例子无关)

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

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

相关文章

成都爱尔周进院长提醒当双眼度数差距过大,我们该做些什么

每个人的用眼方式、用眼习惯且两只眼睛“天生条件”不一定相同,当发生近视,双眼近视程度也就可能不同,双眼度数必然会变得不一样。当双眼度数产生差异,尤其是当双眼度数差别过大时会引发哪些问题? 双眼度数不一致&…

Qt快速入门到熟练(电子相册项目(二))

上一节我们成功实现了创建项目的向导界面的开发,这节我们继续去实现电子相册的其他功能。 新建DirTreeWidget类 还记得在Qt快速入门到熟练(电子相册项目(一))-CSDN博客里面,我们是在QDockWidget中添加了一个treeWidget作为以后显示目录树的空间…

OpenHarmony集成OCR三方库实现文字提取

1. 简介 Tesseract(Apache 2.0 License)是一个可以进行图像OCR识别的C库,可以跨平台运行 。本样例基于Tesseract库进行适配,使其可以运行在OpenAtom OpenHarmony(以下简称“OpenHarmony”)上,并新增N-API接口供上层应…

[算法] 优先算法(二): 双指针算法(下)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

Rust学习心得

我分享一下一年的Rust学习经历,从书到代码都一网打尽。 关于新手如何学习Rust,我之前在Hacker News上看到了这么一篇教程: 这篇教程与其他教程不同的时,他不是一个速成教程,而是通过自己的学习经历,向需要…

mac安装两个版本谷歌浏览器;在mac运行不同版本的chrome浏览器

场景 正常情况下,mac上只能安装一个版本的chrome浏览器,即使你安装了两个版本的,打开老旧版本时候也会自动切换成最新版的浏览器 故本文主要解决如何下载和在mac运行不同版本的chrome浏览器 文章目录 场景一、下载1.mac本身就有一个最新版ch…

【MySQL】库的操作和表的操作

库的操作和表的操作 一、库的操作1、创建数据库(create)2、字符集和校验规则(1)查看系统默认字符集以及校验规则(2)查看数据库支持的字符集(3)查看数据库支持的字符集校验规则(4)校验…

网关路由SpringCloudGateway、nacos配置管理(热更新、动态路由)

文章目录 前言一、网关路由二、SpringCloudGateway1. 路由过滤2. 网关登录校验2.1 鉴权2.2 网关过滤器2.3 登录校验2.3.1 JWT2.3.2 登录校验过滤器 3. 微服务从网关获取用户4. 微服务之间用户信息传递 三、nacos配置管理问题引入3.1 配置共享3.1.1 在Nacos中添加共享配置3.1.2 …

Kubectl 的使用——k8s陈述式资源管理

一、kebuctl简介: kubectl 是官方的CLI命令行工具,用于与 apiserver 进行通信,将用户在命令行输入的命令,组织并转化为 apiserver 能识别的信息,进而实现管理 k8s 各种资源的一种有效途径。 对资源的增、删、查操作比较方便&…

MobaXterm下载虚拟机SSH链接超时解决(保姆级踩坑)

文章目录 为啥要用MobaXtermMobaXterm下载打开虚拟机ssh链接ssh连接失败排查linux配置windows配置 到这了,什么都干了,怎么还不成功? 更多相关内容可查看 在一个阳光明媚的下午,开启了无限踩坑的旅程 为啥要用MobaXterm 作为小编…

高性能负载均衡的分类及架构分析

如何选择与部署适合的高性能负载均衡方案? 当单服务器性能无法满足需求,高性能集群便成为提升系统处理能力的关键。其核心在于通过增加服务器数量,强化整体计算能力。而集群设计的挑战在于任务分配,因为无论在哪台服务器上执行&am…

解决脚本刷服务器导致卡顿宕机的问题

在互联网服务领域,自动化脚本的不当使用或恶意攻击可能会导致服务器资源被过度消耗,从而引发服务响应缓慢甚至系统崩溃。特别是在电商、游戏、社交平台等领域,这种现象尤为常见。本文将深入探讨脚本刷服的常见形式、其对服务器性能的影响&…

面向对象-----继承

前面向大家介绍了面向对象中的封装性,今天再来向大家介绍面向对象的继承和多态的两大特性。 1.继承 1.1 为什么需要继承? 在java语言中,我们用类来描述世间万物,虽然万物非常复杂,但总有一些共同点,如果…

Java NIO 基础

Java NIO 基础 1. NIO 介绍2. NIO 三大组件2.1 Channel2.1.1 常见的 Channel2.1.2 常用方法 2.2 Buffer2.2.1 常见的 Buffer2.2.2 重要属性2.2.3 常用方法 2.3 Selector2.3.1 四种事件类型 1. NIO 介绍 NIO(non-blocking io):非阻塞IO&#…

2024.5.20 学习记录

1、react 原理(jsx的本质、事件机制原理、setState和batch Update、组件渲染更新和diff算法、fiber) 2、代码随想录贪心刷题

【C++初阶】--- C++入门(上)

目录 一、C的背景及简要介绍1.1 什么是C1.2 C发展史1.3 C的重要性 二、C关键字三、命名空间2.1 命名空间定义2.2 命名空间使用 四、C输入 & 输出 一、C的背景及简要介绍 1.1 什么是C C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题&…

GPT-4o 引领人机交互新风向的向量数据库Milvus Cloud 成本

成本 AIGC 时代对于冷热储存的呼唤 成本一直是向量数据库获得更广泛使用的最大阻碍之一,这个成本来自两点: 储存,绝大多数向量数据库为了保证低延迟,需要把数据全量缓存到内存或者本地磁盘。在这个动辄百亿量级的AI 时代,意味着几十上百 TB 的资源消耗。 计算,数据需…

OCR版面分析-- PaddleOCR(python 文档解析提取)

1. 创建新的conda环境 # 在命令行输入以下命令,创建名为paddle_env的环境 # 此处为加速下载,使用清华源 conda create --name paddle_env python3.8 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ # 这是一行命令2. 激活刚创建…

全球视频会议软件巨头Zoom,率先引入后量子端到端加密

5月21日,Zoom Video Communications公司宣布,后量子端到端加密(E2EE)现已面向全球推出,适用于Zoom Workplace。目前,Zoom已将该功能加入Zoom Meetings,稍后将扩展至Zoom Phone和Zoom Rooms。 图…

数据中心大型AI模型网络需求

数据中心大型AI模型网络需求 随着Transformer的崛起和2023年ChatGPT的大规模应用,业界逐渐形成共识:遵循一定的规模效应原则,增加模型参数量能够显著提升模型性能。特别是在参数数量级跃升至数百亿乃至更高时,大型AI模型在语言理…