简介:本资源为博主原创MySQL优化方案,包括MySQL集群搭建(多主,双机热备)、讲解算法演变历程与算法解剖优缺点(时间/空间复杂度、hash开口/封闭寻址、二叉树、AVL平衡二叉树、红黑树、B-树、B+树、B*树)、MySQL引擎、MySQL数据量计算、常见企业级优化策略等。
word文档下载:https://download.csdn.net/download/weixin_38652136/11029000
注意:如果所使用的CentOS7是Everything版本自带MySQL v5.7,不需要另行安装,默认账户为root/root,安装前请先检查一下。
rpm -qa | grep mysql
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 报错: -bash: wget: 未找到命令 安装插件 yum -y install wget
sudo rpm -ivh mysql-community-release-el7-5.noarch.rpm
sudo yum install mysql-server
mysql -u root 报错: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 原因:原因是/var/lib/mysql的访问权限问题。 chown root /var/lib/mysql/
service mysqld restart
mysql -u root use mysql; update user set password=password('123456') where user='root'; exit; 接着继续重启MySQL服务 service mysqld restart
mysql -u root -p GRANT ALL PRIVILEGES ON *.* TO root@"%" IDENTIFIED BY "root"; flush privileges; 重启服务器 service mysqld restart
关闭防火墙 systemctl stop firewalld.service |
主从原理
参照上图可知:
Mater有一个log dump线程,Slave服务器有一个I/O线程和SQL线程。
记录阶段:Master会将所有DML SQL语句记录到二进制binlog文件;
请求阶段:I/O线程去请求主库的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中;
传输阶段:Mater的 log dump 线程,用来给Slave I/O线程传binlog; (Master和Slave会建立一个长连接进行数据传输)
执行阶段:SQL 线程,会读取relay log文件中的日志,并解析成具体操作,来实现主从的操作一致,而最终数据一致。
扩展知识:DML为数据操纵语言(增删改查锁等操作);DDL 数据库定义语言;DCL数据库控制语言 授权,角色控制等 ;TCL(Transaction Control Language)事务控制语言 。
实现
主服务器:192.168.13.103,从节点:192.168.13.104
主服务器节点
vi /etc/my.cnf 新增以下内容 server_id=103 ###服务器id log-bin=mysql-bin ###开启日志文件 |
重启mysql服务 service mysqld restart
验证是否已经配置成功
show variables like '%server_id%';
能够查询对应配置文件中的server_id 说明已经配置成功
show master status;
能够看到同步的文件,和行数 说明已经配置成功。
创建从服务器连接需要使用的账户:
create lming test identified by '123456'; grant all privileges on *.* to 'lming'@'%'identified by '123456' with grant option; flush privileges;
|
all代表接受所有操作,比如 select,insert,delete....; *.* 代表所有库下面的所有表;% 代表这个用户允许从任何地方登录;为了安全起见,这个%可以替换为你允许的ip地址;
从服务器节点
克隆服务器
vi /etc/my.cnf server_id=104 ###从服务器server_id log-bin=mysql-bin ###日志文件同步方式 binlog_do_db=test ###同步数据库 |
重启mysql服务 service mysqld restart
验证是否已经配置成功
show variables like '%server_id%';
能够查询对应配置文件中的server_id 说明已经配置成功
从服务器同步主服务器配置
关闭同步 stop slave; 使用master提供的账户建立同步连接 change master to master_host='192.168.13.103',master_user='lming',master_password='123456', master_log_file=' mysql-bin.000014',master_log_pos= 824; master_log_file需要和Master的File一致,master_log_pos需要与Master的Postiton一致。 开始同步 start slave; 检查从服务器复制功能状态 SHOW SLAVE STATUS
|
Slave_IO_Running和Slave_SQL_Running两个线程都为yes表示同步成功。
重启从服务器mysql:service mysqld restart
验证:在Master上创建表添加数据查看Slave是否会同步数据。
异常:
Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
原因:
因为服务器克隆的时候交UUID产生了重复。
解决办法:
cat /etc/my.cnf
cd /var/lib/mysql
rm -rf auto.cnf
重启服务器即可
service mysqld restart
架构规划
主master 3307 ---> 从slave 3309
主master 3308 ---> 从slave 3310
3307 <---> 3308 互为主从
192.168.13.102(主) |
192.168.13.103(主) |
192.168.13.104(102从) |
192.168.13.105(103从) |
192.168.13.102 my.cnf添加配置
server_id=102 log-bin=mysql-bin binlog_do_db=test ###设置步长 auto_increment_increment=2 ###设置初始值 auto_increment_offset=1 ###开启多主从节点更新同步,如不配置则会出现在master1(102)上进行了更新数据,在master2(103)和slave1(104)上会更新,但是在slave2(105)上不会更新 log-slave-updates ###表示每几次事务提交,MySQL把binlog缓存刷进二进制日志文件中,默认是0,最安全的是设置为1; sync_binlog=1 |
192.168.13.103 my.cnf添加配置
server_id=103 log-bin=mysql-bin binlog_do_db=test ###设置步长 auto_increment_increment=2 ###设置初始值 auto_increment_offset=2 ###开启多主从节点更新同步,如不配置则会出现在master1(102)上进行了更新数据,在master2(103)和slave1(104)上会更新,但是在slave2(105)上不会更新 log-slave-updates ###表示每几次事务提交,MySQL把binlog缓存刷进二进制日志文件中,默认是0,最安全的是设置为1; sync_binlog=1 |
192.168.13.104 my.cnf添加配置
server_id=104 log-bin=mysql-bin binlog_do_db=test |
192.168.13.105 my.cnf添加配置
server_id=105 log-bin=mysql-bin binlog_do_db=test |
(主)创建连接账户
create user lming identified by '123456'; grant all privileges on *.* to 'lming'@'%'identified by '123456' with grant option; flush privileges; |
1. 分别启动四台mysql
2. 在从服务器上停止复制(104、105)
分别执行:
stop slave; reset slave; reset master; |
3. 在102和103上分别执行如下命令已查看同步文件和position值:
show master status; |
5. 在102的两台从服务器上(103、104)执行如下操作实现同步:
stop slave; change master to master_host='192.168.13.102',master_user='lming',master_password='123456', master_log_file='mysql-bin.000002',master_log_pos= 4829; start slave; |
查看从机同步状态:
见到Slave_IO_Running和Slave_SQL_Running为yes表示同步成功了。
6. 在103的两台从服务器上(102、105)执行如下操作实现同步:
stop slave; change master to master_host='192.168.13.103',master_user='lming',master_password='123456', master_log_file='mysql-bin.000017',master_log_pos= 996; start slave; |
7. 查看从机同步状态:
8. 测试多主多从同步
经过测试发现在102/103服务器上创建表(DML操作)在其余所有服务器均会同步,多主多从MySQL集群搭建成功。
MySQL本身是没有实现读写分离的,想要实现读写分离就必须借助于数据库中间件,主流有两种MyCat和Sharding-JDBC。
什么是MyCat?
MyCAT是一款由阿里Cobar演变而来的用于支持数据库,读写分离、分表分库的分布式中间件。MyCAT支持Oracle、MSSQL、MYSQL、PG、DB2关系型数据库,同时也支持MongoDB等非关系型数据库。
MyCAT原理MyCAT主要是通过对SQL的拦截,然后经过一定规则的分片解析、路由分析、读写分离分析、缓存分析等,然后将SQL发给后端真实的数据块,并将返回的结果做适当处理返回给客户端。
官方网站:http://www.mycat.io/
基于MyCat实现读写分离
读写分离,简单地说是把对数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。主数据库进行写操作后,数据及时同步到所读的数据库,尽可能保证读、写数据库的数据一致,比如MySQL的主从复制、Oracle的data guard、SQL Server的复制订阅等。
Linux环境安装MyCat实现读写分离
1、上传安装Mycat-server-1.6.5-release-20180122220033-linux.tar
2、解压安装包tar –zxvf
3、配置schema.xml 和server.xml
schema.xml:
|
server.xml
|
4、客户端连接端口号: 8066
配置文件介绍:
文件 |
说明 |
server.xml |
Mycat的配置文件,设置账号、参数等 |
schema.xml |
Mycat对应的物理数据库和数据库表的配置 |
rule.xml |
Mycat分片(分库分表)规则 |
5、进入bin目录
启动MyCat ./mycat start
停止MyCat ./mycat stop
6、查看/usr/local/mycat/logs wrapper.log日志 如果是为successfully 则启动成功
关闭防火墙:systemctl stop firewalld.service
只可读的账号 user user 端口号8066
可读可写的账号 root 123456 端口号8066
为什么需要使用索引?
MySQL官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。
通俗的讲索引就像书的目录一样可以非常快速的定位到书的页码。
如果向mysql发出一条sql语句请求,查询的字段没有创建索引的话,可能会导致全表扫描,这样的话查询效率非常低。
衡量算法优劣维度
通常,对于一个给定的算法,衡量器优劣是很有必要的,这有助于我们在架构项目时进行技术选型。衡量算法优劣分为两种方式:
事先统计分析法是指的根据算法编写出程序,然后进行大量的测试,对测试数据进行分析,最后得出算法优劣评估报告。
这种方法虽然可行,但不是一个好的方法。该方法有两个缺陷:一是要想对设计的算法的运行性能进行评测,必须先依据算法编制相应的程序并实际运行;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优势。
因事后统计分析法更多的依赖于计算机的硬件、软件等环境因素,有时会遮盖算法本身的优劣,因此诞生了事先估算分析法。
事先估算分析发是指在编写算法程序前依据一定的方法对算法进行估算。首先一一个用高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:
已知任何一个算法都是由控制结构(顺序、分支、循环)和原操作(指固有数据类型操作)构成,所以算法时间消耗取决于两者的综合效果,而我们为了比较对于同一个问题使用不同算法的优劣,我们通常的做法是从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以该基本操作的重复执行的次数作为算法的时间量度。
通俗的说就是给定一台机器,其满足执行一条基本语句或算法花费的单位时间一致(硬件、软件),然后限制所使用的控制结构类型,最后研究其在基本操作重复执行的次数来衡量算法的优劣。
时间复杂度
理解时间复杂度首先需要理解什么是时间频度?
时间频度:
用官方的话来讲一个算法执行所耗费的时间与算法中语句的执行次数成正比,一个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
通俗的说首先我们知道在事先估算分析法中一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。所以我们就使用了时间频度,时间频度就是我们对于这个时间的一个度量单位。
那时间复杂度又是什么呢?
时间复杂度:
在刚才提到的时间频度中,n称为问题的规模,也就是上面所得综合效果,当n不断变化时,时间频度T(n)也会不断变化(正比例)。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,也就是频度,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
上面是官方的解释,T(n)是频度不为零,f(n)函数的到的结果是一个趋近于无穷大n,n是问题规模也不等于零因此T(n)/f(n)自然就是不等于零的常数。
通俗的将时间复杂度就是时间频度的规律,通过这个规律我们能在事先衡量一个问题使用某个算法需要多少时间,虽然这个时间不确定,但我们能得到一个粗略的量度。
时间复杂度与时间频度的区别就在于时间频度只是记录了某个语句执行的次数,而时间复杂的则是多次执行这个算法后某个语句执行次数的变化规律,其实很像物理中的速度与加速度的区别。
好了通过上面一大段废话终于说清楚时间复杂度是什么了,那么空间复杂度又是什么呢?
空间复杂度:
类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。
一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。
存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。
算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。
算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是“就地"进行的,是节省存储的算法。有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如快速排序和归并排序算法就属于这种情况。
总结:具体地说就是时间复杂度与事件频度有关,而时间频度由与两个综合因素有关(控制结构、原操作),空间复杂度则不同只与三种被占用的空间大小有关(本身空间,输入输出数据空间、运行时空间),而具体又分为三种情况(如上所述三种)。
Hash算法数据结构
哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
算法:index=Hash(key)
Hash算法演变出了两种数据结构:
开放寻址即每一个值都会存入哈希表对应的一个hash槽中,如果其hash槽已经有值了,官方话语称为“Hash碰撞”,则会插入其相邻的后一个槽位,以此类推。
开放寻址演示网址:https://www.cs.usfca.edu/~galles/visualization/ClosedHash.html
封闭寻址采用链表法实现,会将相同Hash值对象组成一个链表存放在Hash槽中,与二维数组概念类似,这样当发生“Hash碰撞”会将碰撞的Value插入到Key对应的Hash链表的Hash槽中。Java8以前HashMap采用的就是这种算法,Java8后改用红黑树算法。
封闭寻址演示网址:https://www.cs.usfca.edu/~galles/visualization/OpenHash.html
Hash算法优点:
查找可以直接根据key访问,速度快。
Hash算法缺点:
不能进行范围查找,不实用。
二叉树算法数据结构
由于Hash数据结构并不支持范围查询因此诞生了二叉树数据结构,那么什么是二叉树数据结构呢?
二叉查找树,又称“二叉搜索树”,因为其数据结构图像一颗倒着的树而得名,是具有一下性质的树:
二叉树演示网址:https://www.cs.usfca.edu/~galles/visualization/BST.html
二叉搜索树优点:
相比于Hash数据结构,不会出现碰撞,并且可以进行范围查询。
二叉搜索树缺点:
AVL平衡二叉搜索树算法数据结构
平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值(平衡因子)不超过1。也就是说AVL树每个节点的平衡因子只可能是-1、0和1(左子树高度减去右子树高度)。
AVL树演示网址:https://www.cs.usfca.edu/~galles/visualization/AVLtree.html
AVL树优点:
相比于二叉搜索树,高度有所下降,不再会出现链表情况,时间复杂度也有降低,算法整体效率更高。
AVL树缺点:
红黑树算法数据结构
红黑树(Red-Black Tree)是二叉搜索树(Binary Search Tree)的一种改进。我们知道二叉搜索树在最坏的情况下可能会变成一个链表(当所有节点按从小到大的顺序依次插入后)。而红黑树在每一次插入或删除节点之后都会花O(log N)的时间来对树的结构作修改,以保持树的平衡。也就是说,红黑树的查找方法与二叉搜索树完全一样;插入和删除节点的的方法前半部分节与二叉搜索树完全一样,而后半部分添加了一些修改树的结构的操作。
红黑树基于二叉搜索树,但每个节点除了有key、三个指针:parent(指向父节点)、lchild(指向左节点)、rchild(指向右节点)以外,还多了一个属性color,color只能是红色或黑色,并且红黑树除了需要遵循二叉搜索树的三个性质以外,还需要具备如下四个性质:
提示:按下方地址演示会看到40节点颜色的变化,以及结构的改变。
红黑树演示地址:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
红黑树树优点:
相比于二叉搜索树,高度有所下降,不再会出现链表情况,时间复杂度也有降低,算法整体效率更高。
区别于AVL树的平衡算法,红黑树通过更改结构和颜色来实现平衡,根据统计数据,在性能方面红黑树要比AVL平衡二叉树更加优秀。
红黑树缺点:
B-树算法数据结构
维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。”
B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。
通俗的说,B-树算法继承了AVL树特点,并在其基础上进行了扩展,AVL树每一个节点只允许最多拥有2个关键字,而B-树允许每个节点最少拥有M/2-1个关键字最多拥有M-1个关键字,具体满足的性质如下:
注意:实际情况中任何一个节点都不可能永久拥有M个节点,因为一旦某个节点的子节点数达到了M个就会进行分裂,我们称之为“满了”,满了就会分裂出新节点。 但是在未完成分裂前原有节点还是会有片刻时间拥有M个节点的。
具体请参照下图与演示地址进行理解!
B-数演示地址:https://www.cs.usfca.edu/~galles/visualization/BTree.html
B-树优点:
相比于AVL树/红黑树,每一个节点的容量提升,高度大幅度下降,时间复杂度也有降低,并且会大大减少范围查询时的“回旋”的次数,也就减少了IO操作次数。
B-树缺点:
B+树算法数据结构
B+树是B-树的变体,也是一种多路搜索树,除了需要满足B-树的基本性质以外还新增如下性质:
以上为官方解释!
新增叶子节点与非叶子节点关系,叶子节点中包含了key和value,非叶子节点中只是包含了key,不包含value。
所有相邻的叶子节点包含非叶子节点,使用链表进行结合,有一定顺序排序,从而范围查询效率非常高。
演示连接:https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html
B+树优点:
B+树缺点:
节点“满了”时进行分裂,空间复杂度高。
B*树算法数据结构
B-Tree类算法最终进化形态——B*树。
B*树是B+树的变体,在B+树的非根和非叶子节点上再增加指向兄弟节点的指针。
相信理解了B+树的你一定能看懂这幅图,什么?你看不懂?那我再给你详细介绍一下吧。
首先我们来说一下B+树与B*树分裂时不同的处理方式:
B+树的分裂:
当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针。B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。
B*树的分裂:
当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了)。如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。
根据以上B+树与B*树分裂的对比可看出,B+树一旦节点“满了”就会分裂新节点存储关键字,原节点分配规则为(M*1/2),而B*树会具情况而定,且原节点与其兄弟节点分配规则为(M*1/3),B+树分配规则,没有合理的利用空间,而是直接创建新的空间,导致不论是原节点空闲空间还是新节点空闲空间都很大,而B*树利用了其兄弟节点空闲空间,使得空间复杂度下降。
B+树优点:
B+树缺点:
兄弟节点“满了”时原节点任然会进行分裂,相比较于AVL树、红黑树空间复杂度高。
MySQL的MyISAM引擎与InnoDB引擎的区别?
主键索引: MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。这里设表一共有三列,假设我们以Col1为主键,如下图MyISAM表的主索引(Primary key)示意:
然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同.
MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。
我们知道MySQL底层是使用的B+树结构,那又为什么使用B+树呢?
为什么MySQL底层使用b+树?
B+树相比B树,新增叶子节点与非叶子节点关系,叶子节点中包含了key和value,非叶子节点中只是包含了key,不包含value。
所有相邻的叶子节点包含非叶子节点,使用链表进行结合,有一定顺序排序,从而范围查询效率非常高
注意:MyISAM和InnoDB对B-Tree索引不同的实现方式
MyISAM底层使用B+树 叶子节点的value对应存放行数的地址,在通过行数定位到数据。
InnoDB底层使用B+树,叶子节点的value对应存放是行的data数据,相比MyISAM效率要高一些,但是比较占硬盘内存大小。
MySQL B+树能够存放多少字节数据?
局部性原理与磁盘预读
计算机科学中著名的局部性原理当一个数据被用到时, 其附近的数据也通常会马上被使用。
为了提高效率,磁盘往往不是严格按需读取,而是每次都会预读,即使只需要一个字节,磁盘也会从这个位置开始,顺序向后读取一定长度的数据放入内存。
这里的一定长度叫做页,也就是操作系统操作磁盘时的基本单位。一般操作系统中.页的大小是4Kb (getconf PAGE_SIZE)
所以如果在磁盘中读取1kb,实际会读取4kb。
假设在B+树一个节点为1页
如果从磁盘读取超过1页大小,根据局部性原理与磁盘预读 会读出2页大小
如果从磁盘读取小于1页大小,根据局部性原理与磁盘预读 会读出1页大小
根据以上规则,如果读取正好是页的倍数,这样就可以不用浪费,所以B+树的每一个节点是页的倍数是最佳的。
在MySQL中我们的InnoDB页的大小默认是16k,当然也可以通过参数设置:
show variables like 'innodb_page_size';
16384/1024=16kb;
回到问题上,MySQLb+树能够存放多少字节数据?
假设一行为1kb,那么一页可以读取16行数据,一个叶子节点可以存放16条数据
那么非叶子节点存放多少条数据?非叶子节点存放索引值(bigint 8b)和指针(6b)
那么一页16*1024/(8+6)=1170指针
B+树 高度为2 1170*16=18720 条数据
B+树 高度为3 1170*1170*16=21902400 条数据
所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。
Mysql的优化,大体可以分为三部分:索引的优化,sql慢查询的优化,表的优化。
开启慢查询日志,可以让MySQL记录下查询超过指定时间的语句,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。
先捕获低效SQL→慢查询优化方案→慢查询优化原则
MySQL数据库配置慢查询
参数说明:
slow_query_log 慢查询开启状态
slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)
long_query_time 查询超过多少秒才记录
1.查询慢查询配置
show variables like 'slow_query%';
2.查询慢查询限制时间
show variables like 'long_query_time';
3.将 slow_query_log 全局变量设置为“ON”状态
set global slow_query_log='ON';
4.查询超过1秒就记录
set global long_query_time=1;
5.查询cat /var/lib/mysql/localhost-slow.log
service mysqld restart
explain是MySQL提供给开发者分析SQL的关键字,通过EXPLAIN我们可以查看到SQL是否使用了索引,操作的数据行数等等信息。
数据库优化开启慢查询是每个程序员都必须懂得要领!
索引为什么会失效?注意那些事项?
1.索引无法存储null值
2.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
3.对于多列索引,不是使用的第一部分,则不会使用索引
4.like查询以%开头
5.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
6.如果mysql估计使用全表扫描要比使用索引快,则不使用索引
联合索引为什么需要遵循左前缀原则?
如果在一张表中,存在联合索引的话,在根据条件查询的时候必须要加上第一个索引条件。
EXPLAIN select * from user_details WHERE id=1 and user_name=‘zhangsan’;--索引生效
EXPLAIN select * from user_details WHERE user_name=‘zhangsan’;--索引是不生效的
因为索引底层采用B+树叶子节点顺序排列,必须通过左前缀索引才能定位到具体的节点范围。
表分库为什么能够提高数据库查询效率?
因为将一张表的数据拆分成多个n张表进行存放,让后再使用第三方中间件(MyCat或者Sharding-JDBC)并行同时查询,让后在交给第三方中间进行组合返回给客户端。