MySQL(五) MySQL中的索引详讲

      序言html

         以前写到MySQL对表的增删改查(查询最为重要)后,就感受MySQL就差很少学完了,没有想继续学下去的心态了,缘由多是因为别人的影响,以为对于MySQL来讲,知道了一些复杂的查询,就够了,可是我认为,无论有没有用,如今学着不懂的东西,说明就是本身薄弱的地方,多学才能比别人更强mysql

                                        --WZY算法

 

1、什么是索引?为何要创建索引?sql

       索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,若是表中查询的列有一个索引,MySQL可以快速到达一个位置去搜索数据文件,而没必要查看全部数据,那么将会节省很大一部分时间。函数

       例如:有一张person表,其中有2W条记录,记录着2W我的的信息。有一个Phone的字段记录每一个人的电话号码,如今想要查询出电话号码为xxxx的人的信息。post

          若是没有索引,那么将从表中第一条记录一条条往下遍历,直到找到该条信息为止。学习

          若是有了索引,那么会将该Phone字段,经过必定的方法进行存储,好让查询该字段上的信息时,可以快速找到对应的数据,而没必要在遍历2W条数据了。其中MySQL中的索引的存储类型有两种:BTREE、HASH。 也就是用树或者Hash值来存储该字段,要知道其中详细是如何查找的,就须要会算法的知识了。咱们如今只须要知道索引的做用,功能是什么就行。测试

 

 

2、MySQL中索引的优势和缺点和使用原则优化

      优势:spa

       二、全部的MySql列类型(字段类型)均可以被索引,也就是能够给任意字段设置索引

       三、大大加快数据的查询速度

      缺点:

       一、建立索引和维护索引要耗费时间,而且随着数据量的增长所耗费的时间也会增长

       二、索引也须要占空间,咱们知道数据表中的数据也会有最大上线设置的,若是咱们有大量的索引,索引文件可能会比数据文件更快达到上线值

       三、当对表中的数据进行增长、删除、修改时,索引也须要动态的维护,下降了数据的维护速度。

      使用原则:

            经过上面说的优势和缺点,咱们应该能够知道,并非每一个字段度设置索引就好,也不是索引越多越好,而是须要本身合理的使用。

       一、对常常更新的表就避免对其进行过多的索引,对常常用于查询的字段应该建立索引,

       二、数据量小的表最好不要使用索引,由于因为数据较少,可能查询所有数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。

       三、在一同值少的列上(字段上)不要创建索引,好比在学生表的"性别"字段上只有男,女两个不一样值。相反的,在一个字段上不一样值较多但是创建索引。

  

      上面说的只是很片面的一些东西,索引确定还有不少别的优势或者缺点,还有使用原则,先基本上理解索引,而后等之后真正用到了,就会慢慢知作别的做用。注意,学习这张,很重要的一点就是必须先得知道索引是什么,索引是干吗的,有什么做用,为何要索引等等,若是不知道,就重复往上面看看写的文字,好好理解一下。一个表中很够建立多个索引,这些索引度会被存放到一个索引文件中(专门存放索引的地方)

 

 

3、索引的分类  

       注意:索引是在存储引擎中实现的,也就是说不一样的存储引擎,会使用不一样的索引

            MyISAM和InnoDB存储引擎:只支持BTREE索引, 也就是说默认使用BTREE,不可以更换

            MEMORY/HEAP存储引擎:支持HASH和BTREE索引

       一、索引咱们分为四类来说 单列索引(普通索引,惟一索引,主键索引)、组合索引、全文索引、空间索引、

          1.一、单列索引:一个索引只包含单个列,但一个表中能够有多个单列索引。 这里不要搞混淆了。

             1.1.一、普通索引

                  MySQL中基本索引类型,没有什么限制,容许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。

             1.1.二、惟一索引

                  索引列中的值必须是惟一的,可是容许为空值,

             1.1.三、主键索引

                  是一种特殊的惟一索引,不容许有空值。

          1.二、组合索引

               在表中的多个字段组合上建立的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。这个若是还不明白,等后面举例讲解时在细说 

          1.三、全文索引

               全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,经过其中的某个关键字等,就能找到该字段所属的记录行,好比有"你是个大煞笔,二货 ..." 经过大煞笔,可能就能够找到该条记录。这里说的是可能,由于全文索引的使用涉及了不少细节,咱们只须要知道这个大概意思,若是感兴趣进一步深刻使用它,那么看下面测试该索引时,会给出一个博文,供你们参考。

          1.四、空间索引

               空间索引是对空间数据类型的字段创建的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。

               在建立空间索引时,使用SPATIAL关键字。

               要求,引擎为MyISAM,建立空间索引的列,必须将其声明为NOT NULL。具体细节看下面   

 

