Myisam引擎(非聚集索引)
Innodb引擎(聚集索引)
索引失效的情况
mysql索引
MYSQL5.5之前默认的存储引擎就是MyISAM
MYSQL5.5之后默认的存储引擎就是InnoDB
若以这个引擎创建数据库表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值,从而得到它里面的数据地址。(叶子节点存的是索引和数据地址)。
若以这个引擎创建数据库表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 索引列上不能进行算术运算 避免在索引列上使用IS NULL和IS NOT NULL 应尽量避免在 where 子句中使用!= 应尽量避免在 where 子句中使用 or 来连接条件否则将导致引擎放弃使用索引而进行全表扫描 in 和 not in 也要慎用,否则会导致全表扫描, 在使用LIKE时,尽量不要在开头使用通配符。 不要使用类型转换。如果某个索引列是int型,而在查询时,赋值为字符型,将使用不了索引。 索引优化 select * from vote_record_memory where user_id=‘OomvgFnKrLmluexPpmoM’ and 3:多条件建立联合索引的时候,离散度高的放前面。 4:对于大文本如果需要建立索引可以考虑前缀索引
SELECT … FROM EMPLOYEE WHERE SAL * 12 > 25000;
SELECT … FROM EMPLOYEE WHERE SAL > 25000/12
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0
记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中。
MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN
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
select id from t where num in(1,2,3)
Select id from t where num between 1 and 3
SELECT id FROM t WHERE col LIKE ‘%ike’;
SELECT id FROM t WHERE col LIKE ‘Mich%’;
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
vote_num=5474
CREATE INDEX indexName ON tableName(column1,column2,…,columnN);
create index index_desc on tb_item_desc(item_desc(3))
如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。