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

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.mzph.cn/web/13483.shtml

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

相关文章

Spring Cloud整合Sentinel

1、引入依赖 链接: 点击查看依赖关系 父pom <spring.cloud.version>Hoxton.SR12</spring.cloud.version> <spring.cloud.alibaba.version>2.2.10-RC1</spring.cloud.alibaba.version>Sentinel应用直接引用starter <dependency><groupId&…

【UE5.1】* 动画重定向 (让你的角色可以使用小白人全部动画)

前言 这里以小白人动画重定向给商城资产“Adventure Character”中的角色为例&#xff0c;阐述如何使用UE5.1进行动画重定向。 步骤 1. 创建一个IK绑定 这里选择小白人的骨骼网格体 这里命名为“IKRig_Mannequin” 2. 再新建一个IK绑定&#xff0c;这里使用你要替换给的角色…

MyBatis入门——MyBatis XML配置文件(3)

目录 一、配置连接字符串和MyBatis 二、写持久层代码 1、添加 mapper 接口 2、添加 USerInfoXmlMapper.xml 3、测试类代码 三、增删改查操作 1、增&#xff08;Insert&#xff09; 返回自增 id 2、删&#xff08;Delete&#xff09; 3、改&#xff08;update&#xf…

软考--试题六--中介者模式(Mediator)

中介者模式(Meditor) 意图 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互 结构 适用性 1、一组对象以定义良好但是复杂的方式进行通信&#xff0c;产生的相互依赖关…

民国漫画杂志《时代漫画》第17期.PDF

时代漫画17.PDF: https://url03.ctfile.com/f/1779803-1248612629-85326d?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps:资源来源网络&#xff01;

力扣HOT100 - 1143. 最长公共子序列

解题思路&#xff1a; 动态规划 class Solution {public int longestCommonSubsequence(String text1, String text2) {int m text1.length(), n text2.length();int[][] dp new int[m 1][n 1];for (int i 1; i < m; i) {char c1 text1.charAt(i - 1);for (int j 1…

深度学习之基于YoloV5的动物识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与目标 在生态研究、动物保护、以及畜牧业等多个领域&#xff0c;对动物进行准确、高效的识别都具有重…

形态学操作:腐蚀、膨胀、开闭运算、顶帽底帽变换、形态学梯度区别与联系

一、总述相关概念 二、相关问题 1.形态学操作中的腐蚀和膨胀对图像有哪些影响&#xff1f; 形态学操作中的腐蚀和膨胀是两种常见的图像处理技术&#xff0c;它们通过对图像进行局部区域的像素值替换来实现对图像形状的修改。 腐蚀操作通常用于去除图像中的噪声和细小的细节&a…

单链表oj

练习 1. 删除val节点 oj链接 这道题最先想出来的方法肯定是在遍历链表的同时删除等于val的节点&#xff0c;我们用第二中思路:不等于val的节点尾插&#xff0c;让后返回新节点。代码如下&#xff1a; struct ListNode* removeElements(struct ListNode* head, int val) {str…

软考高级-信息系统项目管理师案例题选择题做题总结

1.不应该只会建立变更和配置管理的规则&#xff0c;应该建立变更控制流程 2.变更的影响不应该只由工程师评估 3.没有对变更和修改进行记录 4.变更完成后&#xff0c;客户没有对变更进行验证 5.变更没有通知相关人员 6.变更没有和配置管理关联 7.项目变更管理的工作流程&#xf…

SOLIDWORKS科研版的介绍

SOLIDWORKS科研版的介绍 针对研究项目充分利用软件功能&#xff0c;无任何限制访问有关工程和科学的最新技术&#xff0c;并与世界各地的其他用户进行交流。 SOLIDWORKS科研版可为研究人员提供有关 SOLIDWORKS 设计和科学工程技术的最新知识&#xff0c;并使他们与世界范围内的…

08.CNN

文章目录 Observation 1Pooling - Max PoolingFlattenApplication&#xff1a;Playing Go使用验证集选择模型食物分类 Observation 1 Pooling - Max Pooling Pooling主要为了降低运算量&#xff0c;现在一般不用了&#xff0c;全convolution Flatten Application&#xff1a;P…

Linux|如何在 awk 中使用流控制语句

引言 当您从 Awk 系列一开始回顾我们迄今为止介绍的所有 Awk 示例时&#xff0c;您会注意到各个示例中的所有命令都是按顺序执行的&#xff0c;即一个接一个。但在某些情况下&#xff0c;我们可能希望根据某些条件运行一些文本过滤操作&#xff0c;这就是流程控制语句的方法。 …

鲸尾识别获奖方案总结

文章目录 1st solution(classification)2nd place code, end to end whale Identification model3rd place solution with code: ArcFace4th Place Solution: SIFT Siamese5th solution blog post code -Siamese7th place Pure Magic thanks Radek solution: classification9…

QGIS DEM数据快速获取

背景 Dem 是非常重要的数据&#xff0c;30 m 的精度也是最容易获取的&#xff0c;目前有很多种方式可以获取&#xff0c;比如地理空间数据云&#xff0c;今天介绍用 QGIS插件获取。 这种方式的最大优势是方便快捷。 插件下载与安装 插件-管理并安装插件-搜索下载 OpenTopogr…

linux:信号深入理解

文章目录 1.信号的概念1.1基本概念1.2信号的处理基本概念1.3信号的发送与保存基本概念 2.信号的产生2.1信号产生的五种方式2.2信号遗留问题(core,temp等) 3.信号的保存3.1 信号阻塞3.2 信号特有类型 sigset_t3.3 信号集操作函数3.4 信号集操作函数的使用 4.信号的处理4.1 信号的…

Python实现天气数据采集

Python实现天气数据采集 一、需求介绍二、完整代码一、需求介绍 本次天气数据采集的需求是获取每日的最高温、最低温、风力、风向、天气状况、AQI指数,如图所示,完整代码附后: 本次采集的目标网址是2345天气网: 上图的URL中,beijing是城市名称的缩写,54511即为城市代码…

科技引领未来:高速公路可视化

高速公路可视化监控系统利用实时视频、传感器数据和大数据分析&#xff0c;通过图扑 HT 可视化展示交通流量、车速、事故和路况信息。交通管理人员可以实时监控、快速响应突发事件&#xff0c;并优化交通信号和指挥方案。这一系统不仅提高了道路安全性和车辆通行效率&#xff0…

vue3结合element-plus之如何优雅的使用表格

背景 表格组件的使用在后台管理系统中是非常常见的,但是如果每次使用表格我们都去一次一次地从 element-plus 官网去 复制、粘贴和修改成自己想要的表格。 这样一来也说得过去,但是如果我们静下来细想不难发现,表格的使用都是大同小异的,每次都去复制粘贴,对于有很多表格…

vue3封装ElementUI plus Dialog弹窗

因为ElementuiPlus的dialog弹框的初始样式不太好看,而公司要求又要好看,本来是已经实现了,但是后来想想了发现封装完dialog的其他功能也要,所以特此记录一下 方案一 思路:封装一个组件,将所有新增的参数引入el-dialog 参数中,实现参数共用 新建一个组件,将官网暴露的属性全部引…