MySQL学习(索引、引擎、优化)

标签: mysql 学习 索引 | 发表时间:2015-11-08 20:28 | 作者:doudou_001
出处:http://www.iteye.com
索引对于查询的速度至关重要,理解索引也是数据库调优的起点。

1. 建立索引前,先设计好建立索引列的数据类型。
1)越小的数据类型性能越好:因为越小的数据类型对于硬盘读取、内存、CPU缓存都需要更少的空间,处理起来更快。
2)简单的数据类型更好:整型比字符型更好。
3)尽量避免使用NULL: 建立索引的列最好是Not Null约束的,如果一定要用NULL,可以用0或者某特殊值替代。因为在MySQL中,对于NULL的值很难进行查询优化,因为他们使得索引的计算更加复杂。

2. 索引概述:
对于任何关系型数据库,索引都是进行优化的最主要因素。对于少量的数据,不必使用索引。
如果对于多列进行索引(组合索引),列的顺序非常中意。MySQL仅对索引最左边的前缀进行有效的查找。
例如:存在组合索引(c1, c2), 查询语句select * from t1 where c1=1 and c2=2能够使用该索引。select * from t1 where c1=1也能够使用该索引。但select * from t1 where c2=2不能使用该索引。
理由是,没有组合索引的引导列,即,要想使用c2列进行索引,必须出现c1等于某值。

2.1 索引的类型
索引与引擎的关系:
索引是在存储引擎中实现的,而不是在服务器层中实现的。所以每种存储引擎的索引都不一定相同,并不是所有的存储引擎都支持所有的索引类型。

2.1.1 B-Tree索引
假如有一个表:
create table people (
last_name varchar(50) not null,
first_name varchar(50) not null,
dob date not null,
gender enum('m', 'f') not null,
key(last_name, first_name, dob)
);
其索引包含了表中每一行的last_name, first_name, dob列。

索引存储的值按照索引列中的顺序排序(先last_name, 在first_name, 再dob). 可以用B-Tree索引进行全关键字、关键字范围、关键字前缀进行查询。
所以可以对如下情形生效:
1)匹配全值(Match the full value): 对索引中所有列都指定具体的值。例如查找出1960-01-01出生的Cuba Allen.
2)匹配最左前缀(Match a leftmost prefix): 可以利用索引查找last_name为Allen的人。
3)匹配列前缀(Match a column prefix): 可以列用索引查找last_name为J开头的人,仅仅使用索引中的第一列。
4)匹配值的范围查询(Match a range of values): 可以利用索引查找last_name在Allen和Barrymore之间的人,仅仅使用索引中的第一列。
5)匹配部分精确而其他部分进行范围匹配(Match one part exactly and match a range on another part): 可以利用索引查找last_name为Allen, 而first_name为K开头的人。

因为B-Tree中的节点都是顺序存储的,所以可以利用索引进行查找(找到某值),也可以对查询结果order by.

使用B-Tree索引有下面的限制:
1)查询必须从索引的最左边的列开始
2)不能跳过某一列索引:即不能利用索引查询last_name为Allen, 且1980-01-01出生的人。必须先查first_name后再查dob.
3)存储引擎不能使用索引中范围条件右边的列。例如:where last_name='Smith' and first_name like 'J%' and dob='1976-01-02', 则索引只对last_name和first_name有效,因为like是范围查询。

2.1.2 Hash索引
MySQL中,只有Memory存储引擎支持hash索引,是Memory引擎默认的索引类型。尽管Memory表也可以使用B-Tree索引。

3. 高性能的索引策略
3.1 聚簇索引(Clustered Indexes) -- 在MySQL的InnoDB引擎中,主键索引就是聚簇索引。
聚簇索引保证关键字的值相近的元组存储的物理位置也相同(所以字符串类型不适合创建索引,特别是随机字符串,会使得系统进行大量的移动操作),且一个表只能有一个聚簇索引。
目前,支持聚簇索引的引擎只有InnoDB和solidDB.

3.1.1 聚簇索引和非聚簇索引的区别:InnoDB引擎支持聚簇索引,而MyISAM不支持聚簇索引。
例如:
create table layout_test (
col1 int NOT NULL,
col2 int NOT NULL,
primary key(col1),
key(col2)
);
假设主键位于1--10000之间,且按随机顺序插入,然后由optimize table进行优化。col2随机赋予1--100之间的值,所以会存在许多重复的值。
1)MyISAM的布局:
MyISAM按照插入的顺序在磁盘上存储数据。
注:MyISAM不支持聚簇索引,索引中每一个叶子节点仅仅包含行号(row number), 且叶子节点按照col1的顺序存储。
2)InnoDB的布局:
InnoDB按聚簇索引的形式存储数据。
注:聚簇索引总每个叶子节点包含primary key的值,事务ID和回滚指针(rollback pointer).

