原作者 https://smartan123.github.io/book/?file=001-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/001-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E9%9D%A2%E8%AF%95%E9%A2%98%E9%9B%86%E9%94%A6#%E4%B8%80%E3%80%81tomcat%E6%9C%89%E5%93%AA%E4%BA%9B%E9%85%8D%E7%BD%AE%E9%A1%B9%E5%8F%AF%E4%BB%A5%E4%BC%98%E5%8C%96%EF%BC%9F
怕丢失做cv拷贝整理
一、SQL语句优化的总体原则有哪些?
- 优化更需要优化的SQL
- 定位优化对象的性能瓶颈
- 明确的优化目标
- 从Explain执行计划入手
- 多使用profile
- 永远用小结果集驱动大结果集
- 尽可能在索引中完成排序
- 只取出自己需要的列
- 仅仅使用最有效的过滤条件
- 尽可能避免复杂的Join和子查询
二、如何理解MySQL中加锁原理?
mysql加锁机制 :
根据类型可分为共享锁(SHARED LOCK)和排他锁(EXCLUSIVE LOCK)或者叫读锁(READ LOCK)和写锁(WRITE LOCK)。
根据粒度划分又分表锁和行锁。表锁由数据库服务器实现,行锁由存储引擎实现。
三、MySQL死锁形成的原因是什么?
争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。
四、请阐述建立索引的原则有哪些?
1、定义主键的数据列一定要建立索引。
2、定义有外键的数据列一定要建立索引。
3、对于经常查询的数据列最好建立索引。
4、对于需要在指定范围内的快速或频繁查询的数据列。
5、经常用在WHERE子句中的数据列。
6、经常出现在关键字order by、group by、distinct后面的字段,建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,否则索引不会被使用。
7、对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。
五、mysql性能调优主要是针对执行计划中的哪些属性进行优化?
主要关注type列,key列,extra列
type列依次性能从好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL,除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。一般来说,好的sql查询至少达到range级别,最好能达到ref。
key列正常情况要是非NULL,如果是NULL,表示没有用索引,性能低下。
extra列主要关注是不是用了临时表排序,索引等等。例如:using temporary,using filesort等都是需要优化的。
8、对于定义为text、image和bit的数据类型的列不要建立索引。
9、对于经常存取的列避免建立索引。
10、限制表上的索引数目。对一个存在大量更新操作的表,所建索引的数目一般不要超过3个,最多不要超过5个。索引虽说提高了访问速度,但太多索引会影响数据的更新操作。
11、对复合索引,按照字段在查询条件中出现的频度建立索引。在复合索引中,记录首先按照第一个字段排序。对于在第一个字段上取值相同的记录,系统再按照第二个字段的取值排序,以此类推。因此只有复合索引的第一个字段出现在查询条件中,该索引才可能被使用,因此将应用频度高的字段,放置在复合索引的前面,会使系统最大可能地使用此索引,发挥索引的作用。
六、mysql中多表join的优化思路有哪些?
1、尽可能减少Join语句中的Nested Loop的循环总次数
如何减少Nested Loop的循环总次数?
最有效的办法只有一个,那就是让驱动表的结果集尽可能的小,永远用小结果集驱动大的结果集。为什么?因为驱动结果集越大,意味着需要循环的次数越多,也就是说在被驱动结果集上面所需要执行的查询检索次数会越多。比如,当两个表(表 A 和 表 B)Join的时候,如果表A通过WHERE条件过滤后有10条记录,而表B有20条记录。如果我们选择表A作为驱动表,也就是被驱动表的结果集为20,那么我们通过Join条件对被驱动表(表B)的比较过滤就会有10次。反之,如果我们选择表B作为驱动表,则需要有20次对表A的比较过滤。当然,此优化的前提条件是通过Join条件对各个表的每次访问的资源消耗差别不是太大。如果访问存在较大的差别的时候(一般都是因为索引的区别),我们就不能简单的通过结果集的大小来判断需要Join语句的驱动顺序,而是要通过比较循环次数和每次循环所需要的消耗的乘积的大小来得到如何驱动更优化。
2、优先优化Nested Loop的内层循环
这不仅仅是在数据库的Join中应该做的,实际上在我们优化程序语言的时候也有类似的优化原则。内层循环是循环中执行次数最多的,每次循环节约很小的资源,在整个循环中就能节约很大的资源。
3、保证Join语句中被驱动表上Join条件字段已经被索引
保证被驱动表上Join条件字段已经被索引的目的,正是针对上面两点的考虑,只有让被驱动表的Join条件字段被索引了,才能保证循环中每次查询都能够消耗较少的资源,这也正是优化内层循环的实际优化方法。
4、当无法保证被驱动表的Join条件字段被索引且内存资源充足的前提下,不要太吝惜Join Buffer的设置
当在某些特殊的环境中,我们的Join必须是All,Index,range或者是index_merge类型的时候, Join Buffer就会派上用场了。在这种情况下,Join Buffer的大小将对整个Join语句的消耗起到非常关键的作用。
七、请阐述order by语句的优化方案
利用索引实现数据排序的方法是MySQL中实现结果集排序的最佳做法。
因为这样可以完全避免因为排序计算所带来的资源消耗。所以,在我们优化sql语句中的ORDER BY的时候,尽可能利用已有的索引来避免实际的排序计算,可以很大幅度的提升ORDER BY操作的性能。在有些sql的优化过程中,即使为了避免实际的排序操作而调整索引字段的顺序,甚至是增加索引字段也是值得的。当然,在调整索 引之前,同时还需要评估调整该索引对其他sql所带来的影响,平衡整体得失。
八、group by语句实现的内部机制是什么?如何优化?
MySQL中,GROUP BY的实现有多种(三种)方式,其中有两种方式会利用现有的索引信息来完成GROUP BY,另外一种为完全无法使用索引的场景下使用。
1、用松散(Loose)索引扫描实现GROUP BY 当MySQL完全利用索引扫描来实现GROUP BY的时候,并不需要扫描所有满足条件的索引键即可完成操作得出结果
什么松散索引扫描的效率会很高? 因为在没有WHERE子句,也就是必须经过全索引扫描的时候,松散索引扫描需要读取的键值数量与分组的组数量一样多,也就是说比实际存在的键值数目要少很多。而在WHERE子句包含范围判断式或者等值表达式的时候,松散索引扫描查找满足范围条件的每个组的第1个关键字,并且再次读取尽可能最少数量的关键字。
2、用紧凑(Tight)索引扫描实现GROUP BY 紧凑索引扫描实现GROUP BY和松散索引扫描的区别主要在于他需要在扫描索引的时候,读取所有满足条件的索引键,然后再根据读取的数据来完成GROUP BY操作得到相应结果。
3、用临时表实现 GROUP BY 前面两种GROUP BY的实现方式都是在有可以利用的索引的时候使用的,当MySQL Query Optimizer无法找到合适的索引可以利用的时候,就不得不先读取需要的数据,然后通过临时表来完成GROUP BY操作。
九、索引的弊端有哪些?
针对增、删、改比较频繁的操作列上,索引会带来额外的开销(索引裂变重排等操作)。
假设我们在Table ta中的Column ca列创建了索引idx_ta_ca,那么任何更新Column ca的操作,MySQL都需要在更新表中Column ca的同时,也更新Column ca的索引数据,调整因为更新所带来键值变化后的索引信息。而如果我们没有对Column ca进行索引的话,MySQL所需要做的仅仅只是更新表中Column ca的信息。这样,所带来的最明显的资源消耗就是增加了更新所带来的IO量和调整索引所致的计算量。此外,Column ca的索引idx_ta_ca是需要占用存储空间的,而且随着Table ta数据量的增长,idx_ta_ca所占用的空间也会不断增长。所以索引还会带来存储空间资源消耗的增长。