首页 > 数据库 > 数据库开发技术 > 关于 MySQL 优化答应我别再拉跨了好么
#给city表创建一个名为 idx_city_name 的索引类型为BTree CREATE INDEX idx_city_name ON city(city_name);
#查询city表的索引 SHOW INDEX FROM city;
#删除索引 DROP INDEX idx_city_name ON city;
#创建唯一索引,允许null值 ALTER TABLE city ADD UNIQUE idx_city_name(city_name);
InnoDB:支持事务、支持行锁、支持外键约束(
RESTRICT、NO ACTION:限制在子表有关联记录的情况下, 父表不能更新;
CASCADE:父表在更新或者删除时,更新或者删除子表对应的记录
SET NULL:父表在更新或者删除的时候,子表的对应字段被SET NULL )
MyISAM:不支持事务、支持表锁、不支持外键约束
查看服务器状态信息:SHOW GLOBAL STATUS LIKE 'Com_______';
show status like 'Innodb_rows_%';
定位低效率执行SQL:
慢查询日志:用--log-slow-queries[=file_name]选项启动时,mysqld 写一个包含所有执行时间超过 long_query_time 秒的 SQL 语句的日志文件
show processlist:show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看 SQL 的执行情况,同时对一些锁表操作进行优化。
explain分析执行计划:
show profile分析SQL:
通过 have_profiling 参数,查看当前MySQL是否支持profile
(select @@have_profiling ;)
set profiling=1;开启profiling
show profiles;查看SQL执行的耗时
show profile for query query_id;查看SQL执行过程中每个线程的状态和耗时情况
trace分析优化器执行计划:
打开trace , 设置格式为 JSON,并设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示。
SET optimizer_trace="enabled=on",end_markers_in_json=on; set optimizer_trace_max_mem_size=1000000;
查看优化日志:select * from information_schema.optimizer_trace\G;
避免索引失效:
查看索引使用情况:
show status like 'Handler_read%'; 当前会话
show global status like 'Handler_read%'; 全局
导入大批量数据的优化:
优化insert语句:
优化order by语句:
两种排序:filesort 排序、using index排序
Filesort 的优化:
两次扫描算法:MySQL4.1 之前,根据条件取出排序字段和行指针信息在sort buffer 中排序,完成排序后,再根据行指针回表读取记录,会导致大量随机I/O操作。
一次扫描算法:一次性取出满足条件的所有字段,然后在sort buffer 中排序后直接输出结果集。内存开销较大,效率高。
MySQL 通过比较系统变量 max_length_for_sort_data 的大小和Query语句取出的字段总大小, 来判定是否那种排序算法,如果max_length_for_sort_data 更大,那么使用一次扫描算法;否则使用两次扫描算法。可以适当提高 sort_buffer_size 和 max_length_for_sort_data 系统变量,来增大排序区的大小,提高排序的效率。
优化group by 语句:
优化嵌套查询:尽量避免使用子查询,改用连接查询
优化OR条件:
优化分页查询:
使用SQL提示:
查询缓存优化:
查询缓存配置:
查看当前的MySQL数据库是否支持查询缓存:SHOW VARIABLES LIKE 'have_query_cache';
查看当前MySQL是否开启了查询缓存 :SHOW VARIABLES LIKE 'query_cache_type';
查看查询缓存的占用大小 :SHOW VARIABLES LIKE 'query_cache_size';
查看查询缓存的状态变量:SHOW STATUS LIKE 'Qcache%';
Qcache_free_memory(缓存可用内存量)、Qcache_hits(命中数)、Qcache_inserts(查询数)、Qcache_not_cached(非缓存查询数)
开启查询缓存:OFF或0(缓存关闭)、ON或1(缓存开启,查询结果符合条件则缓存,SQL_NO_CACHE显式指定不缓存)、DEMAND(按需进行缓存,SQL_CACHE显式指定缓存)
在 /usr/my.cnf 配置中,增加query_cache_type=1,重启服务生效
查询缓存失效的情况:
**InnoDB 内存优化:**innodb用一块内存区做IO缓存池,该缓存池用来缓存innodb的索引块h和innodb的数据块。
Mysql并发参数调整:
锁分类:
MyISAM 表锁:MyISAM 存储引擎只支持表锁
加表锁:MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁;显示加表锁语法:
读锁会阻塞写,但是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写。
MyISAM 的读写锁调度是写优先,所以适合做读为主的表的存储引擎
查看锁的争用情况:
InnoDB 行锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
事务及其ACID属性:
并发事务处理带来的问题:
事务隔离级别:
InnoDB 的行锁模式:对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加 排他锁;
显示给记录集加共享锁或排他锁:
无索引行锁升级为表锁:如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样。
间隙锁:使用范围条件进行检索数据,并请求共享或排它锁时,InnoDB会给符合条件的已有数据进行加锁;对于键值在条件范围内但并不存在的记录,叫做 "间隙(GAP)" , InnoDB也会对这个 "间隙" 加锁。缩小条件筛选范围可以降低间隙锁的出现。
InnoDB 行锁争用情况:show status like 'innodb_row_lock%';
Innodb_row_lock_current_waits: 当前正在等待锁定的数量
Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg:每次等待所花平均时长
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间
Innodb_row_lock_waits: 系统启动后到现在总共等待的次数
优化建议:
SQL执行顺序:
编写顺序:
SELECT DISTINCT
<select list>
FROM
<left_table> <join_type>
JOIN
<right_table> ON <join_condition>
WHERE
<where_condition>
GROUP BY
<group_by_list>
HAVING
<having_condition>
ORDER BY
<order_by_condition>
LIMIT
<limit_params>
执行顺序
FROM <left_table>
ON <join_condition>
<join_type> JOIN <right_table>
WHERE <where_condition>
GROUP BY <group_by_list>
HAVING <having_condition>
SELECT DISTINCT <select list>
ORDER BY <order_by_condition>
LIMIT <limit_params>
正则表达式使用:
^ 在字符串开始处进行匹配
$ 在字符串末尾处进行匹配
. 匹配任意单个字符, 包括换行符
select * from emp where name regexp '^T';
select * from emp where name regexp '2$';
select * from emp where name regexp '[uvw]';
MySQL 常用函数:
数字函数:
日期函数:
聚合函数:
错误日志:show variables like 'log_error%';查看错误日志位置
二进制日志:二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,MySQL的主从复制, 就是通过该binlog实现的。
二进制日志默认情况下是没有开启的,需要到MySQL的配置文件中开启,并配置MySQL日志的格式。
#配置开启binlog日志, 日志的文件前缀为 mysqlbin -----> 生成的文件名如 : mysqlbin.000001,mysqlbin.000002
log_bin=mysqlbin
#配置二进制日志的格式
binlog_format=STATEMENT
日志格式:
查看STATEMENT格式日志内容 :mysqlbinlog mysqlbing.000001;
查看ROW格式日志:mysqlbinlog -vv mysqlbin.000002
日志删除:
慢查询日志:
文件位置和格式:
# 该参数用来控制慢查询日志是否开启, 可取值:1 和 0 , 1 代表开启, 0 代表关闭
slow_query_log=1
# 该参数用来指定慢查询日志的文件名
slow_query_log_file=slow_query.log
# 该选项用来配置查询的时间限制, 超过这个时间将认为值慢查询, 将需要进行日志记录, 默认10s
long_query_time=10
复制原理:主库数据有变更就会记录在Binarylog中,从库有一个线程时时读取Binarylog日志然后再写入RelayLog,之后会有一个线程将RelayLog中的sql语句反映到自己服务器的数据变化
复制优势:
主库出现问题,可以快速切换到从库提供服务。
可以主库负责写操作,从库负责读操作,实现读写分离,降低主库的访问压力。
可以在从库中执行备份,以避免备份期间影响主库的服务。
主从复制搭建步骤:
master主库:
在master 的配置文件(/usr/my.cnf)中,配置如下内容:
#mysql 服务ID,保证整个集群环境中唯一
server-id=1
#mysql binlog 日志的存储路径和文件名
log-bin=/var/lib/mysql/mysqlbin
#错误日志,默认已经开启
#log-err
#mysql的安装目录
#basedir
#mysql的临时目录
#tmpdir
#mysql的数据存放目录
#datadir
#是否只读,1 代表只读, 0 代表读写
read-only=0
#忽略的数据, 指不需要同步的数据库
binlog-ignore-db=mysql
#指定同步的数据库
#binlog-do-db=db01
执行完毕之后,需要重启Mysql:
service mysql restart;
创建同步数据的账户,并且进行授权操作:
#创建账户
grant replication slave on *.* to 'itcast'@'192.168.192.131' identified by 'itcast';
#刷新权限列表
flush privileges;
查看master状态:
show master status;
字段含义:
slave从库:
在 slave 端配置文件中,配置如下内容:
#mysql服务端ID,唯一
server-id=2
#指定binlog日志
log-bin=/var/lib/mysql/mysqlbin
执行完毕之后,需要重启Mysql:
service mysql restart;
执行如下指令 :
#连接主库的ip
change master to master_host= '192.168.192.130',
#连接主库的用户名密码
master_user='itcast', master_password='itcast',
#以下通过show master status;命令查询得到
master_log_file='mysqlbin.000001', master_log_pos=413;
开启同步操作
#开启从库
start slave;
#查看从库状态
show slave status;
重点关注Slave_io_Running和Slave_SQL_Running这两个线程状态
停止同步操作
stop slave;
DevX 不止于技术

原文作者:DevXTalk;如有侵权,请联系管理员删除。