3.2 覆盖索引(Covering Indexes)
如果索引包含满足查询的所有数据,就成为覆盖索引。
覆盖所有有如下好处:
1)索引项通常比记录要小,所以MySQL访问更好的数据。
2)索引都按值的大小顺序存储,相对于随机访问记录,需要更少的IO.
3)大多数数据引擎更好的缓存了索引。比如MySQL只缓存索引。
4)覆盖索引对于InnoDB表尤其有用,因为InnoDB使用聚簇索引组织数据,如果二级索引中包含所需的数据,就不需要在索引中查找了。

3.3 利用索引进行排序
MySQL中,有两种方式生成有序的结果集:一是使用filesort, 二是按索引顺序扫描。
利用索引进行排序非常快,且可以利用同一索引同时进行查找和排序操作。
当索引的顺序与order by的列顺序相同时,且所有的列是同一方向(全部升序或者全部降序)时,可以用索引排序。
如果查询时多表连接,仅当order by中所有的列都是第一个表的列时,索引才会生效。其他情况都会使用filesort.

例如:
create table actor (
actor_id int unsigned not null auto_increment,
name varchar(16) not null default,
password varchar(16) not null default,
primary key(actor_id),
key(name)
) engine=InnoDB
insert into actor(name,password) values('cat01','1234567');
insert into actor(name,password) values('cat02','1234567');
insert into actor(name,password) values('ddddd','1234567');
insert into actor(name,password) values('aaaaa','1234567');

mysql>explain select actor_id from actor order by actor_id;
结果:
id:1
select_type:SIMPLE
table:actor
type:index
possible_keys:NULL
key:PRIMARY
ref:NULL
rows:4
Extra:Using index
1 row in set(0.00 sec)

mysql>explain select actor_id from actor order by password;
结果:
id:1
select_type:SIMPLE
table:actor
type:index
possible_keys:NULL
key:NULL
key_len:NULL
ref:NULL
rows:4
Extra:Unsing filesort
1 row in set(0.00 sec)

mysql>explain select actor_id from actor order by name;
结果:
id:1
select_type:SIMPLE
table:actor
type:index
possible_key:NULL
key:name
key_len:18
ref:NULL
rows:4
Extra:Using index

当MySQL不能使用索引进行排序时,就会利用自己的排序算法(快速排序算法)在内存(sort buffer)中对数据进行排序。如果内存装载不下,它会将磁盘上的数据进行分块,再对各个数据块进行排序,然后将各个数据库合并成有序的结果集。

3.4 索引与加锁
索引对于InnoDB非常重要,因为它可以让查询锁定更少的元组。因为InnoDB直到事务提交时才会解锁。有两个原因:
1. 即使InnoDB行级锁非常高效,内存开销非常小,但还是存在开销。
2. 对不需要的元组加锁,会增加锁的开销,降低并发性能。
InnoDB仅对需要访问的元组加锁,而索引能够减少InnoDB访问的元组数。

===========================
MyISAM和InnoDB的区别:
1. 事务处理:MyISAM不支持,InnoDB支持
2. 性能:MyISAM好于InnoDB
3. fulltext索引:MyISAM支持,InnoDB不支持
4. select count(*) from table1; MyISAM效率好:MyISAM仅读出保存好的行数,而InnoDB要扫描一遍整个表。
5. auto_increment: MyISAM可以用该列与其他列一起建立联合索引,而InnoDB只支持包含只有该字段的索引。
6. delect from table; InnoDB会一行一行删除,不会重新建立表。

综上,MyISAM和InnoDB的主要区别是,InnoDB支持事务处理和行级锁。而MyISAM不支持,所以MyISAM往往被认为只适合在小项目中应用。
MyISAM的好处:
1. 对于读多写少的情形,MyISAM的性能比InnoDB好很多。
2. MyISAM的索引和数据是分开的,并且索引是有压缩的,这样内存使用率就提高了不少。而InnoDB的索引和数据是紧密捆绑的,并没有使用压缩,从而会造成InnoDB的体积更庞大。

一般来说,MyISAM适合:
1. 做很多count计算
2. 插入不频繁,查询非常频繁
3. 没有事务

InnoDB适合于:
1. 可靠性要求比较高,或者要求事务
2. 表更新和查询都非常的频繁,并且表锁定的机会比较大。

============================

MySQL的explain

explain的作用是显示了MySQL如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法:在select语句前加上explain就可以了。

例如:explain select surname, first_name from a, b where a.id=b.id

分析结果形式如下:
table | type | possible_keys | key | key_len | ref | rows | extra

