数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

mysql数据库优化五步走


发布日期:2022年06月07日
 
mysql数据库优化五步走

:磁盘寻道能力以高速硬盘(转/秒)理论上每秒寻道这是没有办法改变的优化的方法是用多个硬盘或者把数据分散存储

:硬盘的读写速度这个速度非常的快这个更容易解决可以从多个硬盘上并行读写

:cpucpu处理内存中的数据当有相对内存较小的表时这是最常见的限制因素

:内存的限制当cpu需要超出适合cpu缓存的数据时缓存的带宽就成了内存的一个瓶颈不过现在内存大的惊人一般不会出现这个问题

第二步: (本人使用的是学校网站的linux平台(Linux A mdk ))

:调节服务器参数

用shell>mysqldhelp这个命令声厂一张所有mysql选项和可配置变量的表输出以下信息:

possible variables for optionsetvariable(o) are:

back_log current value: //要求mysql能有的连接数量back_log指出在mysql暂停接受连接的时间内有多少个连接请求可以被存在堆栈中

connect_timeout current value: //mysql服务器在用bad handshake(不好翻译)应答前等待一个连接的时间

delayed_insert_timeout current value: //一个insert delayed在终止前等待insert的时间

delayed_insert_limit current value: //insert delayed处理器将检查是否有任何select语句未执行如果有继续前执行这些语句

delayed_queue_size current value: //为insert delayed分配多大的队

flush_time current value: //如果被设置为非那么每个flush_time 时间所有表都被关闭

interactive_timeout current value: //服务器在关上它之前在洋交互连接上等待的时间

join_buffer_size current value: //用与全部连接的缓沖区大小

key_buffer_size current value: //用语索引块的缓沖区的大小增加它可以更好的处理索引

lower_case_table_names current value: //

long_query_time current value: //如果一个查询所用时间大于此时间slow_queried计数将增加

max_allowed_packet current value: //一个包的大小

max_connections current value: //允许同时连接的数量

max_connect_errors current value: //如果有多于该数量的中断连接将阻止进一步的连接可以用flush hosts来解决

max_delayed_threads current value: //可以启动的处理insert delayed的数量

max_heap_table_size current value: //

max_join_size current value: //允许读取的连接的数量

max_sort_length current value: //在排序blob或者text时使用的字节数量

max_tmp_tables current value: //一个连接同时打开的临时表的数量

max_write_lock_count current value: //指定一个值(通常很小)来启动mysqld使得在一定数量的write锁定之后出现read锁定

net_buffer_length current value: //通信缓沖区的大小在查询时被重置为该大小

query_buffer_size current value: //查询时缓沖区大小

record_buffer current value: //每个顺序扫描的连接为其扫描的每张表分配的缓沖区的大小

sort_buffer current value: //每个进行排序的连接分配的缓沖区的大小

table_cache current value: //为所有连接打开的表的数量

thread_concurrency current value: //

tmp_table_size current value: //临时表的大小

thread_stack current value: //每个线程的大小

wait_timeout current value: //服务器在关闭它之前的一个连接上等待的时间

根据自己的需要配置以上信息会对你帮助

第三:

:如果你在一个数据库中创建大量的表那么执行打开关闭创建(表)的操作就会很慢 :mysql使用内存

a: 关键字缓存区(key_buffer_size)由所有线程共享

b: 每个连接使用一些特定的线程空间一个栈(默认为k变量thread_stack)一个连接缓沖区(变量net_buffer_length)和一个结果缓沖区(net_buffer_length)特定情况下连接缓沖区和结果缓沖区被动态扩大到max_allowed_packet

c:所有线程共享一个基存储器

d:没有内存影射

e:每个做顺序扫描的请求分配一个读缓沖区(record_buffer)

f:所有联结均有一遍完成并且大多数联结甚至可以不用一个临时表完成最临时的表是基于内存的(heap)表

g:排序请求分配一个排序缓沖区和个临时表

