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

news2024/11/20 8:39:48

Schema与数据类型优化

特殊类型数据

某些类型的数据并不直接与内置类型一致。低于秒级精度的时间戳就是一个例子。另外一个例子是一个IPv4地址。人们经常使用VARCHAR(15)列存储IP地址。然而,它们实际上是32位无符号整数。不是字符串。用小数点将地址分成四段的表示方法只是为了让人们阅读容易。所以应该用无符号整数存储IP地址。MySQL提供INET_ATON()和INET_NTOA()函数在这两种表示方法之间转换

MySQL schema设计种的陷阱

虽然有一些普遍的好或坏的设计原则,但也有一些问题是由MySQL的实现机制导致的,这意味着有可能犯一些只在MySQL下发生的特定错误。接下来我们讨论下设计MySQL的schema的问题。这也许会帮助你避免错误,并且选择在MySQL特定实现下工作得更好的替代方案。

  • 1.太多的列。
    MySQL的存储引擎API工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列。从行缓冲种将编码过的列转换成行数据结构的操作代价是非常高的。MyISAM的定长行结构实际上与服务器层的行结构正好匹配,所以不需要转换。然而,MyISAM的变长行结构实际和INnoDB的行结构则总是需要转换。转换的代价依赖于列的数量。有一个CPU占用非常高的例子,发现客户使用了非常宽的表(数千个字段),然而只有一小部分列会实际用到,这时转换的代价就非常高。如果计划使用数千个字段,必须意识到服务器的性能运行特征会有一些不同。
  • 2.太多的关联
    所谓的"实体 - 属性 - 值"(EAV)设计模式是一个常见的糟糕设计模式,尤其是在MySQL下不能靠谱地工作。MySQL限制了每个关联操作最多只能有61张表,但是EAV数据库需要许多自关联。不少EAV数据库最后超过了这个限制。事实上在许多关联少于61张表地情况下,解析和优化查询地代价也会成为MySQL的问题。一个粗略的经验法则,如果希望查询执行得快速且并发性好,单个查询最好在12个表以内做关联
  • 3.全能的枚举
    注意防止过度使用枚举(ENUM).下面是一个例子
CREATE TABLE ......(country enum('','1','2','3',..........,'31'))

这种模式的schema设计非常凌乱。这么使用枚举值类型也许在任何支持枚举类型的数据库都是一个有问题的设计方案,这里应该用整数作为外键关联到字典表或者查找表来查找具体值。但是在MySQL中,当需要在枚举列表中增加一个新的国家时,就要做一次ALTER TABLE操作。在MySQL5.0以及更早的版本中ALTER TABLE是一种阻塞操作;即使在5.1和更新版本中,如果不是在列表的末尾增加值也会一样需要ALTER TABLE

  • 4.变相的枚举
    枚举(ENUM)列允许在列中存储一组定义值中的单个值,集合(SET)列则允许在列中存储一组定义值中的一个或多个值。有时候可能比较容易导致混乱。这是一个例子。
CREATE TABLE ....(is_default set('Y', 'N') NOT NULL default 'N')

如果这里真和假两种情况不会同时出现,那么毫无疑问应该使用枚举列代替集合列

  • 5.非此发明(Not Invent Here)的NULL
    之前提到避免使用NULL的好处,并且建议尽可能地考虑替代方案。即使需要存储一个事实上的"空值"到列表中时,也不一定非得使用NULL.也许可以使用0、某个特殊值,或者空字符串作为代替。但是遵循这个原则也不要走极端。当确实需要表示未知值时也不要害怕使用NULL.在一些场景中,使用NULL可能回避某个神奇常数更好.从特定类型的值域中选择一个不可能的值。例如用-1代表一个未知的整数,可能导致代码复杂很多,并容易引入bug,还可能会让事情变得一团糟。处理NULL确实不容易,但有时候回避它的替代方案更好:
