首先抛出个问题,什么会引起sql慢、性能下降?
答:执行时间长、等待时间长会导致sql慢,具体来说:
1.查询语句写的烂
2.索引失效,而索引又分为
*单值索引:给表只给一个字段建立的索引; create index idx_user_name on user(name);
*复合索引:给表的多个字段联合在一起,建立的索引。 create index idx_user_nameEmail on user(name,email);
3.关联查询join太多了
4.服务器级别的参数调优
SQL执行顺序以及join
首先学习一下join的基本使用: https://blog.csdn.net/u012410733/article/details/63684663 这篇博客很有帮助
(这是人读的顺序)
然后知道机读是先From 表名 ,Select 放在order by之前(即处在倒数第二位)
存放在磁盘
索引是数据结构,一种排好序的、可以快速查找的数据结构。
MySQL使用InnoDB引擎时,支持的是B+树数据结构
使用索引的举例:
Col2是数据本身;
使用索引后,添加了Col1,Col1是指向数据本身的物理地址的指针。(即蓝色字说的“数据库还维护这一个满足特定查找算法的数据结构”)
以二叉树的形式存储这种带上了索引的新数据结构(真实情况是甚至是三叉数、四叉树等,这里二叉树只是举例,所以统称为B+树以后)
MySQLInnoDB支持B+树索引、全文索引、自适应哈希索引
优点:
通过索引检索,提高查找效率(即降低数据库IO成本);(一个节点对应一次IO,将磁盘文件加载到内存)
通过索引排序,降低排序成本(即降低CPU消耗)。
缺点:
索引本身占空间,一般放硬盘而非内存;
索引查找快,但是增、改、删慢,因为更新表时,不光保存数据还保存索引文件每次更新添加了索引列的字段;
单值索引:一个索引只能包含一个列,但一张表可以有多个单值索引;
复合索引:一个索引包含多个列
(聚集索引、辅助索引(次要索引)既可以是单值索引的形态,也可以是复合索引的形态)
MySQL中一定有主键索引(不指定的话会默认创建一个主键索引列),主键索引就是聚集索引
唯一索引:首先唯一索引是个索引,但是选列有讲究,必须是唯一的值,可以为NULL,但NULL只能有一个。(唯一索引可以用在单值索引上,也可以用在复合索引上)
创建:
如:CREATE INDEX idx_t1_col1Col2 ON t1(col2,col2);
或
AlTER TABLE tableName ADD INDEX indexName ON (colName);
如:ALTER TABLE t1 ADD INDEX idx_t1_col1Col2 ON (col1,col2);
(如果创建的是唯一索引,需要先给列设为主键:(错了吧,非主键列也可以作为唯一索引、一个表可以有多个唯一索引,主键一定是唯一索引,唯一索引不一定是主键)
主键不能为NULL(虽然主键列一定是可以为NULL的唯一索引列,这两者不矛盾)
)
这是棵B+数;
浅蓝色是磁盘块,深蓝色是数据项(所对应数据并不真实存在于页中),黄色是指针;
(B+树无论是聚集索引还是辅助索引,其非叶子节点都有索引列。
对于聚集索引,叶子节点存放了索引列及其完整数据
对于辅助索引,叶子节点存放了索引列及其对应的主键)
真实数据都在叶子结点;(B树的真实数据分布在整个树中)
树高即是查找时的最大IO数(这里规定只有根节点的树树高为1);(这也是为什么不用二叉树的原因,为了减少IO)
IO时会把对应磁盘块内容从磁盘加载到内存;
B+树是B树的变体,为了提高查询效果:
* b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
* b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢);
* 对于范围查找来说,b+树只需遍历叶子节点链表即可(因为B+树中的叶子结点通过链表是直接相连的),b树却需要重复地中序遍历
建表sql:
CREATE TABLE `student` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`tel` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) CHARSET=utf8;
并设tel为普通索引:
CREATE INDEX idx_student_tel ON student(tel);
1.我自己验证举出了例子
explain select * from student where `name` = 'zz';
这是因为name列既不是主键也不是索引,因此只能采用全表扫描来查找目标name。(即type=all)
2.我自己验证举出了例子
索引做扫描,是基于索引在索引的叶子节点上找满足条件的数据
index类型,需要扫描索引上的全部数据。
explain SELECT count(*) FROM student;
3.我自己验证举出了例子
前提:查找在一定范围内的数据,这个查询条件必须是建立了索引的!否则就是个最垃圾的ALL。
指的是有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。
除了显而易见的between,and以及'>','<'外,in和or也是索引范围扫描。
explain select * from student where tel<"123";
4.我自己验证举出了例子
前提:查找在一定范围内的数据,这个查询条件必须是建立了索引的!否则就是个最垃圾的ALL。
指的是有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。
除了显而易见的between,and以及'>','<'外,in和or也是索引范围扫描。
explain select * from student where tel<"123";
4.我自己验证举出了例子
查找条件列使用了索引但是不为主键和unique。其实,意思就是虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。
在employee表中根据tel查找数据的时候,mysql优化器便选择了ref的连接类型
mysql> explain select * from employee where `tel` = '123';
6.我自己验证举出了例子
通常情况下,如果将一个主键放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。
WHERE条件筛选后表上至多有一条元组匹配时,比如WHERE ID = 1 (ID是主键,值为1的要么有一条要么没有)
mysql> explain select * from employee where id = 1;
自己总结:
1.感觉Using index就是用到了索引,就会出现,即不会在数据的基础上查找,而是在索引的基础上查找,good(这个就叫索引覆盖??NO!索引覆盖是指MySQL可以利用索引返回字段,而不必根据索引再次读取数据文件,换句话说查询列被所建立的索引覆盖了,好像在讲possible_keys+key的时候举的那个例就和索引覆盖有关?Yes!因为你建的是col1_col2索引,刚好你要查的就是col1、col2字段);
2.如果出现Using where,表明索引在where条件中用到了;
3.没有出现说明只是为了获取查询结果,而用来读取数据。