mysql索引

mysql存储引擎

Myisam引擎(非聚集索引)
Innodb引擎(聚集索引)
索引失效的情况
mysql索引
MYSQL5.5之前默认的存储引擎就是MyISAM
MYSQL5.5之后默认的存储引擎就是InnoDB

Myisam引擎(非聚集索引)

若以这个引擎创建数据库表Create table test(……),它实际是生成三个文件:

test.myi 索引文件 test.myd数据文件 test.frm数据结构类型。
在这里插入图片描述
  通过show global variables like “%datadir%”命令可以找到你的数据库存放数据的目录
  在这里插入图片描述

如下图:当我们执行 select * from user where id = 1的时候,它的执行流程。

(1)查看该表的myi文件有没有以id为索引的索引树。

(2)根据这个id索引找到叶子节点的id值,从而得到它里面的数据地址。(叶子节点存的是索引和数据地址)。

(3)根据数据地址去myd文件里面找到对应的数据返回出来。
在这里插入图片描述

Innodb引擎(聚集索引)

若以这个引擎创建数据库表Create table user (……),它实际是生成两个文件:

user.ibd 索引文件 user.frm数据结构类型

因为innodb引擎创建表默认就是以主键为索引,所以不需要myi文件。

下图为innodb表的结构图:很显然它与myisam最大的区别是将整条数据存在叶子节点,而不是地址。(叶子节点存的是主键索引和数据信息)

若此时,你在其他列创建索引例如name,它就会另外创建一个以name为索引的索引树,(叶子节点存的是索引和主键索引)。

你在执行select * from user where name = ‘yongchen’,他的执行过程如下:

(1)找到name索引树

(2)根据name的值找到该树下叶子的name索引和主键值

(3)用主键值去主键索引树去叶子节点到该条数据信息
     Innodb引擎(聚集索引)
  若以这个引擎创建数据库表Create table user (……),它实际是生成两个文件:

user.ibd 索引文件 user.frm数据结构类型

因为innodb引擎创建表默认就是以主键为索引,所以不需要myi文件。

下图为innodb表的结构图:很显然它与myisam最大的区别是将整条数据存在叶子节点,而不是地址。(叶子节点存的是主键索引和数据信息)

若此时,你在其他列创建索引例如name,它就会另外创建一个以name为索引的索引树,(叶子节点存的是索引和主键索引)。

你在执行select * from user where name = ‘yongchen’,他的执行过程如下:

(1)找到name索引树

(2)根据name的值找到该树下叶子的name索引和主键值

(3)用主键值去主键索引树去叶子节点到该条数据信息
在这里插入图片描述
   
MyISAM引擎和InnoDB引擎的区别
  MyISAM:支持全文索引;不支持事务;会保存表的具体行数;它是表级锁;当对数据进行修改时会对整个表加锁,所以MyISAM对于写操作的并发性并不是很好.MyISAM用一个变量保存了整个表的行数,执行select count() from table时只需要读出该变量即可,速度很快。
  InnoDB:支持事务,对于InnoDB一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
InnoDB不保存表的具体行数,执行select count() from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
3:行级锁,在对数据库操作时,锁定的资源更少,最大程度支持并发。事务的隔离必须通过锁来实现。

索引失效的情况
索引列上不能使用表达式和函数
SELECT created ,title from tb_item WHERE TO_DAYS(CURRENT_DATE)-TO_DAYS(created)>=30

SELECT created ,title from tb_item WHERE created <DATE_ADD(CURRENT_DATE,INTERVAL -30 DAY);

索引列上不能进行算术运算
SELECT … FROM EMPLOYEE WHERE SAL * 12 > 25000;
SELECT … FROM EMPLOYEE WHERE SAL > 25000/12

避免在索引列上使用IS NULL和IS NOT NULL
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0
记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中。

应尽量避免在 where 子句中使用!=
MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN

应尽量避免在 where 子句中使用 or 来连接条件否则将导致引擎放弃使用索引而进行全表扫描
select id from t where num=10 or num=20
select id from t where num=10 union all select id from t where num=20

in 和 not in 也要慎用,否则会导致全表扫描,
select id from t where num in(1,2,3)
Select id from t where num between 1 and 3

在使用LIKE时,尽量不要在开头使用通配符。
SELECT id FROM t WHERE col LIKE ‘%ike’;
SELECT id FROM t WHERE col LIKE ‘Mich%’;

不要使用类型转换。如果某个索引列是int型,而在查询时,赋值为字符型,将使用不了索引。
SELECT * FROM mytbl WHERE num_col = 1;使用索引
SELECT * FROM mytbl WHERE num_col = ‘1’;没有使用索引

索引优化
1:一般在where子句、group by 子句、order by 子句、聚合函数(max,min)中加索引
2:对于多条件sql语句,离散度高的放在前面,离散度低的放后面
select count(DISTINCT user_id),count(DISTINCT vote_num)from vote_record_memory

select * from vote_record_memory where user_id=‘OomvgFnKrLmluexPpmoM’ and
vote_num=5474

3:多条件建立联合索引的时候,离散度高的放前面。
CREATE INDEX indexName ON tableName(column1,column2,…,columnN);

4:对于大文本如果需要建立索引可以考虑前缀索引
create index index_desc on tb_item_desc(item_desc(3))
如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值