这里上一张不同存储引擎对数据结构支持情况表

索引 InnoDB MyISAM Memory
Btree 支持 支持 支持
Hash 不支持 不支持 支持
R-tree 不支持 支持 不支持
FULL-TEXT 5.60版本后支持 支持 不支持
  1. show VARIABLES like '%version%'; //我的mysql version配置为5.5.40,所以不支持FULL-TEXT

image.png
sql脚本film表

  1. CREATE TABLE `film` (
  2. `film_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  3. `title` varchar(128) NOT NULL,
  4. `description` text,
  5. `release_year` year(4) DEFAULT NULL,
  6. `language_id` tinyint(3) unsigned NOT NULL,
  7. `original_language_id` tinyint(3) unsigned DEFAULT NULL,
  8. `rental_duration` tinyint(3) unsigned NOT NULL DEFAULT '3',
  9. `rental_rate` decimal(4,2) NOT NULL DEFAULT '4.99',
  10. `length` smallint(5) unsigned DEFAULT NULL,
  11. `replacement_cost` decimal(5,2) NOT NULL DEFAULT '19.99',
  12. `rating` enum('G','PG','PG-13','R','NC-17') DEFAULT 'G',
  13. `special_features` set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') DEFAULT NULL,
  14. `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  15. PRIMARY KEY (`film_id`),
  16. KEY `idx_title` (`title`),
  17. KEY `idx_fk_language_id` (`language_id`),
  18. KEY `idx_fk_original_language_id` (`original_language_id`),
  19. CONSTRAINT `fk_film_language` FOREIGN KEY (`language_id`) REFERENCES `language` (`language_id`) ON UPDATE CASCADE,
  20. CONSTRAINT `fk_film_language_original` FOREIGN KEY (`original_language_id`) REFERENCES `language` (`language_id`) ON UPDATE CASCADE
  21. ) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4;

city表

  1. CREATE TABLE `city` (
  2. `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
  3. `city` varchar(50) NOT NULL,
  4. `country_id` smallint(5) unsigned NOT NULL,
  5. `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  6. PRIMARY KEY (`city_id`),
  7. KEY `idx_fk_country_id` (`country_id`),
  8. CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE
  9. ) ENGINE=InnoDB AUTO_INCREMENT=601 DEFAULT CHARSET=utf8mb4;

1.索引的创建(create)

  1. create index index_update_time ON city(last_update);

在表的对象信息中可以看到下面新增了一条index_update_time索引

image.png

可以通过show INDEX from city;

  1. show INDEX from city; //查看city表中的所有索引命令

image.png

2.索引的修改(alter)

  1. ALTER TABLE film ADD FULLTEXT film(description);

2.1在表中增加一个唯一索引

  1. ALTER TABLE staff ADD UNIQUE index_email (email); //staff表中增加email的索引

PRIMARY和unique 索引的区别 都可以表示唯一,但是primary表示唯一的且非空的,unique表示是唯一的但是可以为null(可以有多个)的

NOTE
:对于mysql 5.6版本之前的innodb引擎 是不支持FULLTEXT索引的,报错The used table type doesn’t support FULLTEXT indexes
MyIsam是支持全文索引的

image.png

总结

3.索引的查看(show)

  1. show INDEX from staff; //查看staff表建立了那些索引

image.png

4.索引的删除(drop)

  1. DROP INDEX index_update_time ON city; //删除city表索引

5.索引设计基本原则

  • 在搜索的索引列,不一定的要选择的列,讲人话就是:最适合建立索引的列是在where子句中的列,或是连接子句的列,而不是select关键字后的选择展示的列
  • 使用唯一索引,要考虑列的值的分布,索引的列的基数越大,索引效果越好,比如存放出生日期的列具有不同的值,很容易区分各行,而性别的列只有”M”和”F”不容易区分,不管选择哪个,都是搜索出大约一半的行
  • 使用短索引,较短的值比较起来更快,占用的内存页更小
  • 利用最左前缀原则,比如
    • create index idx_name_email_status on tb_seller(name,email,status); 等价于
      • 对name 创建索引
      • 对name,email索引
      • 对name,email,status创建索引

