序⾔
之前写到MySQL对表的增删改查(查询最为重要)后,就感觉MySQL就差不多学完了,没有想继续学下去的⼼态了,原因可能是由于别⼈的影响,觉得对于MySQL来说,知道了⼀些复杂的查询,就够了,但是我认为,不管有没有⽤,现在学着不懂的东西,说明就是⾃⼰薄弱的地⽅,多学才能⽐别⼈更强
--WZY
⼀、什么是索引?为什么要建⽴索引?
索引⽤于快速找出在某个列中有⼀特定值的⾏,不使⽤索引,MySQL必须从第⼀条记录开始读完整个表,直到找出相关的⾏,表越⼤,查询数据所花费的时间就越多,如果表中查询的列有⼀个索引,MySQL能够快速到达⼀个位置去搜索数据⽂件,⽽不必查看所有数据,那么将会节省很⼤⼀部分时间。
例如:有⼀张person表,其中有2W条记录,记录着2W个⼈的信息。有⼀个Phone的字段记录每个⼈的电话号码,现在想要查询出电话号码为xxxx的⼈的信息。
如果没有索引,那么将从表中第⼀条记录⼀条条往下遍历,直到找到该条信息为⽌。
如果有了索引,那么会将该Phone字段,通过⼀定的⽅法进⾏存储,好让查询该字段上的信息时,能够快速找到对应的数据,⽽不必在遍历2W条数据了。其中MySQL中的索引的存储类型有两种:BTREE、HASH。 也就是⽤树或者Hash值来存储该字段,要知道其中详细是如何查找的,就需要会算法的知识了。我们现在只需要知道索引的作⽤,功能是什么就⾏。
⼆、MySQL中索引的优点和缺点和使⽤原则
优点:
2、所有的MySql列类型(字段类型)都可以被索引,也就是可以给任意字段设置索引 3、⼤⼤加快数据的查询速度 缺点:
1、创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
2、索引也需要占空间,我们知道数据表中的数据也会有最⼤上线设置的,如果我们有⼤量的索引,索引⽂件可能会⽐数据⽂件更快达到上线值
3、当对表中的数据进⾏增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度。 使⽤原则:
通过上⾯说的优点和缺点,我们应该可以知道,并不是每个字段度设置索引就好,也不是索引越多越好,⽽是需要⾃⼰合理的使⽤。
1、对经常更新的表就避免对其进⾏过多的索引,对经常⽤于查询的字段应该创建索引,
2、数据量⼩的表最好不要使⽤索引,因为由于数据较少,可能查询全部数据花费的时间⽐遍历索引的时间还要短,索引就可能不会产⽣优化效果。
3、在⼀同值少的列上(字段上)不要建⽴索引,⽐如在学⽣表的\"性别\"字段上只有男,⼥两个不同值。相反的,在⼀个字段上不同值较多可是建⽴索引。
上⾯说的只是很⽚⾯的⼀些东西,索引肯定还有很多别的优点或者缺点,还有使⽤原则,先基本上理解索引,然后等以后真正⽤到了,就会慢慢知道别的作⽤。注意,学习这张,很重要的⼀点就是必须先得知道索引是什么,索引是⼲嘛的,有什么作⽤,为什么要索引等等,如果不知道,就重复往上⾯看看写的⽂字,好好理解⼀下。⼀个表中很够创建多个索引,这些索引度会被存放到⼀个索引⽂件中(专门存放索引的地⽅)
三、索引的分类
注意:索引是在存储引擎中实现的,也就是说不同的存储引擎,会使⽤不同的索引
MyISAM和InnoDB存储引擎:只⽀持BTREE索引, 也就是说默认使⽤BTREE,不能够更换 MEMORY/HEAP存储引擎:⽀持HASH和BTREE索引
1、索引我们分为四类来讲 单列索引(普通索引,唯⼀索引,主键索引)、组合索引、全⽂索引、空间索引、 1.1、单列索引:⼀个索引只包含单个列,但⼀个表中可以有多个单列索引。 这⾥不要搞混淆了。 1.1.1、普通索引:
MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插⼊重复值和空值,纯粹为了查询数据更快⼀点。
1.1.2、唯⼀索引:
索引列中的值必须是唯⼀的,但是允许为空值, 1.1.3、主键索引:
是⼀种特殊的唯⼀索引,不允许有空值。 1.2、组合索引
在表中的多个字段组合上创建的索引,只有在查询条件中使⽤了这些字段的左边字段时,索引才会被使⽤,使⽤组合索引时遵循最左前缀集合。这个如果还不明⽩,等后⾯举例讲解时在细说 1.3、全⽂索引
全⽂索引,只有在MyISAM引擎上才能使⽤,只能在CHAR,VARCHAR,TEXT类型字段上使⽤全⽂索引,介绍了要求,说说什么是全⽂索引,就是在⼀堆⽂字中,通过其中的某个关键字等,就能找到该字段所属的记录⾏,⽐如有\"你是个⼤煞笔,⼆货 ...\" 通过⼤煞笔,可能就可以找到该条记录。这⾥说的是可能,因为全⽂索引的使⽤涉及了很多细节,我们只需要知道这个⼤概意思,如果感兴趣进⼀步深⼊使⽤它,那么看下⾯测试该索引时,会给出⼀个博⽂,供⼤家参考。 1.4、空间索引
空间索引是对空间数据类型的字段建⽴的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。
在创建空间索引时,使⽤SPATIAL关键字。
要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。具体细节看下⾯
四、索引操作(创建和删除)
4.1、创建索引
4.1.1、创建表的时候创建索引
格式:CREATE TABLE 表名[字段名 数据类型] [UNIQUE|FULLTEXT|SPATIAL|...] [INDEX|KEY] [索引名字] (字段名[length]) [ASC|DESC]
|--------------------------------------| |-----------------------------------| |------------| |---------| |---------------| |------------| 普通创建表语句 设置什么样的索引(唯⼀、全⽂等) 索引关键字 索引名字 对哪个字段设置索引 对索引进⾏排序
4.1.1.1、创建普通索引
CREATE TABLE book CREATE TABLE book ( (
bookid INT NOT NULL, bookid INT NOT NULL, bookname VARCHAR(255) NOT NULL, bookname VARCHAR(255) NOTNULL,
authors VARCHAR(255) NOT NULL, authors VARCHAR(255) NOT
NULL,
info VARCHAR(255) NULL, info VARCHAR(255) NULL, comment VARCHAR(255) NULL, comment VARCHAR(255) NULL,
year_publication YEAR NOT NULL, year_publication YEAR NOTNULL,
INDEX(year_publication) KEY(year_publication) ); );
上⾯两种⽅式创建度可以,通过这个例⼦可以对⽐⼀下格式,就差不多明⽩格式是什么意思了。
通过打印结果,我们在创建索引时没写索引名的话,会⾃动帮我们⽤字段名当作索引名。 测试:看是否使⽤了索引进⾏查询。
EXPLAIN SELECT * FROM book WHERE year_publication = 1990\\G;
解释:虽然表中没数据,但是有EXPLAIN关键字,⽤来查看索引是否正在被使⽤,并且输出其使⽤的索引的信息。
id: SELECT识别符。这是SELECT的查询序列号,也就是⼀条语句中,该select是第⼏次出现。在次语句中,select就只有⼀个,所以是1.
select_type:所使⽤的SELECT查询类型,SIMPLE表⽰为简单的SELECT,不实⽤UNION或⼦查询,就为简单的SELECT。也就是说在该SELECT查询时会使⽤索引。其他取值,PRIMARY:最外⾯的SELECT.在拥有⼦查询时,就会出现两个以上的SELECT。UNION:union(两张表连接)中的第⼆个或后⾯的select语句 SUBQUERY:在⼦查询中,第⼆SELECT。 table:数据表的名字。他们按被读取的先后顺序排列,这⾥因为只查询⼀张表,所以只显⽰book
type:指定本数据表和其他数据表之间的关联关系,该表中所有符合检索值的记录都会被取出来和从上⼀个表中取出来的记录作联合。ref⽤于连接程序使⽤键的最左前缀或者是该键不是 primary key 或 unique索引(换句话说,就是连接程序⽆法根据键值只取得⼀条记录)的情况。当根据键值只查询到少数⼏条匹配的记录时,这就是⼀个不错的连接类型。(注意,个⼈这⾥不是很理解,百度了很多资料,全是⼤⽩话,等以后⽤到了这类信息时,在回过头来补充,这⾥不懂对后⾯的影响不⼤。)可能的取值有system、const、eq_ref、index和All
possible_keys:MySQL在搜索数据记录时可以选⽤的各个索引,该表中就只有⼀个索引,year_publication
key:实际选⽤的索引
key_len:显⽰了mysql使⽤索引的长度(也就是使⽤的索引个数),当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使⽤了哪些索引。这⾥就使⽤了1个索引,所以为1, ref:给出关联关系中另⼀个数据表中数据列的名字。常量(const),这⾥使⽤的是1990,就是常量。
rows:MySQL在执⾏这个查询时预计会从这个数据表⾥读出的数据⾏的个数。 extra:提供了与关联操作有关的信息,没有则什么都不写。
上⾯的⼀⼤堆东西能看懂多少看多少,我们最主要的是看possible_keys和key 这两个属性,上⾯显⽰了key为year_publication。说明使⽤了索引。
4.1.1.2、创建唯⼀索引 CREATE TABLE t1 (
id INT NOT NULL,
name CHAR(30) NOT NULL, UNIQUE INDEX UniqIdx(id) );
解释:对id字段使⽤了索引,并且索引名字为UniqIdx。 SHOW CREATE TABLE t1\\G;
要查看其中查询时使⽤的索引,必须先往表中插⼊数据,然后在查询数据,不然查找⼀个没有的id值,是不会使⽤索引的。
INSERT INTO t1 VALUES(1,'xxx');
EXPLAIN SELECT * FROM t1 WHERE id = 1\\G;
可以看到,通过id查询时,会使⽤唯⼀索引。并且还实验了查询⼀个没有的id值,则不会使⽤索引,我觉得原因是所有的id应该会存储到⼀个const tables中,到其中并没有该id值,那么就没有查找的必要了。
4.1.1.3、创建主键索引 CREATE TABLE t2 (
id INT NOT NULL, name CHAR(10), PRIMARY KEY(id) );
INSERT INTO t2 VALUES(1,'QQQ');
EXPLAIN SELECT * FROM t2 WHERE id = 1\\G;
通过这个主键索引,我们就应该反应过来,其实我们以前声明的主键约束,就是⼀个主键索引,只是之前我们没学过,不知道⽽已。
4.1.1.4、创建单列索引
这个其实就不⽤在说了,前⾯⼏个就是单列索引。
4.1.1.5、创建组合索引
组合索引就是在多个字段上创建⼀个索引
创建⼀个表t3,在表中的id、name和age字段上建⽴组合索引 CREATE TABLE t3 (
id INT NOT NULL,
name CHAR(30) NOT NULL, age INT NOT NULL, info VARCHAR(255), INDEX MultiIdx(id,name,age) );
SHOW CREATE t3\\G;
解释最左前缀
组合索引就是遵从了最左前缀,利⽤索引中最左边的列集来匹配⾏,这样的列集称为最左前缀,不明⽩没关系,举⼏个例⼦就明⽩了,例如,这⾥由id、name和age3个字段构成的索引,索引⾏中就按id/name/age的顺序存放,索引可以索引下⾯字段组合(id,name,age)、(id,name)或者(id)。如果要查询的字段不构成索引最左⾯的前缀,那么就不会是⽤索引,⽐如,age或者(name,age)组合就不会使⽤索引查询
在t3表中,查询id和name字段
EXPLAIN SELECT * FROM t3 WHERE id = 1 AND name = 'joe'\\G;
在t3表中,查询(age,name)字段,这样就不会使⽤索引查询。来看看结果 EXPLAIN SELECT * FROM t3 WHERE age = 3 AND name = 'bob'\\G;
4.1.1.6、创建全⽂索引
全⽂索引可以⽤于全⽂搜索,但只有MyISAM存储引擎⽀持FULLTEXT索引,并且只为CHAR、VARCHAR和TEXT列服务。索引总是对整个列进⾏,不⽀持前缀索引, CREATE TABLE t4 (
id INT NOT NULL,
name CHAR(30) NOT NULL, age INT NOT NULL, info VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
)ENGINE=MyISAM;
SHOW CREATE TABLE t4\\G;
使⽤⼀下什么叫做全⽂搜索。就是在很多⽂字中,通过关键字就能够找到该记录。
INSERT INTO t4 VALUES(8,'AAA',3,'text is so good,hei,my name is bob'),(9,'BBB',4,'my nameis gorlr');
SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');
EXPLAIN SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');
注意:在使⽤全⽂搜索时,需要借助MATCH函数,并且其全⽂搜索的限制⽐较多,⽐如只能通过MyISAM引擎,⽐如只能在CHAR,VARCHAR,TEXT上设置全⽂索引。⽐如搜索的关键字默认⾄少要4个字符,⽐如搜索的关键字太短就会被忽略掉。等等,如果你们在实验的时候可能会实验不出来。感兴趣的同学可以看看这篇⽂章,
4.1.1.7、创建空间索引
空间索引也必须使⽤MyISAM引擎, 并且空间类型的字段必须为⾮空。 这个空间索引具体能⼲嘛我也不知道,可能跟游戏开发有关,可能跟别的东西有关,等遇到了⾃然就知道了,现在只要求能够创建出来。 CREATE TABLE t5 (
g GEOMETRY NOT NULL, SPATIAL INDEX spatIdx(g) ) ENGINE = MyISAM; SHOW CREATE TABLE t5\\G;
4.1.2、在已经存在的表上创建索引
格式:ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名] (索引字段名)[ASC|DESC]
有了上⾯的基础,这⾥就不⽤过多陈述了。 命令⼀:SHOW INDEX FROM 表名\\G 查看⼀张表中所创建的索引 SHOW INDEX FROM book\\G;
挑重点讲,我们需要了解的就5个,⽤红颜⾊标记了的,如果想深⼊了解,可以去查查该⽅⾯的资料,我个⼈觉得,这些等以后实际⼯作中遇到了在做详细的了解把。 Table:创建索引的表
Non_unique:表⽰索引⾮唯⼀,1代表 ⾮唯⼀索引, 0代表 唯⼀索引,意思就是该索引是不是唯⼀索引
Key_name:索引名称
Seq_in_index 表⽰该字段在索引中的位置,单列索引的话该值为1,组合索引为每个字段在索引定义中的顺序(这个只需要知道单列索引该值就为1,组合索引为别的)
Column_name:表⽰定义索引的列字段 Sub_part:表⽰索引的长度 Null:表⽰该字段是否能为空值 Index_type:表⽰索引类型 4.1.2.1、为表添加索引
就拿上⾯的book表来说。本来已经有了⼀个year_publication,现在我们为该表在加⼀个普通索引 ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));
看输出结果,就能知道,添加索引成功了。
这⾥只是拿普通索引做个例⼦,添加其他索引也是⼀样的。依葫芦画瓢⽽已。这⾥就不⼀⼀做讲解了。 4.1.2.2、使⽤CREATE INDEX创建索引。
格式:CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] 索引名称 ON 表名(创建索引的字段名[length])[ASC|DESC]
解释:其实就是换汤不换药,格式改变了⼀下⽽已,做的事情跟上⾯完全⼀样,做⼀个例⼦。 在为book表增加⼀个普通索引,字段为authors。 CREATE INDEX BkBookNameIdx ON book(bookname);
SHOW INDEX FROM book\\G; //查看book表中的索引
解释:第⼀条截图没截到,因为图太⼤了,这⾥只要看到有我们新加进去的索引就证明成功了。。其他索引也是⼀样的创建。 4.2、删除索引
前⾯讲了对⼀张表中索引的添加,查询的⽅法。 添加的两种⽅式
1在创建表的同时如何创建索引,
2在创建了表之后如何给表添加索引的两种⽅式, 查询的⽅式
SHOW INDEX FROM 表名\\G; \\G只是让输出的格式更好看 现在来说说如何给表删除索引的两种操作。
格式⼀:ALTER TABLE 表名 DROP INDEX 索引名。
很简单的语句,现在通过⼀个例⼦来看看,还是对book表进⾏操作,删除我们刚才为其添加的索引。
1、删除book表中的名称为BkBookNameIdx的索引。 ALTER TABLE book DROP INDEX BkBookNameIdx;
已经不在了
删除
五、总结
SHOW INDEX FROM book\\G; //在查看book表中的索引,就会发现BkBookNameIdx这个索引格式⼆:DROP INDEX 索引名 ON 表名;book表中名为BkNameIdx的索引DROP INDEX BkNameIdx ON book;SHOW INDEX FROM book\\G;
MySQL的索引到这⾥差不多就讲完了,总结⼀下我们到⽬前为⽌应该知道哪些东西 1、索引是⼲嘛的?为什么要有索引?
这个很重要,需要⾃⼰理解⼀下,不懂就看顶部的讲解 2、索引的分类 3、索引的操作
给表中创建索引,添加索引,删除索引,删除索引
因篇幅问题不能全部显示,请点此查看更多更全内容