MySQL之性能剖析和Schema与数据类型优化(一)

性能剖析总结

  • 1.定义性能最有效的方法是响应时间
  • 2.如果无法测量就无法有效地优化,所以性能优化工作需要基于高质量、全方位及完整的响应时间测量
  • 3.测量的最佳开始点是应用程序,而不是数据库。即使问题出在底层的数据库,借助良好的测量也可以很容易地发现问题
  • 4.大多数系统无法完整地测量,测量有时候也会有错误的结果。但也可以想办法绕过一些限制,并得到好的结果(但是要能意识到所使用的方法的缺陷和不确定性在哪里)
  • 5.完整的测量会产生大量需要分析的数据,所以需要用到剖析器。这是最佳的工具,可以帮助将重要的问题冒泡到前面,这样就可以决定从哪里开始分析会比较好
  • 6.剖析报告是一种汇总信息,掩盖和丢弃了太多细节。而且它不会告诉你缺少了什么,所以完全依赖剖析报告也是不明智的
  • 7.有两种消耗时间的操作:工作或者等待。大多数剖析器只能测量因为工作而消耗的时间,所以等待分析有时候是很有用的补充,尤其是当CPU利用率很低但工作却一直无法完成的时候
  • 8.优化和提升是两回事。当继续提升的成本超过收益的时候,应当停止优化
  • 9.注意你的直觉,但应该只根据直觉来指导解决问题的思路,而不是用于确定系统的问题。决策应当尽量基于数据而不是感觉。

总的来说,解决性能问题的方法首先是要澄清问题,然后选择合适的技术来解答这些问题。如果你想尝试提升服务器的总体性能,那么一个比较好的七点是将所有查询记录到日志中,然后利用pt-query-digest工具生成系统级别的剖析报告。如果是要追查某些性能低下的查询,记录和剖析得方法也会有帮助。可以把精力放在寻找哪些消耗时间最多的、导致了糟糕的用户体验的,或者那些高度变化的,抑或有奇怪的响应时间直方图的查询。当找到了这些"坏"查询时,要钻取pt-query-digest报告中包含的该查询的详细信息,或者使用SHOW PROFILE及其他诸如EXPLAIN这样的工具。

如果找不到这些查询性能低下的原因,那么也可能时遇到了服务器级别的性能问题。这是,可以较高精度测量和回直服务器状态计数器的细节信息。如果通过这样的分析重现了问题,则应该通过同样的数据制定一个可靠的触发条件,来收集更多的诊断数据。多花费一点时间来确定可靠的触发条件,尽量避免漏检或者误报。如果已经可以捕获故障活动期间的数据,但还是无法找到其根本原因,则要么尝试捕获更多的数据,要么尝试寻求帮助。
我们无法完整地测量工作系统,但说到底它们都是某种状态机,所以只要足够细心,逻辑清晰并且坚持下去,通常来说都能得到想要的结果。要注意的时不要把原因和结果搞混了,而且在确认问题之前也不要随便针对系统做变动。
理论上纯粹的自顶向下的方法分析和详尽的测量只是理想的情况,而我们常常需要处理的是真实系统。真实系统是复杂且无法充分测量的,所以我们只能根据情况尽力而为。使用诸如pt-query-digest和MySQL企业监控器的查询分析其这样的工具并不完美,通常都不会给出问题根源的直接证据。但真的掌握了以后,已经足以完成大部分的优化诊断工作了。

Schema与数据类型优化

概述

良好的逻辑设计和物理设计是高性能的基石,应该根据系统将要执行的查询语句来设计schema,这往往需要权衡各种因素。例如,反范式的设计可以加快某些类型的查询,但同时可能使另一些类型的查询变慢。比如添加计数器和汇总表是一种很好的优化查询的方式,但这些表的维护成本可能会很高。MySQL独有的特性和实现细节对性能的影响也很大。

选择优化的数据类型

