13)mysql的索引

*爱你&永不变心* 提交于 2019-11-29 06:26:42
  • 索引的作用是什么
    告诉存储引擎如何快速的查找所需要的数据,类似目录,可以快速定位到某个区域,而如果没有索引,只能一页一页翻找寻找需要的内容。在磁盘上表现就是要慢慢扫描查找。

  • Innodb支持的索引类型
    Btree索引
    自适应HASH索引
    全文索引
    空间索引
    一般没特别说明,都是指Btree索引,结构如下图

-- 查询出2019年1月1号之后注册的男性会员昵称
EXPLAIN
SELECT user_nick
FROM imc_user
WHERE sex=1 AND reg_time>'2019-01-01';
输出
    id  select_type  table     partitions  type    possible_keys  key     key_len  ref       rows  filtered  Extra        
------  -----------  --------  ----------  ------  -------------  ------  -------  ------  ------  --------  -------------
     1  SIMPLE       imc_user  (NULL)      ALL     idx_sex        (NULL)  (NULL)   (NULL)    2530      3.33  Using where  

-- 筛选性
SELECT COUNT(DISTINCT sex)
,COUNT(DISTINCT DATE_FORMAT(reg_time,'%Y-%m-%d'))
,COUNT(*)
,COUNT(DISTINCT sex)/COUNT(*)
,COUNT(DISTINCT DATE_FORMAT(reg_time,'%Y-%m-%d'))/COUNT(*)
FROM imc_user                                                  


CREATE INDEX idx_regtime ON imc_user(reg_time)

EXPLAIN
SELECT user_nick
FROM imc_user
WHERE sex=1 AND reg_time>'2019-01-01';

'再次获取sql的执行计划,输出'
    id  select_type  table     partitions  type    possible_keys        key          key_len  ref       rows  filtered  Extra                               
------  -----------  --------  ----------  ------  -------------------  -----------  -------  ------  ------  --------  ------------------------------------
     1  SIMPLE       imc_user  (NULL)      range   idx_sex,idx_regtime  idx_regtime  5        (NULL)     516     10.00  Using index condition; Using where 
'添加索引之后,再次执行执行计划,要比之前没索引的情况好 '

DROP INDEX idx_regtime ON imc_user

-- 给sex添加索引后,并不会使用到索引,同样要扫描2530行数据
-- 说明在筛选性不好的列上建立索引,没有任何作用
CREATE INDEX idx_sex ON imc_user(sex)

DROP INDEX idx_sex ON imc_user

区分度最高的列放在联合索引最左侧,因为mysql从左侧开始匹配,左侧区分越高,能筛选的越高,另外索引键值长度越小,性能也越好

如果用abc组成的索引,查询ac,那只能用到a的索引

好的索引能提高数据库性能,不好的索引也能降低数据库性能

一方面索引能增加查询效率,但同样会降低插入和更新数据的速率,甚至在某些情况索引同样会降低查询效率,因为mysql优化器在选择如何优化查询时,会根据统一信息对可以用到的索引进行评估,以生成最优执行计划,如果有太多索引都能用于查询,会增加mysql优化器生成执行计划的时间

MySQL数据页大小为16K,每行记录越长,每个数据页存储的记录数就越少,因此在对数据进行检索时,会产生更多的IO,所以索引的长度大小也会影响检索速度,索引长度越小越好

使用 or 运算符来关联多个查询条件,可能无法用到索引,但in列表查询不一样,是可以用到索引的,所以在优化sql时,有一种方法就是用in代替or,但如果in()表中数据太多,mysql优化器认为效率不好也可能用全局扫描的方法

mysql优化器会自动调整过滤查询的顺序,以适应索引键值的顺序 ,从而正确的使用索引

EXPLAIN
SELECT course_id,b.class_name,d.type_name,c.level_name,title,score
FROM imc_course a
JOIN imc_class b ON b.`class_id`=a.`class_id`
JOIN imc_level c ON c.`level_id`=a.`level_id`
JOIN imc_type d ON d.`type_id`=a.`type_id`
WHERE c.`level_name`='高级'
AND b.`class_name`='MySQL'

-- 联合索引,按照可筛选性排序
CREATE INDEX idx_classid_typeid_levelid ON imc_course(class_id,type_id,level_id);

DROP INDEX idx_classid_typeid_levelid ON imc_course;

CREATE INDEX idx_levelname ON imc_level(level_name)

-- 查询出不存在课程的分类名称
EXPLAIN
SELECT class_name
FROM imc_class
WHERE class_id NOT IN (SELECT class_id FROM imc_course )

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!