分别解释如下:
1. table:显示这一行的数据是关于哪张表的
*2. type:显示连接使用了哪种类型。最好到最差的连接类型为:const, eq_reg, ref, range, index, ALL
3. possible_key: 显示可以应用在这张表上的索引。
*4. key: 实际使用的索引。如果为NULL, 则没有使用索引。
5. key_len: 索引的长度
6. ref: 显示索引的哪一列被使用了。
7. rows: MySQL认为必须检查的用来返回请求数据的行数。
*8. extra: 额外信息:
1)distinct: 一旦找到与行相匹配的行,就不再搜索了。
2)not exist: MySQL优化了左连接,一旦它找到了匹配left join标准的行,就不再搜索了。
3)using filesort: 指Mysql将用外部排序而不是按照index顺序排列结果。数据较少时从内存排序,否则从磁盘排序。Explain不会显示的告诉客户端用哪种排序。
4)using index: 表示Mysql使用覆盖索引避免全表扫描,不需要再到表中进行二次查找数据。


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [mysql 学习 索引] 推荐:

MySQL学习(索引、引擎、优化)

- - 数据库 - ITeye博客
索引对于查询的速度至关重要,理解索引也是数据库调优的起点. 建立索引前,先设计好建立索引列的数据类型. 1)越小的数据类型性能越好:因为越小的数据类型对于硬盘读取、内存、CPU缓存都需要更少的空间,处理起来更快. 2)简单的数据类型更好:整型比字符型更好. 3)尽量避免使用NULL: 建立索引的列最好是Not Null约束的,如果一定要用NULL,可以用0或者某特殊值替代.

ElasticSearch 索引 VS MySQL 索引

- - crossoverJie's Blog
这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的. 这甚至比在我本地使用 MySQL 通过主键的查询速度还快. 这类问题网上很多答案,大概意思呢如下:. Lucene 的全文检索引擎,它会对数据进行分词后保存索引,擅长管理大量的索引数据,相对于.

[MySQL] B+树索引

- - CSDN博客推荐文章
B+树是一种经典的数据结构,由平衡树和二叉查找树结合产生,它是为磁盘或其它直接存取辅助设备而设计的一种平衡查找树,在B+树中,所有的记录节点都是按键值大小顺序存放在同一层的叶节点中,叶节点间用指针相连,构成双向循环链表,非叶节点(根节点、枝节点)只存放键值,不存放实际数据. 保持树平衡主要是为了提高查询性能,但为了维护树的平衡,成本也是巨大的,当有数据插入或删除时,需采用拆分节点、左旋、右旋等方法.

mysql 索引技巧

- - 小彰
MySQL索引的建立对于MySQL的高效运行是很重要的. 下面介绍几种常见的MySQL索引类型. 在数据库表中,对字段建立索引可以大大提高查询速度. 假如我们创建了一个 mytable表:. CREATE TABLE mytable(   ID INT NOT NULL,    username VARCHAR(16) NOT NULL  );   我们随机向里面插入了10000条记录,其中有一条:5555, admin.

mysql选择索引

- - CSDN博客数据库推荐文章
1、尽量为用来搜索、分类或分组的数据列编制索引,不要为作为输出显示的数据列编制索引. 最适合有索引的数据列是那些在where子句中数据列,在联结子句中出现的数据列,或者是在Group by 、Order by子句中出现的数据列. select 后的数据列最好不要用索引. 2、综合考虑各数据列的维度.

mysql 索引详解

- - 行业应用 - ITeye博客
本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题. 特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等. 为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论.

mysql索引认识

- - 数据库 - ITeye博客
数据在磁盘中是以 “块”的形式存储的,所以一张表涉及的数据可能会存在多个块中,而在磁盘中查询数据则会根据字段是否为有序与无序来区分,. 无序情况:1.数值具有唯一性则需要查找 总块数/2.                   2.无序+无唯一性则需要查找  总块数. 有序情况:1.数值唯一性:log2(总块数/2)   (log2是二分查找算法).

MySQL 索引方式

- - zzm
本文配图来自《高性能MySQL(第二版)》. 在数据库中,对性能影响最大的几个策略包括数据库的锁策略、缓存策略、索引策略、存储策略、执行计划优化策略. 索引策略决定数据库快速定位数据的效率,存储策略决定数据持久化的效率. MySQL中两大主要存储引擎MyISAM和InnoDB采用了不同的索引和存储策略,本文将分析它们的异同和性能.

MySql索引总结

- - 掘金后端
MySQL 索引底层数据结构.   Mysql索引使用的数据结构主要有 BTree索引 和 Hash索引. 对于Hash索引来说,底层数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,使用Hash索引查询性能最快. 其余大多数场景建议使用BTree索引. 为什么索引能够提高查询速度.

Mysql-innodb-B+索引

- - 掘金后端
这是读书笔记,Mysql,innodb系列一共3篇. Mysql-innodb-B+索引(本篇). Mysql-innodb-锁(预计20200523). Mysql-innodb-事务预计20200530). CREATE TABLE `aid_***_detail` ( //省略所有字段 PRIMARY KEY (`id`), KEY `range_idx` (`range_id`,`is_delete`,`range_detail_num`,`goods_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4复制代码.