MySQL支持的数据类型非常多,选择正确的数据类型对于获取高性能至关重要。不管存储哪种类型的数据,下面几个简单的原则都有助于做出更好的选择。

  • 1.更好的通常更好
    一般情况下,应该尽量使用可以正确存储数据更小的数据类型(例如只需要存0~200,tinyint unsigned更好)。更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期也更少。
    但是要确保没有嘀咕需要存储的值范围,因为在schema中的多个地方增加数据类型的范围是一个非常耗时和痛苦的操作。如果无法确定哪个数据类型是最好的,就选择你认为不会超过范围的最小类型。(如果系统不是很忙或者存储的数据量不多,或者是在可以轻易修改设计的早期阶段,那之后修改数据类型也比较容易)
  • 2.简单就好
    简单数据类型的操作通常需要更少的CPU周期。例如,整型比字符操作代价更低,因为字符集和校对规则(排序规则)使字符比较比整型比较更复杂。有两个例子:一个是应该使用mySQL的内建类型(date,time,datetime)而不是字符串来存储日期和时间,另外一个是应该使用整型存储IP地址。
  • 3.尽量避免NULL
    很多表都包含可为NULL(空值)的列,即使应用程序并不需要保存NULL也是如此,这是因为可为NULL是列的默认属性。通常情况下最好指定列为NOT NULL,除非真的需要存储NULL值。如果查询中包含可为NULL的列,对MySQL来说更难优化,因为可为NULL的列使得索引、索引统计和值比较都更复杂。可为NULL的列会使用更多的存储空间,在MySQL里也需要特殊处理。当可为NULl的列被索引时,每个索引记录需要一个额外的字节,在MyISAM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。
    通常把可为NULl的列改为NOT NULL带来的性能提升比较小,所以(调优时)没有必要首先在现有schema中查找并修改掉这种情况,除非确定这回导致问题。但是,如果计划在列上键索引,就应该尽量避免设计成可为NULL的列。
    当然也有例外,例如值得一提的时,InnoDB使用单独的位(bit)存储NULL值,所以对于稀疏数据(很多值为NULL,只有少数行的列有非NULL值)有很好的空间效率。但这一点不适用于MyISAM

在为列选择数据类型时,第一步需要确定合适的大类型:数字、字符串、时间等。这通常是很简单的。但是我们会提到一些特殊的不是那么直观的例子。
下一步是选择具体类型。很多MySQL的数据类型可以存储相同类型的数据,这是存储的长度和范围不一样、允许的精度不同,或者需要的物理空间(磁盘和内存空间)不同,相同大类型的不同子类型数据有时也有一些特殊的行为和属性。
然而TIMESTAMP只使用DATETIME一半的存储空间,并且会根据时区变化,具有特殊的自动更新能力。另一方面,TIMESTAMP允许的时间范围要小得多,有时候它的特殊能力会成为阻碍。

整数类型

有两种类型的数字:整数(whole number)和实数(real number)。如果存储整数,可以使用这几种整数类型:TINYINT,SMALLINT, MEDIUMINT,INT,BIGINT.分别使用8,16,24,32,64存储空间。它们可以存储的值的范围从-2(N-1)到2(N-1)-1,其中N是存储空间的位数。
整数类型有可选的UNSIGNED属性,表示不允许负值,这大致可以使正数的上限提高已被。例如TINYINT UNSIGNED可以存储的范围是0255,而TINYINY的存储范围是-128127.
有符号和无符号类型使用相同的存储空间,并具有相同的性能,因此可以根据实际情况选择合适的类型。你的选择决定MySQL是怎么在内存和磁盘中保存数据的,然而,整数计算一半使用64位的BIGINT整数,即使在32位环境也是如此。(一些聚合函数是例外,它们使用DECIMAL或者DOUBLE进行计算)。
MySQL可以为整数类型指定宽度,例如INT(11),对大多数应用这是没有意义的,他不会限制值得合法范围,只是规定了MySQL的一些交互工具(例如MySQL命令行客户端)用来显示字符的个数。对于存储和计算来说INT(1)和INT(20)是相同的。

实数类型

