MySQL - 索引

目录

索引

普通索引

- 创建索引(三种方式)

- 删除索引:DROP INDEX 索引名 ON 表名字;

- 显示索引信息

聚集索引 amd 辅助索引

联合索引 and 覆盖索引

索引的使用

索引总结


索引

MySQL索引的建立可以大大提高MySQL的检索速度。

索引分单列索引组合索引

  • 单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。
  • 组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

索引的缺点:

  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
  • 建立索引会占用磁盘空间的索引文件。
  • 建立索引的时候,速度很慢

注:一旦表创建索引,所有查询首先查询索引,再根据索引定位的结果去找数据。


普通索引

- 创建索引(三种方式)

#方法一:创建表时
      CREATE TABLE 表名 (
                字段名1  数据类型 [完整性约束条件…],
                字段名2  数据类型 [完整性约束条件…],
                [UNIQUE | FULLTEXT | SPATIAL ]   INDEX | KEY
                [索引名]  (字段名[(长度)]  [ASC |DESC]) 
                );
CREATE TABLE mytable(  
 
    ID INT NOT NULL,   
 
    username VARCHAR(16) NOT NULL,  
 
    INDEX [indexName] (username(length))  
 
);  
#方法二:CREATE在已存在的表上创建索引
        CREATE  [UNIQUE | FULLTEXT | SPATIAL ]  INDEX  索引名 
                     ON 表名 (字段名[(长度)]  [ASC |DESC]) ;
CREATE INDEX indexName ON mytable(username(length)); 
#方法三:ALTER TABLE在已存在的表上创建索引
        ALTER TABLE 表名 ADD  [UNIQUE | FULLTEXT | SPATIAL ] INDEX
                             索引名 (字段名[(长度)]  [ASC |DESC]) ;
ALTER table tableName ADD INDEX indexName(columnName)

- 删除索引:DROP INDEX 索引名 ON 表名字;

DROP INDEX [indexName] ON mytable; 

- 显示索引信息

mysql> SHOW INDEX FROM table_name; \G

聚集索引 amd 辅助索引

聚集索引(clustered index)就是按照每张表的主键(primary key)构造一棵B+树,同时叶子结点存放的即为整张表的行记录数据,也将聚集索引的叶子结点称为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。

特点:叶子节点存放的一整条数据

如果未定义主键,MySQL取第一个唯一索引(unique)而且只含非空列(NOT NULL)作为主键,InnoDB使用它作为聚簇索引。
如果没有这样的列,InnoDB就自己产生一个这样的ID值,它有六个字节,而且是隐藏的,使其作为聚簇索引。
由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引。在多少情况下,查询优化器倾向于采用聚集索引。因为聚集索引能够在B+树索引的叶子节点上直接找到数据。此外由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值得查询。

表中除了聚集索引外其他索引都是辅助索引(Secondary Index,也称为非聚集索引),与聚集索引的区别是:辅助索引的叶子节点不包含行记录的全部数据。

特点:如果是按照这个字段创建的索引,那么叶子节点存放的是:{名字:名字所在那条记录的主键的值}

叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含一个书签(bookmark)。该书签用来告诉InnoDB存储引擎去哪里可以找到与索引相对应的行数据。

覆盖索引:只在辅助索引的叶子节点中就已经找到了所有想要的数据
    select name from user where name='name1';
非覆盖索引:查找非叶子节点存在的数据
    select age from user where name='name1';


联合索引 and 覆盖索引

联合索引:指对表上的多个列合起来做一个索引。联合索引的创建方法与单个索引的创建方法一样,不同之处在仅在于有多个索引列,如下:

mysql> create table t(
    -> a int,
    -> b int,
    -> primary key(a),
    -> key idx_a_b(a,b)
    -> );
Query OK, 0 rows affected (0.11 sec)

覆盖索引:InnoDB存储引擎支持覆盖索引(covering index,或称索引覆盖),即从辅助索引中就可以得到查询记录,而不需要查询聚集索引中的记录。


 

索引的使用​​​​​​​

  • 范围问题:条件不明确,即条件中出现这些符号或关键字:>、>=、<、<=、!= 、between...and...、like、
  • 尽量选择区分度高的列作为索引:
      
    区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0。
  • =和in可以乱序.
      比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式
  • 索引列不能参与计算,保持列“干净”.
      比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(’2014-05-29’)
  • 最左前缀匹配原则:对于组合索引mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(指的是范围大了,有索引速度也慢),比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。
  • 排序条件为索引,则select也是索引字段。
  • 避免使用select *
  • count(1)或count(列)代替count(*)
  • 创建表时尽量char代替varchar
  • 表的字段顺序固定长度的字段优先
  • 组合索引代替多个单利索引(进程使用多个条件查询时)
  • 尽量使用短索引
  • 使用连接(join)来代替子索引(sub-queries)
  • 连表时注意条件类型需要一致
  • 索引散列值(重复少)不适合建索引。

索引总结

#1. 一定是为搜索条件的字段创建索引,比如select * from s1 where id = 333;就需要为id加上索引

#2. 在表中已经有大量数据的情况下,建索引会很慢,且占用硬盘空间,建完后查询速度加快
比如create index idx on s1(id);会扫描表中所有的数据,然后以id为数据项,创建索引结构,存放于硬盘的表中。
建完以后,再查询就会很快了。

#3. 需要注意的是:innodb表的索引会存放于s1.ibd文件中,而myisam表的索引则会有单独的索引文件table1.MYI

MySAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在innodb中,表数据文件本身就是按照B+Tree(BTree即Balance True)组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此innodb表数据文件本身就是主索引。
因为inndob的数据文件要按照主键聚集,所以innodb要求表必须要有主键(Myisam可以没有),如果没有显式定义,则mysql系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则mysql会自动为innodb表生成一个隐含字段作为主键,这字段的长度为6个字节,类型为长整型.

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/82777582