h:所有语法分析和计算都在一个本地存储器完成

i:每个索引文件只被打开一次并且数据文件为每个并发运行的线程打开一次

j:对每个blob列的表一个缓沖区动态的被扩大以便读入blob值

k:所有正在使用的表的表处理器被保存在一个缓沖器中并且作为一个fifo管理

l:一个mysqladmin flushtables命令关闭所有不在使用的表并且在当前执行的线程结束时标记所有在使用的表准备关闭

:mysql锁定表

mysql中所有锁定不会成为死锁 wirte锁定: mysql的锁定原理:a:如果表没有锁定那么锁定;b否则把锁定请求放入写锁定队列中

read锁定: mysql的锁定原理:a:如果表没有锁定那么锁定;b否则把锁定请求放入读锁定队列中

有时候会在一个表中进行很多的selectinsert操作可以在一个临时表中插入行并且偶尔用临时表的记录更新真正的表

a:用low_priority属性给一个特定的insertupdate或者delete较低的优先级

b:max_write_lock_count指定一个值(通常很小)来启动mysqld使得在一定数量的write锁定之后出现read锁定

c:通过使用set sql_low_priority_updates=可以从一个特定的线程指定所有的更改应该由较低的优先级完成

d:用high_priority指定一个select

e:如果使用insertselect出现问题使用myisam表因为它支持因为它支持并发的select和insert

:最基本的优化是使数据在硬盘上占据的空间最小如果索引做在最小的列上那么索引也最小实现方法:

a:使用尽可能小的数据类型

b:如果可能声明表列为NOT NULL

c:如果有可能使用变成的数据类型如varchar(但是速度会受一定的影响)

d:每个表应该有尽可能短的主索引 e:创建确实需要的索引

f:如果一个索引在头几个字符上有唯一的前缀那么仅仅索引这个前缀mysql支持在一个字符列的一部分上的索引

g:如果一个表经常被扫描那么试图拆分它为更多的表

第四步

:索引的使用索引的重要性就不说了功能也不说了只说怎么做 首先要明确所有的mysql索引(primaryuniqueindex)在b树中有存储索引主要用语:

a:快速找到where指定条件的记录 b:执行联结时从其他表检索行 c:对特定的索引列找出max()和min()值

d如果排序或者分组在一个可用键的最前面加前缀排序或分组一个表

e一个查询可能被用来优化检索值而不用访问数据文件.如果某些表的列是数字型并且正好是某个列的前缀为了更快值可以从索引树中取出

存储或者更新数据的查询速度 grant的执行会稍稍的减低效率.

mysql的函数应该被高度的优化.可以用benchmark(loop_countexpression)来找出是否查询有问题

select的查询速度如果想要让一个select...where...更快我能想到的只有建立索引.可以在一个表上运行myisamchk--analyze来更好的优化查询.可以用myisamchk--sort-index--sort-records=1来设置用一个索引排序一个索引和数据.

mysql优化where子句

删除不必要的括号

((a AND b) AND c OR (((a AND b) AND (a AND d))))>(a AND b AND c) OR (a AND b AND c AND d)

:使用常数

