mysql优化

调优思路:

• 0.硬件优化
• 1.数据库设计与规划–以后再修改很麻烦,估计数据量,使用什么存储引擎
• 2.数据的应用–怎样取数据,sql 语句的优化
• 3.磁盘 io 优化
• 4.操作系统的优化–内核、tcp 连接数量
• 5.mysql 服务优化–内存的使用,磁盘的使用
• 6.my.cnf 内参数的优化:
• 7 分库分表思路和优劣
·数据类型一定设置好
·多表查询比子查询省空间
·tcp(客户端)连接数量,默认(1024),必须要调
·事务语句不要写太多
·复杂语句拆分多个查询(将多个小查询合成一个大查询)
·尽量减少运算,减少不当查询
· MySQL中定义数据字段的类型对你数据库的优化是非常重要的
·服务器压力大(查询慢)的话:建缓存

硬件优化

CPU—— 64 位、高主频、高缓存,高并行处理能力
内存——大内存、主频高,尽量不要用 SWAP
硬盘——15000转、RAID5、raid10 。 SSD
网络——标配的千兆网卡,10G网卡,bond0,msyql服务器尽可能和使用它的web服务器在同一局域网内,尽量避免诸如防火墙策略等不必要的开销。
纵向拆解: 专机专用
例:现在公司一台服务器同时负责 web、ftp、数据库等多个角色。 R720 dell 内存 :768G
纵向拆解后:数据库服务器专机专用,避免额外的服务可能导致的性能下降和不稳定性。
横向拆解:
主从同步、负载均衡、高可用性集群,当单个 mysql 数据库无法满足日益增加的需求时,可以考虑在数据库这个逻辑层面增加多台服务器,以达到稳定、高效的效果。

查询优化

1、建表时表结构要合理,每个表不宜过大;在任何情况下均应使用最精确的类型。例如,如果ID列用int是一个好主意,而用text类型则是个蠢办法;TIME列酌情使用DATE或者DATETIME。
2、索引,建立合适的索引。
3、查询时尽量减少逻辑运算(与运算、或运算、大于小于某值的运算);
4、减少不当的查询语句,不要查询应用中不需要的列,比如说select * from 等操作。
5、减小事务包的大小;
6、将多个小的查询适当合并成一个大的查询,减少每次建立/关闭查询时的开销;
7、将某些过于复杂的查询拆解成多个小查询,和上一条恰好相反
8、建立和优化存储过程来代替大量的外部程序交互。

操作系统的优化

1、网卡 bonding 技术
设置tcp 连接数量限制,优化系统打开文件的最大限制。
修改网络内核对TCP连接的有关限制:
内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range = 1024 65000
这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值必须大于或等于1024;而端口范围的最大值则应小于或等于65535.修改完后保存此文件。
第二步,执行sysctl命令: sysctl -p
Linux的最大并发允许的连接:ulimit –n
注:在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)
查看当前服务器的并发连接数命令:netstat -nat|grep ESTABLISHED|wc -l
查看Linux系统级的最大打开文件数限制:cat /proc/sys/fs/file-max
注:所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。
临时设定# echo 65535 > /proc/sys/fs/file-max
2、TCP三次握手,四次挥手
三次握手涉及到TCP首部的,同步为SYN,确认位ACK,序号seq,请求号ack.
假设A是客户端,B是服务端。
首先,B处于监听状态,等待客户端的连接请求
第一次:
A向B发送SYN=1,ACK=0,选择一个初始序号seq=x
第二次:
B向A发送SYN=1,ACK=1,确认号ack=x+1 , 同样选择一个序号seq = y
第三次:
A向B发送ACK=1,seq = x+1, ack=y+1
B收到A的确认后,连接建立
TCP四次挥手
linux的并发过程中,time_wait的数量太大,引起的链接挂起等待,需要在服务器增加以下配置:
编辑文件/etc/sysctl.conf,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间

用户级别

1、设置用户最大大家爱文件限制
(1)查看Linux系统用户最大打开的文件限制
#ulimit -n
(2)修改打开文件限制
#vim /etc/security/limits.conf
mysql soft nofile 102400 #最大打开文件,软限制
mysql hard nofile 102400 #最大打开文件,硬限制
mysql soft nproc 102400 #每个进程最大打开文件,软限制
mysql hard nproc 102400 #每个进程最大打开,硬限制
其中mysql指定了要修改哪个用户的打开文件数限制,可用“*”号表示修改所有用户的限制;soft或hard指定要修改软限制还是硬限制,102400则指定了想要修改的新的限制值,即最大打开文件数(请注意软限制要小于或等于硬限制)。
(3)修改/etc/pam.d/login
#vim /etc/pam.d/login
session required /lib/security/pam_limits.so
这是告诉linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。
2、Linux系统级别
查看linux系统对同时打开文件数的硬限制
#sysctl -a | grep file-max
fs.file-max = 65535
这表明这台linux系统最多允许同时打开(即包含所有用户打开文件数总和)65535个文件,是linux系统级硬限制,所有用户级的打开文件数限制都不会超过这个数值。通常这个系统级硬限制是linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制。
(1)、修改file-max限制
#vim /etc/sysctl.conf
fs.file-max = 1000000
执行sysctl -p生效
#sysctl -p
使用64位操作系统,64位系统可以分给单个进程更多的内存。计算更快。

