MySQL优化
一、查询优化
1、启用MySQL的慢查询日志
慢查询日志是用来记录执行时间超过指定时间的查询语句。通过慢查询日志,可以查找出哪些查询语句的执行效率很低,以便进行优化。
查看慢查询日志的定义:
其中:
slow_query_log: off关闭状态 on开启状态
slow_query_log_file:慢查询日志存放地点
long_query_time:选项来设置一个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值(默认为10秒),这个查询语句将被记录到慢查询日志中, 设置为0的话表示记录所有的查询。
开启慢查询日志功能:
方法1:通过配置文件my.cnf开启慢查询日志,在配置文件my.cnf中添加下面的配置项:
slow_query_log = 1 #开启慢查询日志
slow-query-log-file=/data/MySQL/log/slow.log #这个路径对 MySQL 用户具有可写权限
long_query_time=1 #查询超过1秒钟的语句记录下来
log-queries-not-using-indexes =1 #没有使用索引的查询
注:如果不指定存储路径,慢查询日志默认存储到MySQL数据库的数据文件下,如果不指定文件名,默认文件名为hostname-slow.log
重启MySQLd服务,使修改的参数生效。
测试:
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
方法2:通过登录MySQL服务器直接定义,方式如下:
MySQL>set global slow_query_log=1; #开启慢查询日志
MySQL>set global long_query_time=0.001; #更改时间
2、使用EXPLAIN执行计划
可以通过在select语句前使用 explain,来获取该查询语句的执行计划,而不是真正执行该语句。
3、当只要一行数据时使用LIMIT 1
4、只取自己需要的column,避免使用SELECT *
5、添加索引(主键索引/唯一索引/普通索引/复合索引)
6、不做列运算:SELECT id from tablename where age + 1 = 10,任何对列的操作都将导致表扫描,查询时要尽可能将操作移至等号右边
7、sql语句尽可能简单:一条sql只能在一个cpu运算;大语句拆小语句,减少锁时间;一条大sql可以堵死整个库。
8、OR改写成IN
9、避免%xxx式查询
10、尽量避免在WHERE子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
索引失效:
模型数空运最快
模:模糊查询中like 不能以%开头
型:数据类型错误
数:对索引字段使用内部函数
空:null 索引不存储空值
运:对索引列进行加减乘除等运算
最:最左原则的意思。在复合索引中,索引列的顺序非常重要,,如果不是按照索引列最左列开始进行查找,则无法使用该索引
快:全表扫描更快的意思。如果数据库预估全表扫描的查询速度比使用表索引的更快,就不会使用该索引。
二、 存储引擎
1、MYISAM
MyISAM存储引擎的表在数据库中,每一个表都被存储为三个以表名命名的物理文件。首先是任何存储引擎都不可缺少的存放表结构定义信息的.frm文件,另外还有.MYD和.MYI 文件,分别存放了表的数据(.MYD)和索引数据(.MYI)。
Myisam存储引擎的特点:
l表级锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁
l数据库在读写过程中相互堵塞,在数据写入的过程中阻塞用户对数据的读取,在数据读取的过程中阻塞用户写入数据。
l表级锁开销小,影响范围大,适合读多写少的表
l不支持事务
l不支持外键
l不支持崩溃后的安全恢复
2、Innodb:
Innodb 存储引擎也和MyISAM 不太一样,虽然也有.frm文件来存放表结构定义相关的元数据,但是表数据和索引数据是存放在一起的。至于是每个表单独存放还是所有表存放在一起,完全由用户来决定。
Innodb存储引擎的特点:
l行级锁,锁定行的开销要比锁定全表要大。影响范围小,适合写操作比较频繁的数据表。但是全表扫描仍然会是表级锁定
l支持事物,支持四个事务隔离级别
l支持外键
l支持崩溃后的安全恢复
总体来讲,MyISAM适合SELECT密集型的表,而InnoDB适合INSERT和UPDATE密集型的表。
查看默认的存储引擎:
MySQL> show variables like '%storage_engine%';
查看支持的存储引擎:
MySQL> show engines;
详解死锁
锁的概念:当客户端操作表(记录)时,为了保证操作的隔离性(多个客户端操作不能互相影响),通过加锁来处理。
操作方面:
读锁:读操作时增加的锁,也叫共享锁,S-lock。特征是阻塞其他客户端的写操作,不阻塞读操作。(并发读)
写锁:写操作时增加的锁,也叫独占锁或排他锁,X-lock。特征是阻塞其他客户端的读,写操作。
锁定粒度(范围):
l行级:提升并发性,锁本身开销大
l表级:不利于并发性,锁本身开销小。
死锁:
死锁的本质是一种僵持状态,之所以出现死锁,是因为多个线程对资源的强占,你要我的,我也要你的,两人堵在路上谁都不让,所以死锁了。
开启死锁到error_log中 错误日志在my.cnf配置为
log-error=/data/MySQL/log/MySQLd.log
innodb_print_all_deadlocks = 1
1.2.2、 查看数据库服务的状态,登录MySQL
MySQL> show status; 看系统的状态
MySQL> show engine innodb status \G #显示 InnoDB 存储引擎的状态
MySQL> show variables; 看变量,在 my.cnf 配置文件里定义的变量值