11.s_性能优化

性能下降SQL慢 执行时间长 等待时间长

  • 查询数据过多

    能不能拆,条件过滤尽量少

  • 关联太多表,太多join

    join 原理。用 A 表的每一条数据 扫描 B表的所有数据。所以尽量先过滤。

  • 没有利用索引

    1. 单值 ==> create index idx_user_name on user(name)
    2. 复合
  • 服务器调优及各个参数设置(缓冲、线程数等)(不重要的DBA工作)

索引

是帮助MYSQL高效率获取数据的数据结构。(本质是数据结构,可以类比字典–排好序的快速查找数据结构b树)

索引本身也很大,不可能全部存在内存中,,因此往往以引索文件的的形式存储在磁盘上。

平常没有特别指明都是B树(不一定是二叉树)结构组织的索引,其中聚集索引、次要索引、覆盖索引、复合索引、前缀索引、唯一索引默认都是B+树索引、其他还有哈希索引(hash index)

优势
  • 类似大学图书馆数目引索、提高数据检索的效率,降低数据库的IO成本
  • 通过引索多数据进行排序、降低数据排序的成本、降低CPU的消耗
劣势
  • 提高查询速度,但降低了更新表的速度。多保存索引文件每次更新添加了索引列的字段
  • 需要花时间建立最优索引,或优化查询

单值索引 一个索引只包l含单个个例,一个表可以有多个单列索引

唯一索引 索引列的值必须唯一,但允许有空值

复合索引 一个索引包含多个个例

#有四种方式来添加数据表的索引:
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)#: 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。

ALTER TABLE tbl_name ADD UNIQUE index_name (column_list)#: 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。

ALTER TABLE tbl_name ADD INDEX index_name (column_list)#: 添加普通索引,索引值可出现多次。

ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list)#:该语句指定了索引为 FULLTEXT ,用于全文索引。
#复合索引:
create index idx_no_name on emp(no,name);#  // no 与  name 有同一个索引 idx_no_name
#单值索引:
create index idx_no on emp(no);
create index idx_name on emp(name);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HYk35rDA-1599482056467)(C:\Users\Administrator\Desktop\数据库学习-mysql\B-tree.jpg)]

【初始化介绍】
非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如17、35并不真实存在于数据表中。

【查找过程】
如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘块1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同时内存中做二分查找找到29,结束查询,总计三次IO。

真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hD5rsjUW-1599482056470)(C:\Users\Administrator\Desktop\数据库学习-mysql\B+tree.jpg)]

常见性能瓶颈
  • CPU

SQL中对大量数据进行比较、关联、排序、分组

  • IO

实例内存满足不了缓存数据或排序等需要,产生大量物理IO

不适宜的锁设置,导致线程阻塞,性能下降

死锁,线程之间交叉调用资源,导致死锁

  • 服务器硬件性能 ,top,free,iostatvmstat来查看系统性能状态

====>>>>>> 使用 EXPLAIN 关键字可以模拟优化SQL查询语句,从而知道Mysql是如何处理sql语句的。

三步走 ===>>> 优化器、看瓶颈、使Explain

@@@@@@Explain + SQL 检查@@@@@@@@

  • 表的读取顺序
  • 哪些引索可以用
  • 数据读取操作的操作类型
  • 哪些引索被实际使用
  • 表之间的引用
  • 每张表有多少行被优化器查询
执行计划包含信息

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |

  • ​ * *
join语句的优化
ALTER TABLE 'phone' ADD INDEX z('card');
ALTER TABLE 'book' ADD INDEX Y('card'); #上一个case建一个同样的
ENABLE SELECT * FROM class LEFT JOIN book ON class.card=book.card LEFT JOIN phone ON book.card = phone.card
  • 尽可能减少join语句中NestedLoop的循环总数,“永远用小结果集驱动大结果集”
  • 优先优化NestedLoop的内层循环
  • 保证Join语句中被驱动表上Join条件的字段已经被索引
  • 当无法保证被驱动表的Join条件字段被索引且内存资源充足的前提下,不要吝惜JoinBuffer的设置

在这个使用buffer的例子中,可以看到这个地方只是对于tsecer表进行了一次扫描,而通常来说,数据库的扫描代码是最高的(因为要涉及到磁盘读取),这样使用buffer的方式将tsecer表的扫描降低为1次,所以这个效率提高很多,特别是在涉及到的多个table,并且/或者 每个table中的记录数量都很多的情况下。