文件系统调优

给数据仓库一个单独的文件系统,推荐使用XFS,一般效率更高、更可靠。
ext3 不错。 ext4 只是一个过渡的文件系统。
可以考虑在挂载分区时启用 noatime 选项。 #noatime#不记录访问时间
查看硬盘名称:blkid /dev/sda1
[root@cong11 ~]# vim /etc/fstab #在挂载项中添加noatime选项就可以了。
UUID=46cb104c-e4dc-4f84-8afc-552f21279c65 /boot xfs defaults,noatime 1 2
/dev/cdrom /mnt iso9660 defaults 0 0
使设置立即生效,可运行:
[root@cong11 ~]# mount -o remount /boot/ #修改完配置文件,使用这条命令重新挂载
[root@cong11 ~]# mount
Losf
/dev/sda1 on /boot type xfs (rw,noatime)
这样以后系统在读此分区下的文件时,将不会再修改atime属性。
说明:测试效果,结果没有太大的意义。

最小化原则

1)	安装系统最小化
2)	开启程序服务最小化原则(把不必要的服务关闭)
3)	操作最小化原则
4)	登录最小化原则
5)	权限最小化

mysql 服务优化(数据库服务的优化)

1、保持每个表都不要太大
可以对大表做横切和纵切:比如说我要取得某 ID 的 lastlogin, 完全可以做一张只有“ID和 “lastlog”的小表,而非几十、几百列数据的并排大表。
另外对一个有 1000 万条记录的表做更新比对 10 个 100 万记录的表做更新一般来的要慢。
2、 存储引擎:
myisam 引擎,表级锁(将整张表进行锁定),表级锁开销小,影响范围大,适合读多写少的表,不支持事务。(适用于经常读的表)
innodb 引擎,行级锁(对表中某行数据进行锁定),锁定行的开销要比锁定全表要大。影响范围小,适合写操作比较频繁的数据表,支持事务。行级锁可能存在死锁。(适用于频繁更新数据)
MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。
3、 详解死锁
https://www.douban.com/note/344647957/?type=like
http://www.jb51.net/article/100689.htm
之所以出现死锁,是因为多线程对资源的强占,你要我的,我也要你的,两人堵在路上谁都不让,所以死锁了。
开启死锁日志
#开启后会将所有的死锁记录到error_log中 错误日志在my.cnf配置为
log-error=/var/log/mysqld.log
innodb_print_all_deadlocks = 1 开启死锁日志,死锁日志会记录在错误日志中
innodb_sort_buffer_size = 16M
3、 查看数据库服务的状态,登录mysql
mysql> show status; 看系统的状态
mysql> show engine innodb status \G #显示 InnoDB 存储引擎的状态
mysql> show variables; 看变量,在 my.cnf 配置文件里定义的变量值
例如:
log_error | /var/log/mysqld.log
4、 查看警告信息:
mysql> show warnings; 查看最近一个 sql 语句产生的错误警告
看其他的错误信息,需要看日志/var/log/mysqld.log。
5、 查看警告信息
mysql> adadfs; #随便输入一些内容,回车。将看到以下一些错误信息
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘adadfs’ at line 1
mysql> show warnings;
mysql> show processlist ; #显示mysql系统中正在运行的所有线程(查看当前mysql的连接数)。 可以看到每个客户端正在执行的命令
#本语句TCP/IP连接的主机名称(采用host_name:client_port格式),以方便地判定哪个客户端正在做什么。
程序:静态的,存储在硬盘上的一段代码
进程:动态的,进程实际上就是运行的程序在CPU上的一种表现方式。进程的作用就是管理系统分配给该程序的CPU,内存等资源
线程:完成具体工作,一个进程至少会产生一个线层(一般情况下可以产生多个线程),线程共享该进程的资源
5、 启用 mysql 慢查询:
(1)将慢查询记录到日志当中|用于看用户查询哪个最多(查询的慢)
加快查询速度,没有建索引的列也会记录到二进制日制
慢查询就是查询超过指定时间的语句。分析 sql 语句,找到影响效率的 SQL
(2)如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。
[root@cong11 ~]# vim /etc/my.cnf
[mysqld]
slow_query_log = 1 #开启慢查询日志(1代表开启,0代表关闭)
slow-query-log-file=/data/mysql/log/slow.log #这个路径对 mysql 用户具有可写权限
long_query_time=5 #查询超过 5 秒钟的语句记录下来
log-queries-not-using-indexes =1 #没有使用索引的查询
这三个设置一起使用,可以记录执行时间超过5 秒和没有使用索引的查询。请注意有关log-queries-not-using-indexes的警告。
#/etc/init.d/mysqld restart
mysql> create table test (id int,name varchar(20));
mysql> insert into test values (1,‘man’);
mysql> select * from test;
#cat /data/mysql/log/slow.log
6、 my.cnf 内参数的优化