4、索引操做(建立和删除)

      4.一、建立索引

          4.1.一、建立表的时候建立索引

            格式:CREATE TABLE 表名[字段名 数据类型]  [UNIQUE|FULLTEXT|SPATIAL|...] [INDEX|KEY] [索引名字] (字段名[length])   [ASC|DESC]

               |--------------------------------------|  |-----------------------------------| |------------| |---------| |---------------|    |------------|

                    普通建立表语句        设置什么样的索引(惟1、全文等)  索引关键字  索引名字 对哪一个字段设置索引  对索引进行排序 

              4.1.1.一、建立普通索引              

                CREATE TABLE book                    CREATE TABLE book

                (                              (

                  bookid INT NOT NULL,                  bookid INT NOT NULL,

                  bookname VARCHAR(255) NOT NULL,           bookname VARCHAR(255) NOT NULL,

                  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 NOT NULL,

                  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.二、建立惟一索引  

                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.三、建立主键索引

                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.1.1.五、建立组合索引

                组合索引就是在多个字段上建立一个索引

                建立一个表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.六、建立全文索引

                全文索引能够用于全文搜索,但只有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 name is 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.七、建立空间索引

                空间索引也必须使用MyISAM引擎, 而且空间类型的字段必须为非空。 这个空间索引具体能干吗我也不知道,可能跟游戏开发有关,可能跟别的东西有关,等遇到了天然就知道了,如今只要求可以建立出来。

                CREATE TABLE t5

                (

                  g GEOMETRY NOT NULL,

                  SPATIAL INDEX spatIdx(g)

                ) ENGINE = MyISAM;

                SHOW CREATE TABLE t5\G;

                    

          4.1.二、在已经存在的表上建立索引

              格式: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.一、为表添加索引

                就拿上面的book表来讲。原本已经有了一个year_publication,如今咱们为该表在加一个普通索引

                ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));

                    

                看输出结果,就能知道,添加索引成功了。

                这里只是拿普通索引作个例子,添加其余索引也是同样的。依葫芦画瓢而已。这里就不一一作讲解了。

             4.1.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.二、删除索引

            前面讲了对一张表中索引的添加,查询的方法。

              添加的两种方式

                1在建立表的同时如何建立索引,

                2在建立了表以后如何给表添加索引的两种方式,

              查询的方式

                SHOW INDEX FROM 表名\G;  \G只是让输出的格式更好看

              如今来讲说如何给表删除索引的两种操做。

                格式一:ALTER TABLE 表名 DROP INDEX 索引名

                  很简单的语句,如今经过一个例子来看看,仍是对book表进行操做,删除咱们刚才为其添加的索引。

                一、删除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;

                        

 

5、总结

      MySQL的索引到这里差很少就讲完了,总结一下咱们到目前为止应该知道哪些东西

        一、索引是干吗的?为何要有索引?

            这个很重要,须要本身理解一下,不懂就看顶部的讲解

        二、索引的分类

        三、索引的操做

            给表中建立索引,添加索引,删除索引,删除索引  

 

转载于:https://www.cnblogs.com/whgk/p/6179612.html