CREATE TABLE ... (dt DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00')

伪造的全0值可能导致很多问题(可以配置MySQL的SQL_MODE来进制不可能的日期,对于新应用这是个非常好的实践经验,他不会让创建的数据库里充满不可能的值)。值得一提的是,MySQL会在索引中存储NULL值,而Oracle则不会

范式和反范式

对于任何给定的数据通常都有很多种表示方法,从完全的范式化到完全的反范式化,以及两者的折中。在范式化的数据库种,每个事实数据会出现并且只出现一次。相反,在反范式化的数据库种,信息是冗余的,可能会存储在多个地方。下面以经典的"雇员,部门,部门领导"的例子开始:
如图所示,这个schema的问题是修改数据时可能发生不一致。假如Say Brown解人Accounting部门的领导,需要修改多行数据来反应这个变化,这是很痛苦的事并且容易引入错误。如果“Jones”这一行显示部门的领导跟"Brown"这一行的不一样,就没办法直到哪个是对的。这就像有句老话说的:“一个人有两块手标就永远不知道实践”。此外,这个设计在没有雇员信息的情况下就无法表示一个部门——如果我们删除了所有Accounting部门的雇员,我们就失去了关于这个部门本身的所有记录。要避免这个问题,我们需要对这个表进行范式化,方式是拆分雇员和部门项。拆分以后可以用下面两张表来分别存储雇员表:
这样设计的两张表符合第二范式,在很多情况下做到这一步已经足够好了,然而,第二范式只是许多可能的范式种的一种

在这个例子种我们使用姓(Last Name)作为主键,因为这是数据的"自然标识"。从实践来看,无论如何都不应该这么用。这既不能保证唯一性,而且用一个很长的字符串作为主键是很糟糕的主意。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

范式的优点和缺点

当为性能问题而寻求帮助时,经常会被建议对schema进行范式化设计,尤其是写密集的场景。这通常是个好建议。因为下面这些原因,范式化通常能够带来好处:

  • 1.范式化的更新操作通常比反范式化要快
  • 2.当数据较好地范式化时,就只有很少或者没有重复数据,所以只需要修改更少地数据
  • 3.范式化地表通常更小,可以更好地放在内存里,所以执行操作会更快
  • 4.很少有多余地数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY 语句

还是前面地例子:在非范式化的结构种鄙视使用DISTINCT 或者GROUP BY 才能获得一份唯一的部门列表,如果部门(DEPARTMENT)是一张单独的表,则只需要简单的查询这张表就行了.
范式化设计的schema的缺点是通常需要关联,稍微复杂一些的查询语句在符合范式的schema上都可能需要至少一次的关联,也许更多。这不但代价昂贵,也可能使一些索引策略无效。例如,范式化可能将列放在不同的表种,而这些列如果在一个表种本可以属于同一个索引

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

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

相关文章

ThreadLocal为什么会导致内存泄漏?

问题引出: ThreadLocal是为了解决什么问题而产生的? ThreadLocal发生内存泄漏的根本原因是什么? 如何避免内存泄漏的发生?定义 为了解决多个线程同时操作程序中的同一个变量而导致的数据不一致性的问题。   假设现在有两个线程A…

ASP+ACCESS教师档案管理系统

3.1 系统功能模块图 3.2 E-R模型图 3.3 系统使用流程图 3.4 各个模块功能简介: 本系统分为五个功能模块,它们分别是教师信息录入模块、教师信息修改模块、教师信息查询模块、教师信息打印模块。 下面分别介绍各个模块的功能用途&#x…

社交媒体数据恢复:soma messenger

步骤1:检查备份文件 首先,我们需要确认您是否已开启Soma Messenger的自动备份功能。若已开启,您可以在备份文件中找到丢失的数据。 步骤2:清除缓存并重启应用 有时候,清除Soma Messenger的缓存文件可以帮助恢复丢失的…

el-table 划入划出方法

<template><div><el-table :data"tableData" style"width: 100%" cell-mouse-enter"handleMouseEnter" cell-mouse-leave"handleMouseLeave"><el-table-column prop"ddd" label"日期2" widt…

Unity Physics入门

概述 在unity中物理属性是非常重要的&#xff0c;它可以模拟真实物理的效果在unity中&#xff0c;其中的组件是非常多的&#xff0c;让我们来学习一下这部分的内容吧。 Unity组件入门篇总目录----------点击导航 Character Controller(角色控制) 说明&#xff1a;组件是Unity提…

数据结构------二叉树经典习题2

博主主页: 码农派大星. 关注博主带你了解更多数据结构知识 1.非递归的前序遍历 1.用栈来实现 2,前序遍历是根左右, 先是根节点入栈,,然后不为空时向左遍历,当为空时就返回向右遍历,右为空时直接出栈,依次循环即可. public void preOrderNot(TreeNode root){Stack<TreeNo…

点云处理中阶 Octree模块

一、什么是Octree 八叉树&#xff08;Octree&#xff09;是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素&#xff0c;每个节点有八个子节点&#xff0c;这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点作为节点的分叉中…

Java进阶学习笔记6——继承的介绍

继承的学习目标&#xff1a; 认识继承&#xff1b; 继承的好处、应用场景 什么是继承&#xff1f; Java中提供了一个关键字extends&#xff0c;用这个关键字&#xff0c;可以让一个类和另外一个类建立父子关系。 继承的特点: 子类能继承父类的非私有成员&#xff08;成员变…

【JavaEE】加法计算器与用户登录实战演练

目录 综合练习加法计算器1. 准备工作2. 约定前后端交互接口3. 服务器代码 用户登录1. 准备工作2. 约定前后端交互接口3. 服务器代码4. 调整前端页面代码 综合练习 理解前后端交互过程接⼝传参, 数据返回, 以及⻚⾯展⽰ 加法计算器 需求: 输⼊两个整数, 点击"点击相加&q…

windows 7 10 11快捷键到启动页面

1.快速打开用户启动文件夹 shell:startup 方式2&#xff1a;快速打开系统启动文件夹 shell:Common Startup shell:Common Startup

dubbo复习:(7)使用sentinel对dubbo服务进行限流

一、下载sentinel-dashboard 并启动 java -Dserver.port8080 -Dcsp.sentinel.dashboard.serverlocalhost:8080 -Dproject.namesentinel-dashboard -jar sentinel-dashboard.jar二、在spring boot应用中增加sentinel相关依赖 <dependency><groupId>com.alibaba.csp…

Hadoop数据压缩和压缩案例实操

文章目录 数据压缩概述MR支持的压缩编码格式和各自优缺点压缩实操案例1.Map输出端采用压缩2.Reduce输出端采用压缩 数据压缩概述 Hadoop数据压缩是一种通过特定的算法来减小计算机文件大小的机制。这种机制在Hadoop中尤其重要&#xff0c;因为它可以有效减少底层存储系统&…

Docker 模块在宝塔中怎么使用

么是 Docker&#xff1f; Docker 是一个用于开发、发布和运行应用程序的开放平台。Docker 使您能够将应用程序与基础架构分离&#xff0c;以便您可以快速交付软件。使用 Docker&#xff0c;您可以像管理应用程序一样管理基础设施。通过利用 Docker 快速交付、测试和部署代码的方…

【产品经理】输出

引言&#xff1a;        在最近频繁的产品管理职位面试中&#xff0c;我深刻体会到了作为产品经理需要的不仅仅是对市场和技术的敏锐洞察&#xff0c;更多的是在复杂多变的环境中&#xff0c;如何运用沟通、领导力和决策能力来引导产品从概念走向市场。这一系列博客将分享…

hot100 -- 回溯(上)

目录 &#x1f35e;科普 &#x1f33c;全排列 AC DFS &#x1f6a9;子集 AC DFS &#x1f382;电话号码的字母组合 AC DFS &#x1f33c;组合总和 AC DFS &#x1f35e;科普 忘记 dfs 的&#xff0c;先看看这个&#x1f447; DFS&#xff08;深度优先搜索&#xf…

使用 Flask 和 Celery 构建异步任务处理应用

文章目录 什么是 Flask&#xff1f;什么是 Celery&#xff1f;如何在 Flask 中使用 Celery&#xff1f;步骤 1&#xff1a;安装 Flask 和 Celery步骤 2&#xff1a;创建 Flask 应用程序步骤 3&#xff1a;运行 Celery Worker步骤 4&#xff1a;启动 Flask 应用程序 结论 在构建…

SQLiteOpenHelper数据库帮助器

SQLiteOpenHelper数据库帮助器是Android提供的数据库辅助工具。 1、继承SQLiteOpenHelper类&#xff0c;需要重写onCreate和onUpgrade两个方法 案例&#xff1a;实现增删改查 package com.example.databases_text;import android.app.PictureInPictureParams; import androi…

maven打包报错:MalformedInputException: Input length = 1

maven 打包时报错&#xff1a; [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.3.1:resources (default-resources) on project ec-work-mes: filtering /Users/ecmaster/svn/ecmaster/ynmk/ynmk-mes/ec-work/ec-work-mes/src/main/resou…

【问题处理】maven一直提示artemis-http-client-1.1.8.jar报错(2024-05-25)

项目使用了视频监控&#xff0c;里面涉及到海康威视的视频监控。 问题&#xff1a; pom在导入maven时&#xff0c;报错“Could not find artifact com.artemis:http-client:jar:1.1.8 ” 原因&#xff1a; 根据平台提供的maven地址&#xff0c;填写进pom文件中&#xff0c;编…

从0开始linux(3)——如何读写文件

欢迎来到博主的专栏——从0开始linux 博主ID&#xff1a;代码小豪 文章目录 创建普通文件用文本编辑器nano写入文件如何读取文件cat命令less命令head和tail 我们前面已经了解和如何操作文件&#xff0c;但是目前认识的文件类型分为两类&#xff0c;一类是目录文件、另一类是普通…