NOTE:
对于最左前缀索引(包含最左,不能跳跃列)是否生效做一个说明,
通俗的理解可以理解为像爬楼梯一样:必须从第一层楼开始爬,不能跨楼层爬,
比如不能从1楼直接飞到3楼,对应上面的例子 where name = ‘zhangsan’ and status = ‘1’ ,status是不走索引的,只有name走索引了

总结:
最后拿个例子来说明是否走索引
新建一张consumer表

  1. CREATE TABLE `consumer` (
  2. `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  3. `USERNAME` varchar(50) NOT NULL COMMENT '用户名',
  4. `FULLNAME` varchar(50) DEFAULT '' COMMENT '真实姓名',
  5. `ID_NUMBER` varchar(50) DEFAULT NULL COMMENT '身份证号',
  6. `USER_NO` varchar(50) DEFAULT NULL COMMENT '用户编码,生成唯一,用户在存管系统标识',
  7. `MOBILE` varchar(50) DEFAULT NULL COMMENT '平台预留手机号',
  8. `USER_TYPE` varchar(50) DEFAULT NULL COMMENT '用户类型,个人or企业,预留',
  9. `ROLE` varchar(50) DEFAULT NULL COMMENT '用户角色.B借款人or I投资人',
  10. `AUTH_LIST` varchar(50) DEFAULT NULL COMMENT '存管授权列表',
  11. `IS_BIND_CARD` tinyint(1) DEFAULT NULL COMMENT '是否已绑定银行卡',
  12. `LOAN_AMOUNT` decimal(10,0) DEFAULT NULL,
  13. `STATUS` tinyint(1) DEFAULT NULL COMMENT '可用状态',
  14. `REQUEST_NO` varchar(50) DEFAULT NULL COMMENT '请求流水号',
  15. PRIMARY KEY (`ID`)
  16. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='c端用户信息表';

插入一条sql

  1. INSERT INTO `consumer` (
  2. `ID`,
  3. `USERNAME`,
  4. `FULLNAME`,
  5. `ID_NUMBER`,
  6. `USER_NO`,
  7. `MOBILE`,
  8. `USER_TYPE`,
  9. `ROLE`,
  10. `AUTH_LIST`,
  11. `IS_BIND_CARD`,
  12. `LOAN_AMOUNT`,
  13. `STATUS`,
  14. `REQUEST_NO`
  15. )
  16. VALUES
  17. (
  18. '1',
  19. 'zhangsan',
  20. 'zhangsan',
  21. '360752199812033213',
  22. 'ID0001',
  23. '18942123126',
  24. NULL,
  25. NULL,
  26. NULL,
  27. NULL,
  28. NULL,
  29. '1',
  30. NULL
  31. );

创建一个组合索引

  1. CREATE INDEX idx_username_MOBILE_status ON consumer(username,MOBILE,status);

查看第1条sql和执行计划

  1. EXPLAIN SELECT * from consumer WHERE username = 'zhangsan';

image.png

查看第2条sql和执行计划

  1. EXPLAIN SELECT * from consumer WHERE username = 'zhangsan' and mobile = '18942123126';

image.png

查看第3条sql和执行计划

  1. EXPLAIN SELECT * from consumer WHERE username = 'zhangsan' and mobile = '18942123126' and STATUS = '1';

image.png

可以看到type属性都是为ref,说明都是走了索引的,符合我们的最左前缀原则,其实我们还要关注一个字段就是key_len的大小

那么对于WHERE username = ‘zhangsan’ and STATUS = ‘1’(跳过了中间的mobile),这种是不是走索引呢(还记得爬楼的例子么,不能跳跃的例子)

  1. SELECT * from consumer WHERE username = 'zhangsan' and STATUS = '1';

我们看一下执行计划:

  1. EXPLAIN SELECT * from consumer WHERE username = 'zhangsan' and STATUS = '1';

image.png

大家仔细看type=ref,这是走了索引的,但是只是对于第一个WHERE username = ‘zhangsan’走了索引,而后面的and STATUS = ‘1’并没有走索引,那我是怎么知道的呢,因为这里面的key_len和前面的第1条只有一个查询的WHERE username = ‘zhangsan’的长度是一样的 都是152,

image.png
其实也就是说最左前缀原则要满足(包含最左并且列不能跳跃),你对最左前缀原则是否又加深了一点呢