博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mysql的索引类型和左前缀索引
阅读量:5331 次
发布时间:2019-06-14

本文共 6904 字,大约阅读时间需要 23 分钟。

一、常见mysql索引类型

1.B-Tree索引

大的方面看,都用的是平衡树,但集体的实现上,各引擎稍有不同点,比如:严格的说,NDB引擎使用的是T-tree,但是在myisam,innodb中,默认的使用的是B-tree索引

B-tree索引可以理解称为‘排好序的快速查找结构’

2.hash索引

在memory中,默认的是hash索引,hash的理论查询时间复杂度为O(1)

那为啥hash的查找如此的高效,为什么都不用hash索引?

1.hash函数计算后的结果是随机的,这是由于hash的映射关系是无序的,就好比python中的字典,底层用的也是hash,所以也是无序随机的

2.无法对范围查询进行优化

3.排序无法进行优化

二、使用B-tree索引的误区

1.在where条件常用列上加上索引

例如:where cat_id=3 and price>1000;#查询第3个栏目1000元以上的商品

误区:cai_id和price上都加索引,都会使用到该索引

纠正:只能用上cat_id或是price索引,因为都是独立的索引,同时只能用上1个

三、左前缀索引

1.案例

假设某个表有一个联合索引(c1,c2,c3,c4)一下只能使用该联合索引的c1,c2,c3部分

A:where c1=x and c2=x and c4>x and c3=x

B:where c1=x and c2=x and c4=x order by c3

C:where c1=x and c4=x group by c3,c2

D:where c1=x and c5=x order by c2,c3

E:where c1=x and c2=x and c5=? order by c2,c3

2.左前缀索引到底是什么?

现在建立联合索引index(a,b,c),我们来具体分析

 

语句 索引是否发挥作用
where a=3     是,只是用了a列的索引
where a=3 and b=5     是, 使用了a,b列
where a=3 and b=5 and c=4    是, 使用了abc
Where b=3 or where c=4   
Where b=3 and where c=4    a列能发挥索引,c不能
Where a=3 and b>10 and c=7 a 能利用,b能利用, c不能利用
同上,where a=3 and b like ‘xxxx%’ and c=7 a 能利用,b能利用, c不能利用

那么问题来了,如何去理解上面索引的使用?

为便于理解,假设ABC各10米长的木板,河面宽30米

全值索引,则木板长10米,like,及范围查询,则木板长6米

自己拼接一下,能否过河对岸,就知道索引能否利用上

如上例中,where a=3 and b>10 and c=7

A板长10米,A列索引发挥作用

A板正常接B板,B列索引发挥作用

B板短了,接不到C板,C列索引不发挥作用

3.解决上述问题

此时,我们刚开始的那个案例,就可以使用我们刚刚讲到的左前缀索引的知识来进行分析了

首先,建立一张测试表

create table t4(c1 tinyint(1) not null default 0,c2 tinyint(1) not null default 0,c3 tinyint(1) not null default 0,c4 tinyint(1) not null default 0,c5 tinyint(1) not null default 0,index c1234(c1,c2,c3,c4));insert into t4 values (1,3,5,6,7),(2,3,9,8,3),(4,3,2,7,5);

对于A选项

c1=x and c2=x and c4>x and c3=x <==等价==> c1=x and c2=x and c3=x and c4>x

因此 c1,c2,c3,c4都能用上

mysql> explain select * from t4 where c1=1 and c2=2 and c4>3 and c3=3 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: rangepossible_keys: c1234          key: c1234      key_len: 4 #可以看出c1,c2,c3,c4索引都用上

对于B选项

c1=1 and c2=2 and c4=3 order by c3

c1,c2索引用上了,c3是排好序的,因此不用额外排序,而c4没发挥作用

