写到应用程序的SQL语句,禁止一切Data Definition Language(DDL数据定义语言)操作。
例如:Create table xxx ,Drop table xxx , Create database xxx ,Drop database xxx ,Alter table xxx grant … …
避免多余的排序。使用GROUP BY时,默认会进行排序。
MySQL5.7在GROUP BY时,默认进行隐式排序。MySQL8.0时,取消该特性。
禁止select * 这样的代码,指定需要的字段名。
避免在where子句中对字段施加函数
例如,select * from sys_user_log where substr(username,1,5)=‘abcde’
避免where子句中对字段进行表达式操作,避免在WHERE子句中对字段进行NULL值判断。
多表关联查询时,保证被关联的字段需要有索引,需要join的字段,数据类型必须绝对一致
使用ISNULL()来判断是否为NULL值,NULL与任何值的直接比较都为NULL,
NULL<>NULL的返回结果是NULL,而不是false(<>即!=)
NULL=NULL的返回结果是NULL,而不是true
NULL<>1的返回结果NULL,而不是true
禁止使用存储过程,存储过程难以调试和扩展,更没有移植性
不得使用任何外键与级联,一切外键概念必须在应用层解决;
外键与级联更新适用于单机低并发,不适合分布式、高并发集群;
级联更新是强阻塞,存在数据库更新风暴的风险;
外键影响数据库的插入速度。
扩展:
级联操作指的就是,当你操作主表时,自动的操作从表
外键(foreign key) 是用于建立和加强两个表数据之间的链接的一列或多列; 外键约束主要用来维护两个表之间数据的一致性。
通过in条件更新一张表中的某些记录值,直接对子查询使用in的效率是很糟糕的,需要对in的子查询包一层。
正例:
update xxx set name ="test" where id in(
select order_id from (
select order_id from xxx where name like "ct%") as tmp
)
即将in的子查询查出来的数据,再次通过select 取出来,存放在tmp临时表中,从而实现优化效果。
使用in操作时应控制里面的数据不超过1000条
尽量使用UNION ALL代替UNION
因为UNION会执行去重和排序等操作,降低性能。可以在合并前先将数据处理好再合并。UNION ALL,即直接合并。
公共参数优化
max_connections = 1000
#同时处理最大连接数,推荐设置最大连接数是上限连接数的80%左右
sort_buffer_size = 2M
#查询排序时缓冲区大小,只对order by和group by起作用,可增大此值为16M
open_files_limit = 10240
#MySQL打开的文件描述符限制,默认最小1024
connect-timeout = 10
#连接超时之前的最大秒数,在 Linux 平台上,该超时也用作等待服务器首次回应的时间
wait-timeout = 28800
#等待关闭连接的时间
max_allowed_packet = 64M
# 服务所能处理的请求包的最大大小以及服务所能处理的最大的请求大小(当与大的BLOB 字段一起工作时相当必要), 避免超长SQL的执行有问题,默认值为16M
table_cache = 512
# 所有线程所打开表的数量. 增加此值就增加了mysqld所需要的文件描述符的数量
thread_stack = 192K
# 线程使用的堆大小. 此容量的内存在每次连接时被预留.MySQL 本身常不会需要超过 64K
thread_cache_size = 20
# 我们在 cache 中保留多少线程用于重用.当一个客户端断开连接后,如果 cache 中的线程还少于 thread_cache_size,则客户端线程被放入 cache 中.这可以在你需要大量新连接的时候极大的减少线程创建的开销(一般来说如果你有好的线程模型的话,这不会有明显的性能提升.)服务器线程缓存这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能。通过比较Connections 和Threads_created 状态的变量,可以看到这个变量的作用根据物理内存设置规则如下:
# 1G —> 8
# 2G —> 16
# 3G —> 32
thread_concurrency = 8
#该参数取值为服务器逻辑CPU数量×2,在本例中,服务器有 2颗物理CPU,而每颗物理CPU又支持H.T超线程,所以实际取值为4 × 2 = 8.设置 thread_concurrency的值的正确与否,对 mysql 的性能影响很大, 在多个 cpu(或多核)的情况下,错误设置了 thread_concurrency 的值, 会导致 mysql 不能充分利用多 cpu(或多核),出现同一时刻只能一个 cpu(或核)在工作的情况。 thread_concurrency 应设为 CPU 核数的 2 倍.比如有一个双核的 CPU, 那么thread_concurrency 的应该为 4; 2 个双核的cpu,thread_concurrency 的值应为 8,属重点优化参数
thread_concurrency参数对性能的影响比较大,即线程并发数
MySQL常用有两种存储引擎,一个是MyISAM,不支持事务处理,读性能处理快,表级别锁。另一个是InnoDB,支持事务处理(ACID),设计目标是为处理大容量数据发挥最大化性能,行级别锁。
MyISAM存储引擎参数优化
1) MyISAM存储引擎对性能影响较大的参数是key_buffer_size、sort_buffer_size、read_buffer_size
2)参数
key_buffer_size = 256M
#指定用于索引的缓冲区大小,增加它可得到更好的索引处理性能。如果是以InnoDB引擎为主的DB,专用于MyISAM引擎的key_buffer_size 可以设置较小,8MB 已足够 如果是以MyISAM引擎为主,可设置较大,但不能超过4G. 在这里,强烈建议不使用MyISAM引擎,默认都是用InnoDB引擎.注意:该参数值设置的过大反而会使服务器整体效率降低!
sort_buffer_size = 2M
#查询排序时所能使用的缓冲区大小。排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序。注意:该参数对应的分配内存是每连接独占!如果有100个连接,那么实际分配的总共排序缓冲区大小为100 × 2 =200MB,所以,对于内存在 4GB 左右的服务器推荐设置为 6-8M。
read_buffer_size = 1M
#读查询操作所能使用的缓冲区大小。和sort_buffer_size一样,该参数对应的分配内存也是每连接独享!如果机器内存是16G,可分配1MB用来做MyISAM表全表扫描的缓冲大小。当全表扫描需要时,在对应线程中分配.
join_buffer_size = 512
#联合查询操作所能使用的缓冲区大小,默认大小512KB,该参数对应的分配内存也是每连接独享。多表关联查询时,当JOIN key无索引时会用到join_buffer_size,此属性是在没有索引的情况下减少过多的表扫描而设计的。
read_rnd_buffer_size = 8M
#MyISAM 以索引扫描(Random Scan)方式扫描数据的buffer大小,如果程序中有很多order by语句,增大此属性值能够提升性能。
bulk_insert_buffer_size = 64M
#用来缓存批量插入数据的时候临时缓存写入数据。如果有大量数据插入可提高此参数值,默认是8M
myisam_sort_buffer_size = 64M
#MyISAM设置恢复表之时使用的缓冲区的尺寸,默认为8M,最小值4k。当在REPAIR TABLE 或用 CREATE INDEX 创建索引或ALTER TABLE过程中对MyISAM索引排序时分配的缓冲区
myisam_max_sort_file_size = 10G
#mysql重建索引时允许使用的临时文件最大大小,在windows系统中默认值为2G
myisam_repair_threads = 1
#如果该值大于1,在 Repair by sorting 过程中并行创建MyISAM 表索引(每个索引在自己的线程内).如果一个表拥有超过一个索引, MyISAM 可以通过并行排序使用超过一个线程去修复他们.这对于拥有多个 CPU 以及大量内存情况的用户,是一个很好的选择.
myisam_recover = DEFAULT
#Myisam_revocer控制了Myisam查找和修复错误的方式,DEFAULT--Mysql会尝试修复被标记为崩溃会没有干净关闭的表,除了修复,不会做任何事情;Backup--Mysql将数据文件备份到一个BAK文件中;FORCE--即使.MYD文件丢失的数据多余一行,恢复也会继续.
transaction_isolation = REPEATABLE-READ
# 设定默认的事务隔离级别.可用的级别如下:READUNCOMMITTED, READ-COMMITTED, REPEATABLEREAD,SERIALIZABLE,1.READ UNCOMMITTED-读未提交2.READ COMMITTE-读已提交 3.REPEATABLE READ -可重复读 4.SERIALIZABLE -串行
InnoDB存储引擎参数
innodb_file_per_table = 1
# InnoDB为独立表空间模式,每个数据库的每个表都会生成一个数据空间
# 独立表空间优点:
# 1.每个表都有自已独立的表空间。
# 2.每个表的数据和索引都会存在自已的表空间中。
# 3.可以实现单表在不同的数据库中移动。
# 4.空间可以回收(除drop table操作外,表空间不能自已回收)
# 缺点:
# 1.单表增加过大,如超过100G
# 结论:
# 共享表空间在Insert操作上稍有优势。其它都没独立表空间表现好。当启用独立表空间时,请合理调整:
innodb_open_files
innodb_status_file = 1
#启用InnoDB的status file,便于管理员查看以及监控等
innodb_open_files = 2048
# 限制Innodb能打开的文件数量,如果库里的表特别多的情况,请增加这个。这个值默认是300
innodb_additional_mem_pool_size = 128M
#设置InnoDB存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,默认是8M,数据库中表越多这个参数应设置得越大。所以当我们一个MySQL Instance中的数据库对象非常多的时候,是需要适当调整该参数的大小以确保所有数据都能存放在内存中提高访问效率的。
innodb_buffer_pool_size = 128M
#包括数据页、索引页、插入缓存、锁信息、自适应哈希索引、数据字典信息.InnoDB 使用一个缓冲池来保存索引和原始数据,不像MyISAM,这里你设置越大,你在存取表里面数据时所需要的磁盘 I/O 越少。在一个独立使用的数据库服务器上,你可以设置这个变量到服务器物理内存大小的80%,但不要设置过大,否则,由于物理内存的竞争可能导致操作系统的换页颠簸
innodb_write_io_threads = 4
innodb_read_io_threads = 4
# innodb使用后台线程处理数据页上的读写 I/O(输入输出)请求,根据你的 CPU 核数来更改,默认是4
# 注:这两个参数不支持动态改变,需要把该参数加入到my.cnf里,修改完后重启MySQL服务,允许值的范围从 1-64
innodb_data_home_dir = /usr/local/mysql/var/
#设置此选项如果你希望 InnoDB 表空间文件被保存在其他分区.默认保存在 MySQL 的 datadir 中.
innodb_data_file_path = ibdata1:500M;ibdata2:2210M:autoextend
#InnoDB将数据保存在一个或者多个数据文件中成为表空间.如果你只有单个逻辑驱动保存你的数据,一个单个的自增文件就足够好了.其他情况下.每个设备一个文件一般都是个好的选择.你也可以配置InnoDB来使用裸盘分区
innodb_file_io_threads = 4
#用来同步 IO 操作的 IO 线程的数量. 此值在 Unix 下被硬编码为 4,但是在 Windows 磁盘 I/O 可能在一个大数值下表现的更好.
innodb_thread_concurrency = 0
#在 InnoDb 核心内的允许线程数量,InnoDB 试着在 InnoDB内保持操作系统线程的数量少于或等于这个参数给出的限制,最优值依赖于应用程序,硬件以及操作系统的调度方式.过高的值可能导致线程的互斥颠簸.默认设置为 0,表示不限制并发数,这里推荐设置为0,更好去发挥CPU多核处理能力,提高并发量
innodb_flush_log_at_trx_commit = 1
#可以通过修改此参数的默认值,即批量提交事务IO的方式来提高数据库性能。但是当数据库crash的时候可能会丢事务。如设置为1,只要事务一提交,就会对Log buffer进行刷盘。
innodb_log_buffer_size = 8M
#用来缓冲日志数据的缓冲区的大小.当此值快满时, InnoDB将必须刷新数据到磁盘上.由于基本上每秒都会刷新一次,所以没有必要将此值设置的太大(甚至对于长事务而言)
innodb_log_file_size = 500M
#事务日志大小.在日志组中每个日志文件的大小,你应该设置日志文件总合大小到你缓冲池大小的5%~100%,来避免在日志文件覆写上不必要的缓冲池刷新行为.不论如何, 请注意一个大的日志文件大小会增加恢复进程所需要的时间.
innodb_log_files_in_group = 2
#在日志组中的文件总数,通常来说2~3是比较好的.
innodb_log_group_home_dir = /usr/local/mysql/var/
# InnoDB的日志文件所在位置. 默认是与innodb_data_home_dir参数值相同。
innodb_lock_wait_timeout = 50
#设置锁等待的时间默认是50s,一旦数据库锁超过这个时间就会报错,避免在资源有限的情况下产生太多的锁等待。
innodb_flush_method = O_DSYNC
#这个参数控制着innodb数据文件及redo log的打开、刷写模式.默认值是 “fdatasync”, 调用fsync()去刷数据文件与redo log的buffer;另一个是 “O_DSYNC”,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件;设为O_DIRECT时,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log
innodb_force_recovery=1
# 如果你发现 InnoDB 表空间损坏, 设置此值为一个非零值可能帮助你导出你的表.从1 开始并且增加此值知道你能够成功的导出表。这个参数只能修改my.cnf配置文件,然后重启数据库实例,不能用命令行修改。
innodb_fast_shutdown
# 0,代表当MYSQL关闭时,Innodb需要完成所有full purge和merge insert buffer操作,这需要花费时间来完成;
# 1,是默认值,不需要完成full purge和merge insertbuffer操作,但是在缓冲池的一些数据脏页还是会刷新到磁盘;
InnoDB引擎参数中对性能影响较大的参数是innodb_buffer_pool_size
MySQL慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阈值的语句,具体指运行时间超过long_query_time值的SQL语句会被记录到慢查询日志中。
开启慢查询日志
默认情况下,MySQL并不会开启慢查询日志,需要手动去设置这个参数,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询会降低服务器的性能。
1)进入MySQL终端,查看是否开启慢查询日志,默认是OFF:show variables like "%slow_query_log%;"
2)开启慢查询:set global slow_query_log =1;
3)关闭慢查询:set global slow_query_log =0;
4)这样开启只对当前数据库生效,重启之后将恢复默认值,如果要永久生效必须修改MySQL配置文件,即在my.cnf文件中添加以下内容:
slow_query_log=1
slow_query_log_file=慢查询日志存放的路径
5)查询慢查询的阈值:show variables like "%long_query_time%";
6)修改慢查询的阈值:set global long_query_time = 8;
修改完慢查询的阈值后,需要重新连接MySQL客户端才会生效。
7)查询慢查询语句的记录条数:show global status like "%slow_queries%";
mysqldumpslow慢查询日志分析
使用mysqldumpslow命令对慢查询日志进行分析。
命令参数:
1)-s 按照哪种方式排序(al, at, ar, c, l, r, t), 默认按at排序
2)c 访问计数
3)l 锁定时间
4)r 返回记录
5)t 查询时间
6)al 平均锁定时间
7)ar 平均访问记录数
8)at 平均查询时间
9)-t 是top n 的意思,即返回多少条数据
10)-g 可以跟正则表达式,大小写不敏感
11)得到返回记录数最多的10条sql:mysqldumpslow -s r -t 10 /var/lib/mysql/192-slow.log;
12)得到访问次数最多的10条sql:mysqldumpslow -s c -t 10 /var/lib/mysql/192- slow.log;
13)得到慢查询日志里包含left join的sql语句:mysqldumpslow -s t -g 'left join' /var/lib/mysql/192-slow.log;
14)如果慢查询日志中sql语句太多,可结合|more使用:mysqldumpslow -s c /var/lib/mysql/192-slow.log|more;
慢查询show profiles
show profiles是mysql提供的可以用来分析当前会话中sql语句执行的资源消耗情况的工具,可用于sql调优的参考。同样和慢日志查询一样,默认是处于关闭状态,并保存最近15次的运行结果。
1)查看当前JDK版本是否支持:show variables like "%profiling%";
如果hava_profiling的值为true,即支持。
profiling默认值为OFF,即默认关闭状态。
profiling_history_size默认为15次。
2)开启profiling:set profiling = on;
3)查看搜集的慢查询SQL语句:show profiles;
4)诊断sql:show profile cpu,block io for query 5;
当出现下面的数据时就要进行优化了
converting HEAP to MyISAM #查询结果太大,内存放不下了,需要往磁盘上写
creating tmp tables #创建临时表,先copy数据到临时表,用完再删除
copying to tmp table on disk #把内存中的临时表复制到磁盘上
locked #被锁定