优化总原则:

给 mysql 的资源太少,则 mysql 施展不开:给 mysql 的资源太多,可能会拖累整个 OS。
40%资源给OS(系统), 60%-70% 给mysql (内存和CPU)
1、 对查询进行缓存
大多数LAMP应用都严重依赖于数据库查询,查询的大致过程如下:
PHP发出查询请求->数据库收到指令对查询语句进行分析->确定如何查询->从磁盘中加载信息->返回结果
如果反复查询,就反复执行这些。MySQL 有一个特性称为查询缓存,他可以将查询的结果保存在内存中,在很多情况下,这会极大地提高性能。不过,问题是查询缓存在默认情况下是禁用的。
!! mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
(1)sql语句缓存:把查询多的内容放到缓存(内存)当中,不再从硬盘当中查询。查询缓存 show status like ‘qcache%’;
(3)表高速缓存:打开表之后查询(不用再打开表)
(2)关键字缓存:默认不缓存,经常用的话要开启关键字缓存。总爱执行like字句(模糊查询),卡的话怎么办,就可以设置关键字缓存
查看缓冲区的内容:show status like ‘%key_read%’;
2、启动查询缓存:
[root@cong11 ~]# vim /etc/my.cnf 添加:
[mysqld] #在此字段中添加
query_cache_size = 32M #设置缓存空间为32M
query_cache_type=1 #开启mysql查询缓存功能
[root@cong11 ~]# systemctl restart mysqld
3、 查看:查询缓存
mysql> show status like ‘qcache%’;
变量名 说明

  1. Qcache_free_blocks 缓存中相邻内存块的个数。数目大说明可能有碎片(缓存效果不好)。
    如果数目比较大,可以执行:
    mysql> flush query cache;
    #对缓存中的碎片进行整理,从而得到一个空闲块。
  2. Qcache_free_memory 缓存中的空闲内存大小
  3. Qcache_hits 每次查询在缓存中命中时就增大。
  4. Qcache_inserts 表示多少次未命中然后插入,意思是新来的SQL请求在缓存中未找到,不得不执行查询处理,在执行(未命中)
  5. Qcache_lowmem_prunes #因内存不足删除缓存次数,缓存出现内存不足并且必须要进行清理,以便为更多查询提供空间的次数。返个数字最好长时间来看;如果返个数字在不断增长,就表示可能碎片非常严重,或者缓存内存很少。
    如果Qcache_free_blocks比较大,说明碎片严重。 如果 free_memory 很小,说明缓存不够用了。
  6. Qcache_not_cached # 没有进行缓存的查询的数量,通常是这些查询未被缓存或其类型不允许被缓存
  7. Qcache_queries_in_cache # 在当前缓存的查询(和响应)的数量。
  8. Qcache_total_blocks #缓存中块的数量。

4、 使用mysql查询缓存
mysql> create database aa;
mysql> use aa;
mysql> create table test3 (id int, name varchar(255)) ;
mysql> insert into test3 values (1,‘aaaa’), (2,‘aaaa’);
mysql> select * from test3;
mysql> show status like “qcache%”; #没有命中
再查询:
mysql> select * from test3;
mysql> select * from test3;
mysql> show status like “qcache%”; #可以看见缓存了2次
5、表高速缓存:
数据库中的每个表存储在一个文件中,要读取文件的内容,你必须先打开文件,然后再读取。为了加快从文件中读取数据的过程,mysqld 对这些打开文件进行了缓存,其最大数目由 /etc/my.cnf中的 table_cache 指定
[root@cong11 ~]# vim /etc/my.cnf #在表中添加以下内容
[mysqld]
table_open_cache=23 #最多缓存23个表
[root@cong11 ~]# systemctl restart mysqld
mysql> show global status like ‘open%_tables’; 显示打开了多少表数量
Open_tables 表示打开表的数量,Opened_tables表示打开过的(过去一共打开过多少)表数量,如果Opened_tables数量过大,说明配置中 table_cache(5.1.3之后这个值叫做table_open_cache)值可能太小.
table_cache 的值在 2G 内存以下的机器中的值默认从 256 到 512个。
对于有 1G 内存的机器,推荐值是 128-256。
6、关键字缓冲区
key_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。
[root@cong11 ~]# vim /etc/my.cnf #在表中添加以下内容
[mysqld]
key_buffer_size=512M #关键字缓冲区大小
[root@cong11 ~]# systemctl restart mysqld
查看:
mysql> show status like ‘%key_read%’;
Key_reads 代表命中磁盘的请求个数,Key_read_requests 是总数, 命中磁盘的读请求数除以读请求总数就是不中比率.