mysql> explain select * from t4 where c1=1 and c2=2 and c4=3 order by c3 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: refpossible_keys: c1234          key: c1234      key_len: 2          ref: const,const         rows: 1        Extra: Using where1 row in set (0.00 sec

对于C选项

只用到c1索引,因为group by c3,c2,无法利用c2,c3索引

mysql> explain select * from t4 where c1=1 and c4=2 group by c3,c2 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: refpossible_keys: c1234          key: c1234      key_len: 1 #只用到c1,因为先用c4后用c2,c3分组,导致c2,c3索引没发挥作用,c4也接不上          ref: const         rows: 1        Extra: Using where; Using temporary; Using filesort1 row in set (0.00 sec
mysql> explain select * from t4 where c1=1 and c4=2 group by c2,c3 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: refpossible_keys: c1234          key: c1234      key_len: 1          ref: const         rows: 1        Extra: Using where1 row in set (0.00 sec)

Using temporary表示由于排序没有走索引,创建了一个内存临时表

对于D选项

C1确定的基础上,c2是有序的,c2之下c3是有序的,因此c2,c3发挥排序的作用,因此,没用到filesort(文件排序,没用到索引排序)

mysql> explain select * from t4 where c1=1 and c5=2 order by c2,c3 \G  *************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: refpossible_keys: c1234          key: c1234      key_len: 1          ref: const         rows: 1        Extra: Using where1 row in set (0.00 sec)

对于E选项

这一句等价select * from t4 where c1=1 and c2=3 and c5=2 order by c3;

因为c2的值即是固定的,参与排序时并不考虑

mysql> explain select * from t4 where c1=1 and c2=3 and c5=2 order by c2,c3 \G*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: t4         type: refpossible_keys: c1234          key: c1234      key_len: 2          ref: const,const         rows: 1        Extra: Using where1 row in set (0.00 sec)

上面就是一个比较经典的左前缀的匹配案例,因此我们在工作中应该在经常使用的列上加索引

 四、主键索引解决分页问题

第1页:select * from usr limit 0,10;第2页:select * from usr limit 10,10;第3页:......第2000010页select * from usr limit 2000000,10;越往后查询,需要的时间约长,是因为越往后查,全文扫描查询,会去数据表中扫描查询。mysql> select * from usr limit 2000000,10;+---------+------+--------+--------------------+| id      | name | gender | email              |+---------+------+--------+--------------------+| 2000000 | jack | m      | xxxx2000000@qq.com || 2000001 | jack | m      | xxxx2000001@qq.com || 2000002 | jack | m      | xxxx2000002@qq.com || 2000003 | jack | m      | xxxx2000003@qq.com || 2000004 | jack | m      | xxxx2000004@qq.com || 2000005 | jack | m      | xxxx2000005@qq.com || 2000006 | jack | m      | xxxx2000006@qq.com || 2000007 | jack | m      | xxxx2000007@qq.com || 2000008 | jack | m      | xxxx2000008@qq.com || 2000009 | jack | m      | xxxx2000009@qq.com |+---------+------+--------+--------------------+10 rows in set (1.59 sec)
(1)只有上一页和下一页        做一个记录:记录当前页的最大id或最小id        下一页:        select * from usr where id>max_id limit 10;        上一页:        select * from usr where id
pre_max_id limit (cur_max_id-pre_max_id)*10) as A order by A.id desc limit 10 );mysql> select * from usr where id>=2000000 limit 10;+---------+------+--------+--------------------+| id | name | gender | email |+---------+------+--------+--------------------+| 2000000 | jack | m | xxxx2000000@qq.com || 2000001 | jack | m | xxxx2000001@qq.com || 2000002 | jack | m | xxxx2000002@qq.com || 2000003 | jack | m | xxxx2000003@qq.com || 2000004 | jack | m | xxxx2000004@qq.com || 2000005 | jack | m | xxxx2000005@qq.com || 2000006 | jack | m | xxxx2000006@qq.com || 2000007 | jack | m | xxxx2000007@qq.com || 2000008 | jack | m | xxxx2000008@qq.com || 2000009 | jack | m | xxxx2000009@qq.com |+---------+------+--------+--------------------+10 rows in set (0.00 sec)mysql> select * from usr where id<2000000 order by id desc limit 10;+---------+------+--------+--------------------+| id | name | gender | email |+---------+------+--------+--------------------+| 1999999 | jack | m | xxxx1999999@qq.com || 1999998 | jack | m | xxxx1999998@qq.com || 1999997 | jack | m | xxxx1999997@qq.com || 1999996 | jack | m | xxxx1999996@qq.com || 1999995 | jack | m | xxxx1999995@qq.com || 1999994 | jack | m | xxxx1999994@qq.com || 1999993 | jack | m | xxxx1999993@qq.com || 1999992 | jack | m | xxxx1999992@qq.com || 1999991 | jack | m | xxxx1999991@qq.com || 1999990 | jack | m | xxxx1999990@qq.com |+---------+------+--------+--------------------+10 rows in set (0.01 sec)

 

转载于:https://www.cnblogs.com/angelyan/p/11417304.html

你可能感兴趣的文章
like tp
查看>>
posix多线程有感--线程高级编程(线程属性函数总结)(代码)
查看>>
spring-使用MyEcilpse创建demo
查看>>
DCDC(4.5V to 23V -3.3V)
查看>>
kettle导数到user_用于left join_20160928
查看>>
activity 保存数据
查看>>
typescript深copy和浅copy
查看>>
linux下的静态库与动态库详解
查看>>
hbuilder调底层运用,多张图片上传
查看>>
较快的maven的settings.xml文件
查看>>
Git之初体验 持续更新
查看>>
随手练——HDU 5015 矩阵快速幂
查看>>
Maven之setting.xml配置文件详解
查看>>
SDK目录结构
查看>>
malloc() & free()
查看>>
HDU 2063 过山车
查看>>
高精度1--加法
查看>>
String比较
查看>>
Django之Models
查看>>
CSS 透明度级别 及 背景透明
查看>>