【索引】
概述:通过索引,高效对于mysql数据进行二叉树结构检索。扫描比全表扫描少,降低IO成本。
缺点:占用磁盘,空间换时间,降低更新表速度(update,insert,delete)。
结构{
B+树,范围匹配,所有存储引擎都支持。
hash,精确匹配,不支持范围,仅支持menmory引擎。
r-tree(仅支持misam)。
full-text(全文索引,倒排,仅支持misam-innodb)。
}
索引{
主键索引 primary:只能有一个,针对表中主键创建的索引。
唯一索引 unique:能有多个,避免表.列.值重复。
常规索引: 可有多个,用于快速定位特定数据。
全文索引 fulltext:可有多个,查找的是文本关键词。
单索引:一个索引只包含一个列。
联合多因:一个索引包含多个列。
}
索引存储形式划分:
默认主键索引是聚集索引,不存在主键将第一个唯一索引作为聚集索引,如果没有主键,自动生成rowid为聚集索引。
聚集索引:将数据存储与索引放到一起,索引结构的叶子节点保存行数据,有且只有一个,决定存储行数据所以必须有。查找时,找主键,返回即可,一次查询。
二级索引:将数据与索引分开存储,索引结构的叶子节点关联是对应的主键,可以存在多个。叶子节点挂的是主键id号(主键值)。查找时,先找到对应的主键,再根据主键去查询数据。两次查询。
#创建索引{
#普通索引
CREATE INDEX index_name ON table_name (column_name);
create index 索引名 on 表名(字段名);
#唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column_name);
create unique index 索引名 on 表名(字段名)
#复合索引(在一个表的多个列上创建索引):
CREATE INDEX index_name ON table_name (column1, column2);
create index 索引名 on 表名(字段名1,字段名2)
#全文索引(在支持全文索引的数据库系统中,如MySQL):
CREATE FULLTEXT INDEX index_name ON table_name (column_name);
create fulltext index 索引名 on 表名(字段名)
#联合索引(查询时满足有关联的两个字段存在联合索引关系)***
#检索时,是把phone和name作为一个建查询,属于二级索引。phone左,name右
create unique index idx_user_phone_name on tb_user(phone,name)
create 唯一 索引 索引名 在 user表里的phone和name创建为联合索引
}
sql性能分析工具{
索引是为了做性能优化产生的。主要是为了优化select语句。
sql执行频率:
增删改查那个用得频繁
命令查看--show global status like 'com_______'; #7个
慢查询日志:
定义--记录所有执行时间超过指定参数(long_query_time 单位秒。默认10秒)的所有sql语句日志,需要在/etc/my.cnf配置。
vim /etc/my.cnf
[mysqld]
slow_query_log = 1 #开
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2 #超过2秒记录
命令查看--show variables like 'slow_query_log';
默认路径--/var/lib/mysql/localhost-slow.log
日志解析:
#Time:时间
#user@host: root[root]@localhost [] id : 8
#query_time: 13.00执行时间 luck_time:0.00231锁行 rows_sent: 1返回记录 rows_examined:0
user itcast;#数据库
set timestamp=121341434; #操作时间
select count(*) from table; #执行的语句
proflie详情:
show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。
通过have profiling参数,能够看到当前MVSQL是否支持profile操作:
SELECT @@have _ profiling ; #0未开通
默认profiling是关闭的,可以通过set语句在session/global级别开启
profiling:SET profiling =1;
profile语法:
执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:
#查看每一条SQL的耗时基本情况
show profiles;
#查看指定query id的SQL语句各个阶段的耗时情况
show profile for 表名 字段;
#查看指定query id的SQL语句CPU的使用情况
show profile cpa for 表名 字段;
--------以上是从时间层面去判定,粗略判定
*explain执行计划
explain或desc命令获取mysql如何执行select语句信息,包括在select语句中执行如何连接和连接顺序
语法:explain select 字段列表 from 表名 where 条件 #直接在select前加
}
使用规则{
索引使用
#索引性能
explain select id,name,age,status from student where name='xxx' and age=21 and status=0;
Extra
using where;using in #性能高,说明需要的数据都在索引列中,不需要回表查询数据
using index condition #性能低,需要回表查询,和二级索引一样查询过程,先拿到id主键,再根据id主键查询二级数据
}
索引失效情况{
#不能在索引列上运算操作,否则索引失效
explain select * from students where substring(phont,12,2)='12'
#需要加上引号,否则会是全表检索
explain select * from students where phone = 1111; #type=all说明全表检索,type=ref说明有最左索引检索,range数值索引
#尾部模糊匹配 like X% ,索引不会失效,头部模糊匹配索引失效
#or连接, id主键索引,name没有索引,索引也不会生效
where id=sxxx or name='11';
#数据分布影响
索引比全表扫描慢,那么索引检索不会生效。检索的数据达到全表50%就不生效了
}
sql提示{
#符合最左前缀法则
explain select *from student profession='工程造价';
#索引名字
use index: #建议mysql使用单列索引
explain select * from tb_user use index(idx_user_pro) where profession ='软件工程';
ignore index: #不要用的索引
explain select * from tb_user ignore index(idx_user_pro) where profession ='软件工程';
force index: #强制使用
explain select * from tb_user force index(idx_user_pro) where profession ='软件工程';
覆盖索引:是辅助索引,检索name也不需要回表,直接返回。
二级索引:根据键值先去检索id主键,然后回表查询id行的name,创建联合索引可以避免这种情况
==============================================================
sql语句优化思考题:
如何优化一下语句?使用联合索引.让其不需要回表查询,直接覆盖索引,性能最佳.
select id,username,password,status from student where username='itcast';
前缀索引-大文本字符串:
数据类型为varchant,txt时,字符串长,索引会变大,查询时浪费大量io,影响查询效率.
可以将字符串一部分前缀(5个)建立索引,大大节约索引空间,提升效率。
#使用场景:大文本字符串
#语法
create index idx_xxx on table_name(cloumn(5))
create index idx_email_5 on student(email(5))
#查询流程
设计原则:最左前缀法则,最左的列必须存在。
联合索引:会丢失最右列,在数值范围匹配的时候尽量使用>=或<=
索引失效:函数运算,字符加引号,like模糊匹配在前加%号,or链接一侧有索引一侧没有,评估全表扫描比走索引快。