MySql
2023-12-26 09:26:03 53 举报
AI智能生成
MySql
作者其他创作
大纲/内容
基本概念<br>
SQL语句分类
DDL
数据定义语句(create drop alter)<br>
DML
数据操作语句(insert update delete)
子查询操作符
all<br>
any<br>
合并查询
union
union all
intersect
minus
DQL
数据查询语句(select)
DCL
数据控制语句(grant revoke commit rollback)<br>
基本操作语句
显示数据库创建语句:<u>SHOW CREATE DATABASE db_name</u>
辅助操作
约束
not null
unique<br>
primarykey
foregin key
<u>check</u>
触发器
函数
存过程
数据备份为sql文件及数据恢复
备份<br>
恢复
函数
时间日期函数
字符串函数
数字函数
流程相关函数
其他函数
mysql用到字符编码的地方
client:客户端字符集
connection:连接数据库的字符集,不指定则使用服务端默认字符集<br>
database:指定数据库使用的字符集,若建库时不指定则使用服务器字符集
result:数据库给客户端返回的字符集,若不指定则使用服务器默认字符集
server:服务器安装时使用的默认字符集
system:数据库系统使用的字符集
事务和锁
事物
原子性<br>持久性<br>一致性
redo log
用户崩溃时恢复数据(WAL预写日志的方式,在数据提交前记录日志(日志文件顺序存储速度快));<br>Force Log at Commit(1.设定参数每隔一段时间落盘;2.事物提交时落盘)保证该日志落盘(从redo log buffer 到 redo log),以此来达到奔溃时数据可能恢复;。<br>总的有两个日志空间交替使用,当空间满的时候出发数据文件落盘(Buffer Poll 到 数据文件),数据文件落盘之后及可清除redo log日志文件<br>
force log at commit
保证事物提交之后redo log已经持久化<br>
Double write
用于提高数据库的可靠性,用于解决脏页落盘时部分写失效问题<br>
操作系统磁盘最小单位4KB;<br>mysql最小操作单位16KB;<br>duble write 保证mysql的数据页要么全部成功,要么全部失败<br>
undo log<br>
用于对数据回滚时进行撤销,也会用于隔离性的多版本控制<br>
控制台操作
0) start transaction //开始一个事务 <br>1) savepoint 保存点名 //设置保存点<br>2) rollback to 保存点名 //取消部分事务<br>3) rollback //取消全部事务<br>4) commit //提交事务.
隔离性
读未提交(脏读)
当一个事务读取另一个事务尚未提交的修改时,产生脏读
读已提交(不可重复读)
<font color="#f15a23">同一查询</font>在<font color="#f15a23">同一事务</font>中多次进行,由于其他提交事务所做的<font color="#f15a23">修改</font>,每次返回不同的结果集,此时发生非重复读<br>
重复读(幻读)
<font color="#f15a23">同一查询</font>在<font color="#f15a23">同一事务</font>中多次进行,由于其他提交事务所做的<b><font color="#f15a23">插入</font></b>操作,每次返回不同的结果集,此时发生幻读。
导致一条数据查询不存在,但是插入也不能成功(因为别的事物插入了该数据,而当前session不可见)
序列化
相关操作指令
1.查看当前会话隔离级别:<font color="#f68b1f"> select @@tx_isolation;</font><br>
2.查看系统当前隔离级别:select @@global.tx_isolation;
3.设置当前会话隔离级别:set session transaction isolation level repeatable read;
4.设置系统当前隔离级别:set global transaction isolation level repeatable read;
5. mysql 默认的事务隔离级别是 repeatable read
锁
insert/update/delete
for update
mysql使用行锁,首先得明确使用的是innoDB引擎
innoDB存储引擎加行锁,<font color="rgba(0, 0, 0, 0)"><b>实际是对索引加锁</b></font>
分类<br>
表级锁<br>
特征<br>
开销小,加锁快,不会出现死锁;<br>粒度大,发生锁冲突概率大,并发低<br>
适合以查询为主
读锁<br>
local table table_name read<br>
<b>现象:<br><ul><li>可以对表进行读操作;</li><li>当前session对表进行CUD操作(报错);</li><li>其他session进行CUD操作(等待)</li></ul></b>
写锁
local table table_name write<br>
<b>现象:<br><ul><li>当前session可以进行CRUD操作;</li><li>其他session CRUD操作(等待)</li></ul></b>
释放锁<br>
unlock tables<br>
行级锁<br>
读锁<br>
不允许其他session 再来加排他锁,但可以加读锁<br>
select * from table_name where ** lock in share mode<br>
写锁
不允许其他事物写和加锁,但允许读
select * from table_name where ** for update<br>
特征
开销大、加锁慢、会出现死锁;<br>粒度小,发生锁冲突低,并发高<br>
注意<br>
<u>行锁必须要有索引才能实现,否则锁全表</u>
CUD默认都会加行级锁
页面锁
特征
开销介于表级别锁与行级别锁之间;<br>会出现死锁;<br>粒度介与表级锁与行级锁之间;并发一般。<br>
BDB引擎使用
间隙锁
索引
分类
聚集索引(主键索引)<br>
非聚集索引<br>
基本操作<br>
查看索引
show index from 表名<br>
创建索引
CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));<br>ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length)) <br>
删除索引
DROP INDEX [indexName] ON mytable;<br>
存储引擎
事务安全型
innoDB
特征
5.5 后默认引擎,系统表空间;<br>5.6后默认使用独立表空间<br>
表空间相关参数:innodb_file_per_table<br>
系统表空间无法简单收缩文件大小<br>
独立表空间可以使用optinized table 收缩文件大小<br>
系统表空间会产生IO瓶颈
独立表空间可以同时向多个文件刷新数据
支持事物
redo.log, undo.log<br>
行级锁(默认),表级锁<br>
行锁为索引加锁,如果where字段不是索引,将会锁全表<br>
5.6之后支持全文索引,对中文支持需要特殊配置处理
InnoBD引擎架构
buffer pool<br>(缓冲池)
主内存中的一个区域,在InnoDB访问<b>表数据</b>和<b>索引数据</b>的时候,会顺便把对应的数据页缓存到<b>缓冲池</b>中;<br>专用服务器上,通常将80%左右的物理内存分配给缓冲池;<br>提高缓存管理效率,<b>缓冲池把页面链接为列表</b>,使用改进版的LRU算法将很少使用的数据从缓存中老化淘汰掉.<br>
LRU
当需要把新页面存储到缓冲池中的时候,将淘汰最近最少使用的页面,并将<b>新页面添加到旧子列表的头部</b>。<br>
<ul><li>默认 3/8缓冲池用于旧子列表;</li><li>当新页面如缓冲池时,首先将其插入旧子列表头部;</li><li>重复访问旧子列表的页面,将使其移动至新子列表的头部;</li><li>随着数据库的运行,页面逐步移至列表尾部,缓冲池中未被方位的页面最终将被老化淘汰。</li></ul>
`innodb_old_blocks_pct`:控制LRU列表中旧子列表的百分比,默认是37,也就是3/8,可选范围为5~95;<br>`innodb_old_blocks_time` :指定第一次访问页面后的时间窗口,该时间窗口内访问页面不会使其移动到LRU列表的最前面。默认是1000,也就是1秒。
innodb_old_blocks_time很重要,有了这1秒,对于全表扫描,<br>由于是顺序扫描的,一般同一个数据页的数据都是在一秒内访问完成的,<br>不会升级到新子列表中,一直在旧子列表淘汰数据,所以不会影响到新子列表的缓存。<br>
文件IO
innodb_flush_method
将数据刷新到InnoDB数据文件和日志文件的方法,这可能会影响I/O吞吐量
change bugger
当二级索引页(非唯一索引)不在缓冲池中时,它们会缓存这些更改 。当页面通过其他读取操作加载到缓冲池中时,再将由INSERT,UPDATE或DELETE操作(DML)产生的change buffer合并到buffer pool的数据页中。
索引不可以使用chage buffer
自适应哈希索引
自适应哈希索引功能由innodb_adaptive_hash_index变量启用 ,或在服务器启动时由--skip-innodb-adaptive-hash-index禁用。
Log Buffer
og buffer(日志缓冲区)用于保存要写入磁盘上的log file(日志文件)的数据。日志缓存区的内容会定期刷新到磁盘。<br>日志缓冲区大小由innodb_log_buffer_size变量定义 。默认大小为16MB。较大的日志缓冲区可以让大型事务在提交之前无需将redo log写入磁盘。<br>如果您有更新,插入或者删除多行的事务,尝试增大日志缓冲区的大小可以节省磁盘I/O。
参数配置<br>
innodb_flush_log_at_trx_commit
控制如何将日志缓冲区的内容写入并刷新到磁盘
通过该参数获取更好的性能,但是会导致在系统崩溃的过程中导致数据丢失。
可选参数:<br><ul><li>0,事务提交之后,日志只记录到log buffer中,每秒写一次日志到缓存并刷新到磁盘,尚未刷新的日志可能会丢失;</li><li>1,要完全符合ACID,必须使用该值,表示日志在每次事务提交时写入缓存并刷新到磁盘;</li><li>2,每次事务提交之后,日志写到page cache,每秒刷一次到磁盘,尚未刷新的日志可能会丢失;</li></ul>
innodb_flush_log_at_timeout
控制日志刷新频率。可让您将日志刷新频率设置为N秒(其中N为1 ... 2700,默认值为1)
为了保证数据不丢失,请执行以下操作:<br>如果启用了binlog,则设置:sync_binlog=1;<br>innodb_flush_log_at_trx_commit=1;
表空间
系统表空间
独立表空间
通用表空间
当`innodb_file_per_table`启用时,通常是将表存放在独立表空间中,这是默认配置;<br>当`innodb_file_per_table`禁用时,则会在系统表空间中创建表;<br>请使用 `CREATE TABLE … TABLESPACE`语法。
frm文件
创建一个InnoDB表时,MySQL 在数据库目录中创建一个.frm文件
InnoDB它还在系统表空间内的自身内部数据字典中编码有关表的信息。MySQL删除表或数据库时,将删除一个或多个.frm文件以及InnoDB数据字典中的相应条目。
ibd文件
在独立表空间创建的表,还会在数据库目录中生成一个 .ibd表空间文件
通用表空间中创建的表在现有的常规表空间 .ibd文件中创建
ibdata文件
系统表空间文件,在 InnoDB系统表空间中创建的表在ibdata中创建。
逻辑存储结构(五级)<br>
表空间
段<br>
区
页
行
分类
系统表空间
独立表空间<br>
通用表空间<br>
undo 表空间<br>
redo log
四大特性<br>
插入缓冲(insert buffer)
二次写(duble write)<br>
double write
自适应哈希索引(ahi)<br>
维护索引叶页面中所有记录的索引键值(或键值前缀)到索引叶页面位置的Hash映射关系
预读(read ahead)<br>
数据和索引都存在同一个文件中.idb
BDB
页级锁
非事务安全型
MYISAM
特性<br>
并发高,支持表级锁<br>
支持全文检索<br>
5.6之后innodb也支持全文索引,5.6之前只有myisam支持
支持数据压缩
myisampack -b -f **.MYI<br>
不支持事物<br>
适用场景<br>
非事务应用
只读型应用
空间类(空间函数、坐标)<br>
<font color="#f15a23"><u><b>内部维护有数据计数器</b></u></font>,select count(*)很快<br>
MERGE
是 MyISAM 类型的一种变种。合并表是将几个相同的 MyISAM 表合并为一个虚表。<font color="#ff9800">常应用于日志和数据仓库</font><br>
ISAM
ISAM 简称为索引顺序访问方法。它是由 IBM 开发的,<font color="#ff9800">用于在磁带等辅助存储系统上存储和检索数据</font>。
HEAP(memory)
特征
所有数据保存在内存中<br>
支持Hash索引和bTree索引<br>
所有字段都是固定长度varchar(10)=char(10)<br>
不支持blog和text等大字段<br>
使用<b>表级锁</b><br>
最大大小以max_heap_table_size参数决定<br>
使用场景<br>
用于保存数据产生的中间表<br>
用于缓存周期性聚合数据的结果表<br>
archive
特征
以zlib对表数据进行压缩,磁盘IO更少,数据存储在ARZ为后缀的文件中<br>
只支持insert和delete操作<br>
只允许在自增ID列加索引
使用场景
日志和数据采集等
federated<br>
默认禁止<br>
如需要使用在启动前在配置文件中增加配置:federated=1
CVS<br>
特征
数据已文本方式存储<br>
文件存储内容:**.cvs
表结构:**.frm
文件存储表元数据(表状态,数据量): **.csm<br>
所有列不能为空,在创建表的时候需就需要指定
不支持索引,不适合大表,不适合在线索引
可以对数据文件进行直接编译
数据和索引分开存储:<br>数据 .MYD <br>索引 .MYI<br>
修改存储引擎
ALTER TABLE `表名` ENGINE = 储存引擎;
相关操作<br>
show engines 查看当前提供的存储引擎<br>
show variables like '%storage_engine%' 查看默认搜索引擎<br>
MVCC<br>(多版本并发控制)<br>
基本概念
当前读
像 select lock in share mode (共享锁), select for update; update; insert; delete (排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁
快照读
像不加锁的 select 操作就是快照读,即不加锁的非阻塞读;
数据库并发场景
读-读
读-写
MVCC解决该问题
为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。
写-写
维持一个数据的多个版本,使得读写操作没有冲突
快照读就是 MySQL 实现 MVCC 理想模型的其中一个非阻塞读功能
MVCC 模型在 MySQL 中的具体实现则是由<br> 3 个隐式字段,undo 日志 ,Read View 等去完成的<br>
三个隐式字段
DB_TRX_ID
DB_ROLL_PTR
DB_ROW_ID
删除字段
undo日志
insert undo log
update undo log
purge
Read View<br>(读试图)
RR级别
某个事务的<font color="#e65100"><b><u>对某条记录的第一次快照读会创建一个快照及 Read View</u></b></font>, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,还是使用的是同一个 Read View,所以只要当前事务在其他事务提交更新之前使用过快照读,那么之后的快照读使用的都是同一个 Read View,所以对之后的修改不可见
RC级别
每次快照读都会新生成一个快照和 Read View , 这就是我们在 RC 级别下的事务中可以看到别的事务提交的更新的原因
间隙锁
磁盘文件
日志文件
错误日志文件(error log)
二进制日志文件(bin log)<br>【mysql服务】<br>
需要手动开启
通用查询日志(general query log)
慢查询日志(show query log)
中继日志(relay log)
主从复制时,从库从主库获取过来的bin log日志在本地保存为中继日志(relay log)<br>
重做日志文件(redo log)
用于奔溃时回复数据,循环使用;<br>根据checkpoint脏页落盘成功之后就可以清除该记录(当redolog空间不足也会触发脏页落盘)。<br>
回滚日志文件(undo log)<br>【innodb存储引擎】<br>
事物回滚
隔离性,多版本控制
ibdata
*.fmt
磁盘
随机写文件
数据(数据增删很频繁)<br>
顺序写文件
日志(写得快,都是增量)
keepalived/HAProxy<br>
keepalived
检查被代理服务器的可用性<br>
任意时间只有一个服务(获得与keepalived连接的服务)对外提供服务
被代理服务通过抢占的方式去争夺与keepalived的链接,一旦有连接成功,别的需等待该连接失效
HAProxy
动态代理服务器,更多的类似nginx
执行流程
查询流程
整体架构
sql执行流程<br>
1.先尝试从<u><strike>查询缓存</strike>(8.0以后不再有查询缓存)</u>中查询该sql是否已经有<b>缓存</b>的结果了;<br>2.<b><font color="#f15a23">分析器</font></b>拿到sql之后会尝试对sql语句进行<font color="#f15a23">词法分析和<b>语法分析,校验语法</b></font>的正确性;<br>3.<b><font color="#f15a23">优化器</font></b>拿到分析器的sql之后,开始继续解析sql,<font color="#f15a23">判断需要走什么<b>索引</b>,根据实际情况<b>重写sql</b>,最终生成<b>执行计划</b></font>;<br>4.<b><font color="#f15a23">执行器</font></b>根据执行计划执行sql,执行之前会先进行<b><font color="#f15a23">操作权限校验</font></b>;<br>然后根据表存储引擎调用对应接口进行查询数据,这里的扫描行数就是指的接口返回的记录数,执行器拿到返回记录之后进一步加工;<br>5.<b><font color="#f57c00">执行器</font></b>根据sql<b><font color="#ff9800">条件依次筛选数据</font></b>;<br> 从磁盘数据中读取数据到内存<b>Buffer Pool</b>(数据页,索引页)中;<br>
CUD流程
1.数据写入Buffer Pool的同时,先写入数据到redo log buffer中;<br>2.<font color="#f15a23">redo log buffer</font> 依据<font color="#f15a23"> Force log at Commit(按时或事物提交的时候)写入 redo log日志中</font>;<br>3.Buffer pool 依据check point 择时脏页数据落盘;(redo log日志满了也会触发该操作,成功之后会清理redo log日志);<br>4.Double write保证脏页数据不会出现部分落盘失败的情况。<br>
in与exists效率<br>
1. 如果查询的两个表大小相当,使用in和exists差别不大;<br>2. 如果两个表中一个较小,一个较大,则子查询表大的用exists,子查询小的使用in;<br>3. not in和 not exists :如果查询语句使用了not in, 那么内外表都进行全表扫描,没有用到索引;而notexists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in快。
操作命令
show processlist<br>
查看连接池中建立好的连接
Time:表示这个连接多久没有动静了;<br>默认地,如果超过<font color="#c41230"><b>8个小时</b></font>还没有动静,连接器就会<b>自动断开连接</b>,可以通过<b><u>wait_timeout参数进行控制</u></b><br>
限制
任何标准表最多可以创建16个索引列<br>
集群架构<br>
三种方式
MySQL Cluster<br>
复杂
drbd 磁盘镜像 网络raid<br>
维护成本高
MySQL复制
缺点
存在延时问题<br>
操作步骤
1.主库记录bin log日志;<br>2.主库推送bin log日志给从库;<br>3.从库接受日志保存为中继日志(relay log);<br>4.从库线程从中继日志(relay log)还原数据。<br>
bin log日志记录三种方式<br>
statement
记录语句<br>
Row
记录影响的数据行<br>
mix<br>
混合statement 和 row<br>
常用复制架构<br>
一主多从<br>
缺点
从库多了之后,主库推送bin log日志压力会增大<br>
多级复制<br>
从库复制给从库,一级一级传递
双主复制<br>
两个数据库互为主从
需要的技术
浮动IP-keepalived
双主多级复制<br>
复制方式
异步复制<br>
主库dump线程异步负责推送bin log日志给从库<br>
缺点
主从数据不一致
在dump线程还未推送日志或推送过程中挂了
从库性能比主库差等原因,导致在使用数据的时候从库还没有从中继日志(relay log)中恢复数据<br>
异步复制<br>
半同步复制
半同步复制<br>
主库bin log日志要推送在从库中并<font color="#f15a23">记录中继日志(relay log)</font>之后才返回客户端成功<br>
搭建时候需要插件支持
半同步复制,主从库都需要的插件<br>
读写分离实战
核心问题
SQL路由问题
Mysql+keepalived实现双主集群
两个服务都需要设置logs-slave-updates ,<u><b>将从另一个主库收到的日志也保存bin-log日志</b></u>(主从复制情况下,从库收到的中继日志不需要保存一份bin-log日志, 但主从从的情况也需要设置该参数)<br>
spring提供的解决方案
spring提供的多数据源解决方式<br>
分库分表实现
方案
客户端分片
应用层直接实现
定制JDBC协议<br>
定制ORM框架
代理分片<br>
Mycat
常见概念<br>
逻辑库
逻辑表<br>
分片表<br>
非分片表<br>
数据量不大的表,没必要分片
ER表
解决跨库查询的问题(子表和父表存在同一个库,主从明细表等)<br>
全局表(数据冗余)
每个库都保存一个数据(例如字典表一些变更少,数据少的数据)
分片节点<br>
节点主机<br>
分片规则<br>
哈希分片
时间分片
全局序列号<br>(分布式ID生成算法)
基于数据库实现
采用一台服务器一次性申请多个ID放入本地缓存(保证效率)
雪花算法<br>
64位(1位符号(0)+41位时间戳+10位机器标识+12位序列号)
zk实现<br>
持久顺序节点,异步删除不再使用的节点
redis
Cobar<br>
ShardingSphere
TDDL
Mysql-proxy
Oneproxy
Atlas
Vitess
优化
一般操作步骤<br>
1.通过show status了解各种SQL执行频率;<br>
<font color="#f15a23"><b>show [session|global] status [like '???']</b></font><br>
session来表示当前的连接的统计结果(默认),<br>global来表示自数据库上次启动至今的统计结果<br>
show status like ‘Com_%’;
Connections:试图连接MySQL服务器的次数<br>Uptime:服务器工作的时间(单位秒)<br><font color="#f15a23">Slow_queries:慢查询的次数 (默认是慢查询时间10s)</font><br>
2.定位执行效率较低的SQL;
<font color="#f15a23">默认不记录慢查询日志,需要在服务启动时手动开启;</font><br>通过慢查询日志定位执行效率较低的SQL语句。<br>慢查询日志记录了所有执行时间超过long_query_time所设置的SQL语句<br>
慢查询<br>
常用配置
slow_query_log 启动停止记录慢查询日志<br>slow_query_log_file 指定慢查询日志得存储路径及文件(默认和数据文件放一起)<br>long_query_time 指定记录慢查询日志SQL执行时间得伐值(单位:秒,默认10秒)<br>log_queries_not_using_indexes 是否记录未使用索引的SQL<br>log_output 日志存放的地方【TABLE】【FILE】【FILE,TABLE】<br>
记录语句
记录CRUD所有符合条件的语句<br>
分析工具
mysqldumpslow
<u><font color="#c41230">mysqldumpslow -s r -t 10 slow-mysql.log</font></u><br><ol><li> -s order (c,t,l,r,at,al,ar) </li></ol><ul><li> c:总次数</li><li> t:总时间</li><li> l:锁的时间</li><li> r:总数据行</li><li> at,al,ar :t,l,r平均数 【例如:at = 总时间/总次数】</li></ul><ol><li> -t top 指定取前面几天作为结果输出</li></ol>
pt_query_digest
pt-query-digest --explain h=127.0.0.1, u=root,p=password slow-mysql.log<br>
3.通过explain分析低效率SQL的执行情况;<br>
Explain + SQL语句<br>
id
表示查询中执行select子句或操作表的顺序<br>
三种情况<br>
<ol><li>id相同,<b><font color="#c41230">执行顺序由上至下</font></b></li><li>id不同,如果是子查询,id的序号会递增,<font color="#c41230"><b>id值越大优先级越高,越先被执行</b></font></li><li>id相同不同,同时存在</li></ol>
select_type<br>(查询类型)<br>
主要是用于区别普通查询、联合查询、子查询等的复杂查询<br>
<ul><li><b>SIMPLE:简单的 select 查询,查询中不包含子查询或者UNION</b></li><li><b>PRIMARY:若查询中包含任何复杂的子查询,则外层标记为此类型</b></li><li><b>SUBQUERY:在select或where中使用的查询使用该类型</b></li><li><b>DERIVED/MATERIALIZED:在from列表中使用的子查询被标记为DERIVED(衍生),mysql会递归这些子查询,把结果放入临时表中</b></li><li><b>UNION:若第二个select出现在union之后,则被标记为UNNION;若UNION被包含在from子句的查询中,则外层被标记为DERIVED</b></li><li><b>UNION RESULT:从union表获取结果的select</b></li></ul><br>
table
显示这一行数据是关于哪个表<br>
type
type显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏依次是:<br><font color="#c41230"><b>system </b></font>> <font color="#c41230"><b>const </b></font>> <font color="#c41230"><b>eq_ref </b></font>> <font color="#c41230"><b>ref </b></font>> fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > <b><font color="#c41230">range </font></b>> <b><font color="#c41230">index </font></b>> <font color="#c41230"><b>ALL </b></font><br>
<b><font color="#f15a23">system</font>:表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计<br><font color="#f15a23">const</font>:表示通过索引一次就找到了;const用于比较primary key或者unique索引<br><font color="#f15a23">eq_ref</font>:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描<br><font color="#f15a23">ref</font>:非唯一性索引扫描,返回匹配某个单独值的所有行<br><font color="#f15a23">range</font>:只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的where语句中出现了between、<、>、in等的查询<br><font color="#f15a23">index:</font>使用了整个索引文件(全表扫描的一种)<br><font color="#f15a23">all</font>:Full Table Scan,将遍历全表以找到匹配的行<br></b><br>
possible_key
key
key_len
<b>表示索引使用的字节数</b><br>表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。<b>在不损失精确性的情况下,长度越短越好</b><br>key_len显示的值<u>为索引字段的最大可能长度,并非实际使用长度</u>,即key_len是<u>根据表定义计算而得,不是通过表内检索出的</u><br>
key_len计算总结<br>
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值<br>
rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数<br>
extra
包含不适合在其他列中显示但十分重要的额外信息<br>
4.确定问题,并做相应处理。
索引
查看索引的使用情况 <font color="#f15a23"><b>show status like ‘Handler_read%’;</b></font><br><font color="#f15a23">handler_read_key</font>:这个值越高越好,越高表示使用索引查询到的次数。<br> <font color="#f15a23">handler_read_rnd_next</font>:这个值越高,说明查询低效。<br>
常用优化方式
选择合适的存储引擎
合适的数据类型
对表进行水平划分
对表进行垂直划分
数据库参数配置
innodb_additional_mem_pool_size = 64M<br>innodb_buffer_pool_size =1G
选择合适的编码
四个方面
1.数据库设计;
2.sql优化<br>
大批量插入数据
MyISAM:<br>alter table table_name disable keys;<br>loading data//insert语句; <br>alter table table_name enable keys;<br>
Innodb:<br>1,将要导入的数据按照主键排序<br>2,set unique_checks=0,关闭唯一性校验。<br>3,set autocommit=0,关闭自动提交。<br>
优化group by 语句
默认情况,MySQL对所有的group by col1,col2进行排序。这与在查询中指定order by col1, col2类似。<br>如果<u><font color="#f68b1f">查询中包括group by但用户想要避免排序结果的消耗,则可以使用order by null禁止排序</font></u><br>
<u>想要在含有or的查询语句中利用索引,则or之间的每个条件列都必须用到索引,如果没有索引,则应该考虑增加索引</u>
有些情况下,可以使用连接来替代子查询。因为<font color="#f15a23">使用join,MySQL不需要在内存中创建临时表</font>。
原则
优化需要优化的Query<br>定位优化对象性能瓶颈<br>从Explain入手<br><font color="#f15a23"><b>永远小结果集驱动大结果集</b></font>#<br>尽可能在索引中完成排序<br><font color="#f68b1f"><b>只取自己需要的Column</b></font><br>仅仅使用最有效的过滤条件<br>尽可能避免复杂的join和子查询
3.数据库参数设置;
innodb_additional_mem_pool_size = 64M<br>innodb_buffer_pool_size =1G<br>
4.恰当的硬件资源和操作系统
避免索引失效<br>
尽量全值匹配<br>
联合索引,尽量吧联合字段都使用起来
最左匹配原则
如果索引了多列,查询从索引的最左列开始并且不能跳过部分索引<br>
不在索引上做任何操作<br>
不要在索引字段上做操(函数,类型转换,计算)作,会失效<br>
范围条件放最后
范围条件<font color="#f15a23"><b>之后</b></font>的索引字段会索引失效
尽量使用覆盖索引(查询列是索引列),减少使用select *<br>
少用不等于<br>
使用不等于的时候会索引失效导致全表扫描<br>
Null、Not null可能有影响<br>
字段not null(所以字段都有值,此时进行null值判断没有任何意义,如一定要用可使用覆盖索引方式)<br>
条件为is null 索引失效<br>
条件is not null 索引失效<br>
字段为is null<br>
条件为is null 使用索引<br>
条件为is not null 索引失效<br>
like查询使用‘%具体字段’的方式会索引失效,全表扫描<br>
字符串不加单引号会索引失效<br>
类型不匹配会调用函数转类型,从而导致失效
union比or的效率更高
0 条评论
下一页