索引优化
  1. 全值匹配

  2. 最佳左前缀法则

    • 查询从索引最左列开始,且不跳过引索中的列
  3. 不要再索引列上做任何操作(计算、函数、(自动/手动)类型转换),会导致全表扫描

    explain SELECT * FROM staff WHERE left(NAME,4) = 'July':
    
  4. 尽量使用覆盖引索(只访问引索的查询(索引列和查询列一致))减少select *

  5. 使用不等于(!= 或者 <>)的时候无法使用索引会导致全表扫描

  6. is not null无法使用引索,但是is null可以使用

  7. like以通配符开头(’%abc’)mysql 引索失效会变成全表扫描操作,%加在右边会好点

    使用覆盖索引来解决

    #create index
    CREATE INDEX idx_user_nameAge ON tbl_user(name,age);
    
    SELECT id,NAME FROM tbl_user WHERE NAME LIKE '%aa%'
    SELECT id,NAME,age FROM tbl_user WHERE NAME LIKE '%aa%'
    SELECT NAME,age FROM tbl_user WHERE NAME LIKE '%aa%'
    
    #以上都有效  查询与建立索引字段个数顺序
    
  8. 字符串不加单引号引索失效(隐式类型转换)

  9. 少用or

假设index(abc)

Where语句 索引是否被使用
where a = 3 Y,使用到a
where a = 3 and b = 5 Y,使用到a,b
where a = 3 and b = 5 and c = 4 Y,使用到a,b,c
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4 N
where a = 3 and c = 5 使用到a, 但是c不可以,b中间断了
where a = 3 and b > 4 and c = 5 使用到a和b, c不能用在范围之后,b后断了
where a = 3 and b like ‘kk%’ and c = 4 Y,使用到a,b,c
where a = 3 and b like ‘%kk’ and c = 4 Y,只用到a
where a = 3 and b like ‘%kk%’ and c = 4 Y,只用到a
where a = 3 and b like ‘k%kk%’ and c = 4 Y,使用到a,b,c

面试
  1. 查询优化器可以优化mysql语句(查询顺序)

    #index(c1,c2,c3,c4)
    #const const const const
    explain select * from test03 where c1='a1' and c2='a2' and c3='a3' and c4='a4'
    
    #范围之后全失效 keylen => 93
    explain select * from test03 where c1='a1' and c2='a2' and c3>'a3' and c4='a4'
    
    #底层调优 ==> 3 x const keylen => 124
    explain select * from test03 where c1='a1' and c2='a2' and c4>'a4' and c3='a3'
    
    #c3作于与排序而非查找,没有统计于const				const keylen => 64
    explain select * from test03 where c1='a1' and c2='a2' and c4='a4' order by c3
    
    #extre ==> Using filesort	性能下降	       const keylen => 64
    explain select * from test03 where c1='a1' and c2='a2' order by c4
    
    #extre ==> c2,c3用于排序	      
    explain select * from test03 where c1='a1' and c5='a5' order by c2,c3
    
    #extre ==> Using filesort                     
    explain select * from test03 where c1='a1' and c5='a5' order by c3,c2
    
    #extre ==> c2,c3用于排序	      
    explain select * from test03 where c1='a1' and c2 = 'a2' order by c2,c3
    
    #extre ==>无 Using filesort  !!!! 此时c2为常量          复合引索树结构            
    explain select * from test03 where c1='a1' and c2='a2' and c5='a5' order by c3,c2
    
    #extre ==>
    explain select * from test03 where c1='a1' and c4='a4' order by c2,c3
    
    #extre ==> using temporary using filesort      
    explain select * from test03 where c1='a1' and c5='a5' order by c3,c2
    

    group by 几乎和order by一致

  • 对于单值索引,尽量选择对当前query过滤性更好的索引
  • 组合索引时,当前query过滤性更好的索引位置越靠前越好
  • 尽量选择可以能够包含query中where字句中更多字段的索引
  • 尽可能通过分析统计信息和调整query写法来达到选择合适索引的目的

官方文档 https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types

order by一致

  • 对于单值索引,尽量选择对当前query过滤性更好的索引
  • 组合索引时,当前query过滤性更好的索引位置越靠前越好
  • 尽量选择可以能够包含query中where字句中更多字段的索引
  • 尽可能通过分析统计信息和调整query写法来达到选择合适索引的目的

官方文档 https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值