Mysql索引

为什么使用索引速度更快

B+树查找时采用多分查找,速度更快。

底层索引结构

B+树索引

B+树是一个多叉搜索树,数据都存在叶子节点的data域中,非叶子节点中没有数据,只有对应的key的值,这样可以保证每个数据查询的平均效率是一样的。并且叶子节点之间用链表相连接,使得获得全表数据更容易。所有叶子节点都在一层。

B树

B树也是一个多叉搜索树,但是数据存放在节点中,所有叶子节点都在一层。

使用B+树的原因:

  • 是因为B+树查询效率更稳定(数据都在叶子节点)。
  • B+树支持预读取。
  • B+树扫库更方便,叶子节点相连。
  • 范围查找更高效。

不用二叉树原因:

  • 二叉树高度较高,因为查询速度和高度相关,所以二叉树速度更慢。

Hash索引

通过建立对应的hash表结构建立索引。
能以O(1)的速度进行查找,但是失去了有序性,且不支持范围查找。

概念索引

聚簇索引

聚簇索引是指在索引中保存了数据,从而避免了读取磁盘,提高了效率。
在聚簇索引的叶子节点的data域中记录着完整的数据记录(行记录)。一般默认为主键建立聚簇索引。
有序的。

非聚簇索引(辅助索引)

Innodb
innodb的辅助索引的叶子节点中不存储数据,而是保存的指向主键的位置的指针(这里会有一次IO,通过指针找到对应的主键),然后通过主键,使用聚簇索引,找到对应的数据。
MyISAM
MyISAM存储时,数据和索引是分开存储的,数据存储在一个地方,索引存储在一个地方,所以它的叶子节点存储的是指向data的指针,直接找到数据。(MyISAM的聚簇索引和非聚簇索引没什么差别)。
在这里插入图片描述

应用索引

主键索引

它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引(一般对应聚簇索引)

唯一索引

MySQL数据库索引列的值必须唯一,但允许有空值。

全文索引

使用MyISAM支持

普通索引

基本的索引,它没有任何限制。

联合索引

mysql> CREATE TABLE `t_mobilesms_11` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `userId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '用户id,创建任务时的userid',
    `mobile` varchar(24) NOT NULL DEFAULT '' COMMENT '手机号码',
    `billMonth` varchar(32) DEFAULT NULL COMMENT '账单月',
    `time` varchar(32) DEFAULT NULL COMMENT '收/发短信时间',
    `peerNumber` varchar(64) NOT NULL COMMENT '对方号码',
    `location` varchar(64) DEFAULT NULL COMMENT '通信地(自己的)',
    `sendType` varchar(16) DEFAULT NULL COMMENT 'SEND-发送; RECEIVE-收取',
    `msgType` varchar(8) DEFAULT NULL COMMENT 'SMS-短信; MSS-彩信',
    `serviceName` varchar(256) DEFAULT NULL COMMENT '业务名称. e.g. 点对点(网内)',
    `fee` int(11) DEFAULT NULL COMMENT '通信费(单位分)',
    `createTime` datetime DEFAULT NULL COMMENT '创建时间',
    `lastModifyTime` datetime DEFAULT NULL COMMENT '最后修改时间',
    PRIMARY KEY (`id`),
    KEY `联合索引` (`userId`,`mobile`,`billMonth`)
    ) ENGINE=InnoDB AUTO_INCREMENT=71185 DEFAULT CHARSET=utf8 COMMENT='手机短信详情';
Query OK, 0 rows affected (0.43 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222';
+----+-------------+----------------+------+---------------+----------+---------+-------+------+-----------------------+
| id | select_type | table          | type | possible_keys | key      | key_len | ref   | rows | Extra                 |
+----+-------------+----------------+------+---------------+----------+---------+-------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | ref  | 联合索引      | 联合索引 | 767     | const |    1 | Using index condition |
+----+-------------+----------------+------+---------------+----------+---------+-------+------+-----------------------+
1 row in set (0.07 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972'
    -> ;
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table          | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t_mobilesms_11 | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using where |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE billMonth='2018-04'
    -> ;
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table          | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t_mobilesms_11 | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using where |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND mobile='13281899972'
    -> ;
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
| id | select_type | table          | type | possible_keys | key      | key_len | ref         | rows | Extra                 |
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | ref  | 联合索引      | 联合索引 | 841     | const,const |    1 | Using index condition |
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE  mobile='13281899972' AND userid='2222'
    -> ;
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
| id | select_type | table          | type | possible_keys | key      | key_len | ref         | rows | Extra                 |
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | ref  | 联合索引      | 联合索引 | 841     | const,const |    1 | Using index condition |
+----+-------------+----------------+------+---------------+----------+---------+-------------+------+-----------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972' AND billMonth='2018-04'
    -> ;
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table          | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t_mobilesms_11 | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using where |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid>'2222' AND mobile like '%123';
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
| id | select_type | table          | type  | possible_keys | key      | key_len | ref  | rows | Extra                 |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | range | 联合索引      | 联合索引 | 767     | NULL |    1 | Using index condition |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
1 row in set

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid>'2222' AND mobile like '123%';
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
| id | select_type | table          | type  | possible_keys | key      | key_len | ref  | rows | Extra                 |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | range | 联合索引      | 联合索引 | 767     | NULL |    1 | Using index condition |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
1 row in set

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE 
mobile like '123%';
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table          | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t_mobilesms_11 | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using where |
+----+-------------+----------------+------+---------------+------+---------+------+------+-------------+
1 row in set

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile like '123%'  AND userid>'2222';
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
| id | select_type | table          | type  | possible_keys | key      | key_len | ref  | rows | Extra                 |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+
|  1 | SIMPLE      | t_mobilesms_11 | range | 联合索引      | 联合索引 | 767     | NULL |    1 | Using index condition |
+----+-------------+----------------+-------+---------------+----------+---------+------+------+-----------------------+

三个单列索引

mysql> CREATE TABLE `t_mobilesms_11` (
    ->   `id` bigint(20) NOT NULL AUTO_INCREMENT,
    ->   `userId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '用户id,创建任务时的userid',
    ->   `mobile` varchar(24) NOT NULL DEFAULT '' COMMENT '手机号码',
    ->   `billMonth` varchar(32) DEFAULT NULL COMMENT '账单月',
    ->   `time` varchar(32) DEFAULT NULL COMMENT '收/发短信时间',
    ->   `peerNumber` varchar(64) NOT NULL COMMENT '对方号码',
    ->   `location` varchar(64) DEFAULT NULL COMMENT '通信地(自己的)',
    ->   `sendType` varchar(16) DEFAULT NULL COMMENT 'SEND-发送; RECEIVE-收取',
    ->   `msgType` varchar(8) DEFAULT NULL COMMENT 'SMS-短信; MSS-彩信',
    ->   `serviceName` varchar(256) DEFAULT NULL COMMENT '业务名称. e.g. 点对点(网内)',
    ->   `fee` int(11) DEFAULT NULL COMMENT '通信费(单位分)',
    ->   `createTime` datetime DEFAULT NULL COMMENT '创建时间',
    ->   `lastModifyTime` datetime DEFAULT NULL COMMENT '最后修改时间',
    ->   PRIMARY KEY (`id`),
    ->   INDEX id_index(`userId`),
    ->   INDEX mobile_index(`mobile`),
    ->   INDEX billMonth_index(`billMonth`)
    -> ) ENGINE=InnoDB AUTO_INCREMENT=71185 DEFAULT CHARSET=utf8 COMMENT='手机短信详情'
    -> ;