实数是带有小数部分的数字。然而,它们不只是为了存储小数部分;也可以使用DECIMAL存储比BIGINT还大的整数。MySQL既支持精确类型,也支持不精确类型。
FLOAT和DOUBLE类型支持使用标准的浮点运算进行近似计算。如果需要直到浮点运算时怎么计算的,则需要研究所使用的平台的浮点数的具体实现。DECIMAL类型用于存储精确的小数。在MySQL 5.0和更高版本,DECIMAL类型支持精确计算。MySQL4.1及更早版本则使用浮点运算来实现DECIMAL的计算,这样做会因为精度损失导致一些奇怪的结果。在这些版本的MySQL中,DECIMAL只是一个"存储类型"。
因为CPU不支持对DECIMAL的直接计算,所以在MySQL5.0以及更高版本中,MySQL服务器自身实现了DECIMAL的高精度计算。相对而言,CPU直接支持原生浮点计算,所以浮点运算明显更快。
浮点和DECIMAL类型都可以指定精度。对DECIMAL列,可以指定小数点前后所允许的最大位数。这会影响列的空间消耗。MySQL5.0和更高版本将数字打包保存到一个二进制字符串中(每4个字节存9个数字)。例如DECIMAL(18,9)小数点两边将个存储9个数字,一共使用9个字节:小数点前的数字用4个字节,小数点后的数字用4个字节,小数点本身占1个字节。
MySQL5.0和更高版本中的DECIMAL类型允许最多65个数字。而早期的MySQL版本中,这个限制时254个数字,并且保存为未压缩的字符串(每个数字一个字节)。然而,这些(早期)版本实际上并不能在计算中使用这么大的数字,因为DECIMAL只是一种存储格式,在计算中DECIMAL会转换为DOUBLE类型。
有多种方法可以指定浮点列所需要的精度,这回使得MySQL悄悄选择不同的数据类型,或者在存储时对值进行取舍。这些精度定义时非标准的,所以建议只指定数据类型,不指定精度。
浮点类型在存储同样范围的值时,通常比DECIMAL使用更少的空间。FLOAT使用4个字节存储。DOUBLE只能用8个字节,相比FLOAT有更高的精度和更大的范围。和整数类型一样,能选择的只是存储类型;MySQL使用DOUBLE作为内部浮点计算的类型。
因为需要额外的空间和计算开销,所以应该尽量只在对小数进行精确计算时才使用DECIMAL——例如存储财务数据。但在数据量比较大的时候,可以高铝使用BIGINT代替DECIMAL,将需要存储的货币单位根据小数的位数乘以相应的倍数即可。假设要存储财务数据精确到万分之一,则可以把所有金额乘以一百万,然后将结果存储在BIGINT里,这样就可以同时避免浮点存储计算不精确和DECIMAL精确计算代价高的问题

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

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

相关文章

C++系列-友元

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 我们在之前的文章有提到友元&#xff0c;我们先来看下面的这段包含了友元的代码&#xff1a; ​​#define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace…

CLIP论文学习

学习来自B站bryanyzhu

jdk17安装教程详细(jdk17安装超详细图文)

2021年9月14日JDK17 发布&#xff0c;其中不仅包含很多新语言功能&#xff0c;而且与旧版 JDK 相比&#xff0c;性能提升也非常明显。与之前 LTS 版本的 JDK 8 和 JDK 11 相比&#xff0c;JDK17 的性能提升尤为明显&#xff0c;本文将教你如何安装 相比于JDK1.8&#xff0c;JD…

虚拟机网络设置为桥接模式后未显示网络

本方法为&#xff0c;VMware配置正确&#xff0c;但在尝试其他办法后未能成功解决的人提供一种方法 本机的虚拟机使用NAT模式正常使用 但是使用桥接模式后重启&#xff0c;未发现虚拟机内网络设置,详见下图&#xff1a; 使用 ifconfig 查看网络详情 发现没有ens33接口 查看硬…

双非本科,逆袭中大厂的 Java 学习路线

从零基础入门 Java&#xff0c;到最后秋招上岸&#xff0c;笔者也是花费了不少的经历&#xff0c;也走了很多弯路。这一篇文章会记录下真正有用的学习路线。 为什么要强调真正有用&#xff1f;网上的很多所谓从入门到求职&#xff0c;推荐的路线都超级长&#xff0c;零基础的同…

LeetCode198:打家劫舍

题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋存…

【学习笔记】Windows GDI绘图(六)图形路径GraphicsPath详解(中)

上一篇【学习笔记】Windows GDI绘图(五)图形路径GraphicsPath详解(上)介绍了GraphicsPath类的构造函数、属性和方法AddArc添加椭圆弧、AddBezier添加贝赛尔曲线、AddClosedCurve添加封闭基数样条曲线、AddCurve添加开放基数样条曲线、基数样条如何转Bezier、AddEllipse添加椭圆…

华为校招机试 - 最久最少使用缓存(20240508)

题目描述 无线通信移动性需要在基站上配置邻区(本端基站的小区 LocalCell 与周边邻基站的小区 NeighborCelI 映射)关系, 为了能够加速无线算法的计算效率,设计一个邻区关系缓存表,用于快速的通过本小区 LocalCell 查询到邻小区 NeighborCell。 但是缓存表有一定的规格限…

代码随想录-Day07

