关于mysql的学习有很多
好文章就是要分享,详情参考链接:https://www.cnblogs.com/msjhw/p/15816582.html
扩展问题
是很全的面试链接:
https://blog.csdn.net/liu_weiliang10405/article/details/123930244
针对sql优化类的,细节记录
索引失效的注意点:
不在索引上做任何操作(计算,函数,类型转换)。会导致索引失效
组合索引中,如果中间某字段使用了范围条件,则右边索引失效
减少select*
使用!= 或者<> ,is null,is not null无法使用索引
like通配符必须放在所以右边,否则索引失效
少用or, 会使索引失效
慢查询使用排查记录:
1. show variables like 'slow_query_log';
默认是关闭的,开启慢查询日志
2. set global slow_query_log=on;
3. 查看慢查询阈值(超过这个时间sql就会被记录在慢查询日志中)这个阈值默认是10s
4. show variables like 'long_query_time';
5. 更改一下阈值 set long_query_time=0.3;
更改完记得查询确认一下,执行第4操作语句
6. 查看慢查询日志的位置
show variables like 'slow_query_log_file';
7.测试慢查询sql
select * from family_member;
select uuid from family_member where name = '555';
8. 查询慢SQL的日志
cat vvv.log文件
慢查询日志分析mysqldumpslow工具
sql mysqldumpslow -s t -t 10 -g 'select' ./slow.log;
总结
mysql判断sql语句是不是慢查询,是根据语句的执行时间来衡量的,mysql会用语句的执行时间和long_query_time这个系统参数做比较,如果语句执行时间大于long_query_time,都会把这个语句记录到慢查询日志里面。long_query_time的默认值是10s,一般生产环境不会设置这么大的值,一般设置1秒。
原文链接: https://blog.csdn.net/qq_48508278/article/details/127043949
--查询耗时最多的10条数据:
Count:代表这个 SQL 语句执行了多少次
Time:代表执行的时间,括号是累计时间
Lock:表示锁定的时间,括号是累计时间
Rows:表示返回的记录数,括号是累计记录数
找到慢查询的SQL以后,用explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看。
主要看type那列,ALL标识全文检索,所以这条sql查询很慢。
解决:最简单有效的方法就是:加索引。
alter table xxx(表名) add index nameIndex (name);
删除索引:
drop index nameIndex on xxx(表名);
看出type是ref,已经不是全盘扫描了。
过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。
explain函数介绍
explain显示了MySQL如何使用索引来处理select语句以及连接表。他可以帮助选择更好的索引和写出更优化的查询语句
explain显示了很多列,各个关键字的含义如下:
table:顾名思义,显示这一行的数据是关于哪张表的;
type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为:const、eq_reg、ref、range、indexhe和ALL;
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从where语句中选择一个合适的语句;
key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MySQL会选择优化不足的索引。这种情况下,可以在Select语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MySQL忽略索引;
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好;
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数;
rows:MySQL认为必须检查的用来返回请求数据的行数;
Extra:关于MySQL如何解析查询的额外信息。
EXPLAIN原文链接:https://blog.csdn.net/u011298909/article/details/120567849
扩展:mysql索引底层实现 B+tree
二叉树
每个节点最多有两个子树,所以二叉树不存在度大于2的节点(结点的度:结点拥有的 子树的数目。),可以没有子树或者一个子树。
左子树和右子树有顺序,次序不能任意颠倒
二叉书并不适合去做索引,遇到这种极端情况,就会导致有索引和无索引效果一样
平衡二叉树(AVL树)
由于旋转的耗时,AVL树在删除数据时效率很低。不广泛
红黑树
红黑树并不追求严格的平衡,而是大致的平衡:只是确保从根到叶子的最长的可能路径不多于最短的可能路径的两倍长 ,红黑树的缺点就是太高了。
B-tree Tree就是我们常说的B树,
它是一种多路搜索树而非二叉树,使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度.
B树是二叉排序树的扩展,二叉排序树是二路查找,B-树是多路查找。因为B-树节点内的关键字是有序的,在节点内查找的时候除了顺序查找之外,还可以用折半查找提高效率,B-树的具体查找步骤可以参照折半查找方法。
B+Tree(B-Tree变种)
B+树是一种树数据结构,通常用于数据库和操作系统的文件系统中。B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+树元素自底向上插入,这与二叉树恰好相反。
非叶子节点不存储data,只存储索引(冗余),可以放更多的索引,只有叶子节点才存储数据
叶子节点包含所有索引字段
叶子节点增加了一个指向相邻子节点的指针,它的最后一个数据会指向下一个叶子节点的第一个数据,形成一个有序链表的结构,提高区间访问的性能
为什么说B+树比B树更适合实际应用中作为操作系统的文件索引和数据库索引?
(1)B+树的磁盘读写代价更低
非叶子节点包含的信息更少,如果把同一节点的所有信息放在一个磁盘块中,则可以比B树放入更多的关键码。一次读入内存当中(读一个块)就能读入更多的关键码,所以降低了磁盘I/O总数。
(2)查询效率更加稳定
对任何关键字的查找都必须从根节点走到叶子节点,路径长度相同,所以对每条数据的查询效率相当,在存储相等的关键字上,B+树树的高度会更低。
(3)B树在提高磁盘I/O性能的同时并没有解决元素遍历效率低下的问题。而B+树因为叶子节点有链指针存在,所以遍历叶子节点即可以实现对整棵树的遍历。而在数据库中基于范围的查询是非常频繁的,B+树就能更好的支持。
InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。在5.5版本之后,MYSQL的默认引擎变成了InnoDB
mysql索引创建:
SELECT * FROM table WHERE a = 1 and b = 2 and c = 3;
此题正确答法是,(a,b,c)或者(c,b,a)或者(b,a,c)都可以,重点要的是将区分度高的字段放在前面,区分度低的字段放后面。像性别、状态这种字段区分度就很低,我们一般放后面
例如假设区分度由大到小为b,a,c。那么我们就对(b,a,c)建立索引。在执行sql的时候,优化器会 帮我们调整where后a,b,c的顺序,让我们用上索引。
SELECT * FROM table WHERE a > 1 and b = 2;
正确答法是,对(b,a)建立索引。如果你建立的是(a,b)索引,那么只有a字段能用得上索引,毕竟最左匹配原则遇到范围查询就中止匹配。如果对(b,a)建立索引那么两个字段都能用上,优化器会帮我们调整where后a,b的顺序,
SELECT * FROM table WHERE a > 1 and b = 2 and c > 3;
回答也是不一定,(b,a)或者(b,c)都可以,要结合具体情况具体分析。
SELECT * FROM table WHERE a = 1 and b = 2 and c > 3;
正确答法是,对(a,b,c)建立索引
SELECT * FROM table WHERE a = 1 ORDER BY b;
正解,对(a)建立索引,因为a的值是一个范围,这个范围内b值是无序的,没有必要对(a,b)建立索引。
SELECT * FROM table WHERE a IN (1,2,3) and b > 1;
正解,还是对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!
order by索引问题
select order_no from order where status =1 order by create_time desc
如果有 order by 的场景,请注意利用索引的有序性。 order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
正例: where a=? and b=? order by c; 索引: a_b_c
反例: 索引如果存在范围查询, 那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无 法排序
联表查询
inner left right 三种连接如果结果相同,优先使用inner join,如果使用left join左边表尽量小。
inner join 内连接,只保留两张表中完全匹配的结果集;
left join会返回左表所有的行,即使在右表中没有匹配的记录;
right join会返回右表所有的行,即使在左表中没有匹配的记录
#默认内连接
SELECT
product.id,
product.name,
image.url
FROM
product,
image
WHERE
product.img_id = image.id