(ab> AND b=c AND a=

:删除常数条件

(b>= AND b=) OR (b= AND =) OR (b= AND =) >b= OR b=

:索引使用的常数表达式仅计算一次

在一个表中没有一个where的count(*)直接从表中检索信息

:所有常数的表在查询中在任何其他表之前读出

:对外联结表最好联结组合是尝试了所有可能性找到的

如果有一个orderby字句和一个不同的groupby子句或者orderby或者groupby包含不是来自联结的第一个表的列那么创建一个临时表

:如果使用了sql_small_result那么msyql使用在内存中的一个表

:每个表的索引给查询并且使用跨越少于30%的行的索引.

在每个记录输出前跳过不匹配having子句的行

优化leftjoin

在mysql中a left join b按以下方式实现

a表b依赖于表a

b表a依赖于所有用在leftjoin条件的表(除了b)

c所有leftjoin条件被移到where子句中

d进行所有的联结优化除了一个表总是在所有他依赖的表后读取.如果有一个循环依赖那么将发生错误

e进行所有的标准的where优化 f如果在a中有一行匹配where子句但是在b中没有任何匹配leftjoin条件那么在b中生成的所有设置为NULL的一行

g如果使用leftjoin来找出某些表中不存在的行并且在where部分有column_name IS NULL测试(column_name为NOT NULL列).那么mysql在它已经找到了匹配leftjoin条件的一行后将停止在更多的行后寻找

优化limit

a如果用limit只选择一行当mysql需要扫描整个表时它的作用相当于索引

b如果使用limit#与orderbymysql如果找到了第#行将结束排序而不会排序正个表

c当结合limit#和distinct时mysql如果找到了第#行将停止

d只要mysql已经发送了第一个#行到客户mysql将放弃查询

elimit 一直会很快的返回一个空集合.

f临时表的大小使用limit#计算需要多少空间来解决查询

优化insert

插入一条记录的是由以下构成

a:连接(3)

b:发送查询给服务器(2)

c:分析查询(2)

d:插入记录(1*记录大小)

e插入索引(1*索引)

f关闭(1)

以上数字可以看成和总时间成比例

改善插入速度的一些方法

如果同时从一个连接插入许多行使用多个值的insert这比用多个语句要快

如果从不同连接插入很多行使用insertdelayed语句速度更快

: 用myisam如果在表中没有删除的行能在selects正在运行的同时插入行

: 当从一个文本文件装载一个表时用loaddatainfile.这个通常比insert快

:可以锁定表然后插入--主要的速度差别是在所有insert语句完成后索引缓沖区仅被存入到硬盘一次.一般与有不同的insert语句那样多次存入要快.如果能用一个单个语句插入所有的行锁定就不需要.锁定也降低连接的整体时间.但是对某些线程最大等待时间将上升.例如

thread does inserts

thread and does insert

thread does inserts

如果不使用锁定4将在1和5之前完成.如果使用锁定将可能在1和5之后完成.但是整体时间应该快40%.因为insertupdatedelete操作在mysql中是很快的通过为多于大约5次连续不断的插入或更新一行的东西加锁将获得更好的整体性能.如果做很多一行的插入可以做一个locktables偶尔随后做一个unlocktables(大约每1000行)以允许另外的线程存取表.这仍然将导致获得好的性能.loaddatainfile对装载数据仍然是很快的.

为了对loaddatainfile和insert得到一些更快的速度扩大关键字缓沖区.

7优化update的速度

它的速度依赖于被更新数据的大小和被更新索引的数量

使update更快的另一个方法是推迟修改然后一行一行的做很多修改.如果锁定表做一行一行的很多修改比一次做一个快

8优化delete速度

删除一个记录的时间与索引数量成正比.为了更快的删除记录可以增加索引缓存的大小 从一个表删除所有行比删除这个表的大部分要快的多

第五步

选择一种表类型 静态myisam

这种格式是最简单且最安全的格式它是磁盘格式中最快的.速度来自于数据能在磁盘上被找到的难易程度.当锁定有一个索引和静态格式的东西是它很简单只是行长度乘以数量.而且在扫描一张表时每次用磁盘读取来读入常数个记录是很容易的.安全性来源于如果当写入一个静态myisam文件时导致计算机down掉myisamchk很容易指出每行在哪里开始和结束因此它通常能收回所有记录除了部分被写入的记录.在mysql中所有索引总能被重建

动态myisam

这种格式每一行必须有一个头说明它有多长.当一个记录在更改期间变长时它可以在多于一个位置上结束.能使用optimizetablename或myisamchk整理一张表.如果在同一个表中有像某些varchar或者blob列那样存取/改变的静态数据将动态列移入另外一个表以避免碎片.

压缩myisam用可选的myisampack工具生成

内存

这种格式对小型/中型表很有用.对拷贝/创建一个常用的查找表到洋heap表有可能加快多个表联结用同样数据可能要快好几倍时间.

select tablenameatablenamea from tablenametablanemtablename where

tablanemea=tablenamea and tablenamea=tablenamea and tablenamec!=;

为了加速它可以用tablename和tablename的联结创建一个临时表因为用相同列(tablenamea)查找.

CREATETEMPORARYTABLEtest TYPE=HEAP

SELECT

tablenamea as atablenamea as a

FROM

tablenamtablename

WHERE

tablenamea=tablenamea and c=;

SELECT tablenameatesta from tablenametest where tablenamea=testa;

SELECT tablenameatestafrom tablenametest where tablenamea=testa and ;

静态表的特点

默认格式.用在表不包含varcharblobtext列的时候

所有的charnumeric和decimal列填充到列宽度

非常快

容易缓沖

容易在down后重建因为记录位于固定的位置

不必被重新组织(用myisamchk)除非是一个巨量的记录被删除并且优化存储大小

通常比动态表需要更多的存储空间

动态表的特点

如果表包含任何varcharblobtext列使用该格式

所有字符串列是动态的

每个记录前置一个位.

通常比定长表需要更多的磁盘空间

每个记录仅仅使用所需要的空间如果一个记录变的很大它按需要被分成很多段这导致了记录碎片

如果用超过行长度的信息更新行行被分段.

在系统down掉以后不好重建表因为一个记录可以是多段

对动态尺寸记录的期望行长度是3+(numberofcolumns+7)/8+(number of char columns)+packed size of numeric columns+length of strings +(number of NULL columns+)/

对每个连接有6个字节的惩罚.无论何时更改引起记录的变大都有一个动态记录被连接.每个新连接至少有20个字节因此下一个变大将可能在同一个连接中.如果不是将有另外一个连接.可以用myisamchk-恶毒检查有多少连接.所有连接可以用myisamchk r删除.

压缩表的特点

一张用myisampack实用程序制作的只读表.

解压缩代码存在于所有mysql分发中以便使没有myisampack的连接也能读取用myisampack压缩的表

占据很小的磁盘空间

每个记录被单独压缩.一个记录的头是一个定长的(1~~3个字节)这取决于表的最大记录.每列以不同的方式被压缩.一些常用的压缩类型是

a:通常对每列有一张不同的哈夫曼表 b:后缀空白压缩 c:前缀空白压缩 d:用值0的数字使用1位存储

e:如果整数列的值有一个小范围列使用最小的可能类型来存储.例如如果所有的值在0到255之间一个bigint可以作为一个tinyint存储

g:如果列仅有可能值的一个小集合列类型被转换到enum h:列可以使用上面的压缩方法的组合

能处理定长或动态长度的记录去不能处理blob或者text列 能用myisamchk解压缩

mysql能支持不同的索引类型但一般的类型是isam这是一个B树索引并且能粗略的为索引文件计算大小为(key_length+)*在所有的键上的总和.

字符串索引是空白压缩的如果第一个索引是一个字符串它可将压缩前缀如果字符串列有很多尾部空白或是一个总部能甬道全长的varchar列空白压缩使索引文件更小.如果很多字符串有相同的前缀.

内存表的特点

mysql内部的heap表使用每偶溢出去的100%动态哈希并且没有与删除有关的问题.只能通过使用在堆表中的一个索引来用等式存取东西(通常用'='操作符)

堆表的缺点是

想要同时使用的所有堆表需要足够的额外内存

不能在索引的一个部分搜索

不能按顺序搜索下一个条目(即使用这个索引做一个orderby)

mysql不能算出在2个值之间大概有多少行.这被优化器使用是用来决定使用哪个索引的但是在另一个方面甚至不需要磁盘寻道

上一篇:如何才能使图形化管理MySQL更轻松(一)

下一篇:教你如何在MySQL数据库中直接储存图片