454. 四数相加 II 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < n nums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&#xff1a; 输入&#x…

系统磁盘高级管理、lvm例子、创建pv、创建VG、创建lv、磁盘扩展

LVM&#xff1a; 逻辑卷&#xff0c;动态调整分区大小&#xff0c;扩展性好 创建pv pvcreate &#xff1a; 将实体 partition 创建成为 PV &#xff1b; pvscan &#xff1a; 搜寻目前系统里面任何具有 PV 的磁盘&#xff1b; pvdisplay &#xff1a; 显示出目前系统上面…

GNSS仿真测试之三种常用坐标系与转换

作者介绍 在当今的全球导航卫星系统&#xff08;GNSS&#xff09;技术领域&#xff0c;仿真测试是评估和验证GNSS接收机性能的关键环节&#xff0c;全球导航卫星系统&#xff08;GNSS&#xff09;仿真测试是确保GNSS接收机和导航解决方案在实际部署前能够正确、可靠地工作的关键…

【git】学习记录: 贮藏功能

Git 贮藏修改是一种临时存储工作目录中已经修改但尚未提交的更改的机制。通过贮藏修改&#xff0c;你可以将当前的工作目录状态保存起来&#xff0c;以便你可以在之后的时间点重新应用这些更改&#xff0c;或者在不同的分支间切换时避免冲突。 要使用 Git 贮藏修改&#xff0c…

Linux(centos)常用命令

Linux&#xff08;Centos&#xff09;常用命令使用说明文档 切换到/home目录下 使用cd命令切换目录&#xff0c;例如&#xff1a; cd /home列出/home目录下的所有文件 使用ls命令列出目录下的文件和子目录&#xff0c;例如&#xff1a; ls /home新建目录dir1 使用mkdir命…

头歌OpenGauss数据库-I.复杂查询第1关:获取前N名成绩

本关任务&#xff1a;编写函数来实现获取前N名成绩的方法。 提示&#xff1a;前面的实验没有提供编写自定义函数的示例&#xff0c;需要参考OpenGauss数据库文档学习自定义函数的使用。 score表内容如下&#xff1a; IdScore13.5223.6534.2343.8554.2363.65 --#请在BEGIN - END…

python windows 开发.exe程序笔记

import win32api import win32gui import win32con import time import tkinter as tk## pyinstaller --onefile t4.py 将python 代码打包为windows可执行文件 .exe ## airtext 大漠 def clickGoogle():hw win32gui.FindWindow("Chrome_WidgetWin_1", "新标…

解决Redis 缓存雪崩(过期时间不一致) 和 缓存穿透(黑名单)

解决Redis 缓存雪崩&#xff08;过期时间不一致&#xff09; 和 缓存穿透&#xff08;黑名单&#xff09; public Product getdetailById(Integer id) {String key "product." id;// 查询黑名单中是否有该keyBoolean b hashOperations.hasKey(PROODUCT_DETAIL_B…

算法 Hw7

Hw 7 Graph Algorithm 1 Edge detection2 Reachability3 Bitonic shortest paths 1 Edge detection 由 Cut Property 可知&#xff1a;如果 e 是从某个集合 S 到补集 V−S 的开销最小的边&#xff0c;则 e 一定所有最小生成树中。 由 Cycle Property 可知&#xff1a;如果 e 是…

Gradle常见问题及总结

使用android studio开发项目&#xff0c;难免遇到gradle相关的错误&#xff0c;在此总结。 gradle插件与gradle home版本关系错误 参考更新 Gradle Gradle下载太慢 Index of /gradle/ (tencent.com) 是国内下载地址,手动下载对应版本即可 缓存不刷新 问题描述 maven发布…

jenkins插件之xunit

分析测试工具执行的结果&#xff0c;并图形化&#xff0c;比如phpunit&#xff0c;phpstan,可分析junit格式的结果 安装jenkins插件 搜索xunit并安装 项目配置 配置 - Build Steps 您的项目 - 配置 - Build Steps, 新增 Run with timeout 超时时间根据实际情况配置 Build…

Day38 贪心算法part05

LC435无重叠区间(未掌握) 思路&#xff1a;先对数组进行排序&#xff0c;找到非重叠的区间的个数&#xff0c;然后区间的总数减去非重叠区间的个数即是需要移除的区间的个数与LC452用最少数量的箭引爆气球类似&#xff0c;但是不同的是[1,2]和[2,3]在此题并不是重叠区间但是在…