强制限制mysql 资源设置

您可以在mysqld中强制一些限制来确保系统负载不会导致资源耗尽的情况出现。
[root@cong11 ~]# vim /etc/my.cnf
[mysqld]
max_connections=500 #上限是看硬件配置
wait_timeout=10 #等待超时时间
max_connect_errors = 100 #最多错误连接100次 限制暴力破解
参数:
第一行:最大连接数,在服务器没有崩溃之前确保只建立服务允许数目的连接。该参数设置过小的最明显特征是出现“Too many connections”错误;
第二行:mysqld将终止等待时间(空闲时间)超过10秒的连接。在LAMP应用程序中,连接数据库的时间通常就是Web 服务器处理请求所花费的时间。有时候如果负载过重,连接会挂起,并且会占用连接表空间。如果有多个交互用户使用了到数据库的持久连接,那么应该将这个值设低一点。
第三行:如果一个主机在连接到服务器时有问题,并重试很多次后放弃,那么这个主机就会被锁定,直到执行:
mysql> FLUSH HOSTS;
Query OK, 0 rows affected (0.00 sec)
默认情况下,10 次失败就足以导致锁定了。将这个值修改为100 会给服务器足够的时间来从问题中恢复。如果重试100 次都无法建立连接,那么使用再高的值也不会有太多帮助,可能它根本就无法连接。
测试:
[root@cong11 ~]# vim /etc/my.cnf #在配置文件中添加一下内容
[mysqld]
max_connections=500 #上限是看硬件配置
wait_timeout=10 #等待超时时间
max_connect_errors = 100 #最多错误连接100次
验证:
mysql> show status like ‘max_used_connections’; #当前有1个连接
再另一个客户端打开一个mysql连接,执行一下查询,可以看到有两个:
mysql> show status like ‘max_used_connections’;
总结:
mysql有超过100个可以调节的设置,要记住那么多基本是不可能的,但是幸运的是你只需要记住很少一部分你就可以基本满足你的需求了,我们还可以通过“SHOW STATUS”命令来查看mysql是否按照我们的期望在运行。

扩展mysql优化之-------分库分表

1、基本思想之什么是分库分表?
从字面上简单理解,就是把原本存储于一个库的数据分块存储到多个库上,把原本存储于一个表的数据分块存储到多个表上。
2、基本思想之为什么要分库分表?
数据库中的数据量不一定是可控的,在未进行分库分表的情况下,随着时间和业务的发展,库中的表会越来越多,表中的数据量也会越来越大,相应地,数据操作,增删改查的开销也会越来越大;另外,一台服务器的资源(CPU、磁盘、内存、IO等)是有限的,最终数据库所能承载的数据量、数据处理能力都将遭遇瓶颈,。
3、 分库分表的实施策略。
如果你的单机性能很低了,那可以尝试分库。分库,业务透明,在物理实现上分成多个服务器,不同的分库在不同服务器上。分区可以把表分到不同的硬盘上,但不能分配到不同服务器上。一台机器的性能是有限制的,用分库可以解决单台服务器性能不够,或者成本过高问题。
当分区之后,表还是很大,处理不过来,这时候可以用分库。
orderid,userid,ordertime,…
userid%4=0,用分库9/9981
userid%4=1,用分库2
userid%4=2, 用分库3
userid%4=3,用分库4
上面这个就是一个简单的分库路由,根据userid选择分库,即不同的服务器
例如:
mysql> create table user1(id int,name char(40),price int);
mysql> insert into user1(id,name,price) select bid,bName,price from books where bid mod 4 = 0;
4、 分库分表存在的问题。
事务问题。
在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出高昂的性能代价;如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
5、 跨库跨表的join问题。
在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表、不同的库上,这时,表的关联操作将受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果原本一次查询能够完成的业务,可能需要多次查询才能完成。
6、 额外的数据管理负担和数据运算压力。
额外的数据管理负担,最显而易见的就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然引起额外的逻辑运算,例如,对于一个记录用户成绩的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果。

mysql扩展
横向:添加几台服务器,做主从复制(高可用)
纵向:在原有服务器上添加硬盘等设备

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值