Query OK, 0 rows affected (0.32 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE  userid='2222' AND mobile='13281899972' AND billMonth='2018-04'
    -> ;
+----+-------------+----------------+------+---------------------------------------+----------+---------+-------+------+------------------------------------+
| id | select_type | table          | type | possible_keys                         | key      | key_len | ref   | rows | Extra                              |
+----+-------------+----------------+------+---------------------------------------+----------+---------+-------+------+------------------------------------+
|  1 | SIMPLE      | t_mobilesms_11 | ref  | id_index,mobile_index,billMonth_index | id_index | 767     | const |    1 | Using index condition; Using where |
+----+-------------+----------------+------+---------------------------------------+----------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972' AND billMonth='2018-04'
    -> ;
+----+-------------+----------------+------+------------------------------+--------------+---------+-------+------+------------------------------------+
| id | select_type | table          | type | possible_keys                | key          | key_len | ref   | rows | Extra                              |
+----+-------------+----------------+------+------------------------------+--------------+---------+-------+------+------------------------------------+
|  1 | SIMPLE      | t_mobilesms_11 | ref  | mobile_index,billMonth_index | mobile_index | 74      | const |    1 | Using index condition; Using where |
+----+-------------+----------------+------+------------------------------+--------------+---------+-------+------+------------------------------------+
1 row in set (0.00 sec)

mysql> EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE  userid='2222' OR mobile='13281899972'
    -> ;
+----+-------------+----------------+------+-----------------------+------+---------+------+------+-------------+
| id | select_type | table          | type | possible_keys         | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------------+------+-----------------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t_mobilesms_11 | ALL  | id_index,mobile_index | NULL | NULL    | NULL |    1 | Using where |
+----+-------------+----------------+------+-----------------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

覆盖索引

索引失效情况

  1. 使用OR语句的时候会发生索引失效。
    原因:对于or左右的两个字段,如果第一个加了索引,第二个没加,那么查找的顺序为(索引+全表+合并),那么既然要全表扫描了,何不直接一次全表扫描得到需要的数据。
    但如果or的左右列都加了索引,那么索引还是可能走的。
  2. 使用like通配符科恩那个会导致索引失效
    使用like %123此种情况时,会导致索引失效
    但是使用 like 123%这种情况的时候,不会导致索引失效。
  3. 联合索引查序顺序和定义顺序不同会失效
    比如一个索引 idx_name_age(name,age)
    那么where name=“…” and age="…“有效;
    where name=“…” 有效
    where age=”…" 无效
  4. 使用mysql的内置函数会是索引无效
  5. 对索引列加运算(=,+,-,/)
  6. 对索引列使用in not in时会失效
  7. 对索引列使用!=或<>时会失效
  8. 对索引列使用is null或is not null时会失效
  9. 对索引进行表达式操作时会失效
    10.mysql估计使用全表扫描要比使用索引快,则不使用索引
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值