在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 564663 点 威望 12 点 阅读权限 255 积分 174622 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
) ?' @2 e: _0 I3 w' D# S; P( W
mysql索引和explain的详解 索引原理分析
M4 H* ]& a' J, K 2 F4 d# ?* o- N2 {! E( l Z
索引存储结构
$ z' h4 }4 G! H/ n$ y 索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引
& n6 P- P7 w% M: ^5 N6 [, \ MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换' k2 [+ C% G! s6 i a' [9 W- D
MEMORY/HEAP存储引擎:支持HASH和BTREE索引* j' c* x4 B' P1 Y! { f: n' M% @
8 [8 K) E, a3 a: E! w4 j7 P& I2 D+ J
B树图示
4 K# E- I, r" l( k# z0 ~/ V2 x
8 n0 A# k; U/ A6 T+ d B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。# \. j J3 ?* ~, A6 F+ T* ?
/ u4 Y m" K: I% C; w# d$ s3 z4 ~% N
8 p$ @& k$ B, Q: Z% o 0 I5 Z/ S# ~, \0 N- M
6 n6 `% s8 N' o B树和B+树的区别:& L8 _7 t; d' s, P2 _
B树和B+树的最大区别在于非叶子节点是否存储数据的问题
" e t3 Q$ y8 ~, b0 ?
: g: h6 J; ]! R2 R- e0 L- w5 p0 f" s 在结构上:% {" q) K4 ` V
(1) B树是非也只节点和叶子节点都会存储数据。# I1 `- q8 F! d+ \% y+ }* G
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。% j+ Y/ Q* Z1 M+ ` W s4 J% p) `
/ ]% W: I# Q p- {, d
在性能上:9 y, U" C# G) u# ^4 D& n
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
' y4 L% q& V) N5 B (2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。! {& W$ I) `9 ^$ _$ ]' Q- H) m N1 C
% O7 [9 Z* I w1 u% a7 W9 F' i 聚集索引(MyISAM)
( p, C% H% h, e; E9 L7 O B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
8 e, ~' T) p( `: T 索引。# v4 x( e' G# O+ h
聚集索引包含主键索引和辅助索引都会存储数据指针的值。
2 A' a! B1 y# z7 X 9 s6 v# y& k- L6 k, m
( D( M& W4 m5 u/ r$ X5 i) _4 l- P: m
* R5 ] _! V* {& _& r9 d' A7 |) C
辅助索引(次要索引) 5 k6 h/ B) r& z! Q/ C1 `
在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的, 7 @2 O7 g. o" m
而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示 * Z# l L" K" X1 Z3 d! Q6 I! j
# N" Q# [( D/ _# R( y& ` 同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。, p, e s8 o- s5 r4 U' M
! c# T9 B& W$ h5 n9 J3 t& E7 T 聚集索引(InnoDB)* n% r0 P3 H7 f8 D. I
2 y- @' F% j# D! m5 p( H
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。/ u# h4 G5 B5 m z* d+ M# N8 [
辅助索引只会存储主键值
7 C5 J( z- ]9 w0 \$ F: C" H# B 如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
: `! U7 c- V; p0 D- O 3 R# h. d- [! P/ Z* s! A
主键索引 |' i4 z; l! C+ A
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
. T- Z$ Z% Z2 M! t) e 唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。5 Y* a8 N& m9 i% W A
" T9 O2 E6 _0 ]8 Z8 ~* p% ?4 @ }8 [! x
7 Q- p8 g5 m; \7 @
8 u6 B( K6 m0 F% ^) V9 Y
1 u8 ~* C0 U2 C$ s/ u
上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
; r+ P- {3 x( `' s) r
7 V6 b; _: a* J; ~# _: d6 i
8 J* L1 K- J. d J' Z
2 }' `) V5 [. S9 x: W0 f
; z; X# C- V$ _& V9 ` ^
3 d. B* W# r! R0 v2 h; b/ d1 H ( j7 r4 Z: ?, H3 u, O
mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。+ e; W8 t$ E6 C: L$ R. L. G
. L- i' ^% w. |$ j* Z explain的详解7 u% O& X# o4 z8 S& q0 J( o
$ c1 k( @* [: S% z1 ^, A4 U* u' l
参数说明:
0 R8 i5 W2 Q$ T$ @; o/ O! k explain后会出现十列数据,下面将介绍这下面的十列数据。4 g" w) S' D( n- {; C* H- D
& X" J: g, ~. V. z5 H9 j id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
" p1 F; x5 Z) f9 O0 [. J6 y3 q ) I* J* R8 t) `7 S( g* ]7 O1 K' j
先附上案例表:
. J6 V7 W! b. D4 B i' t3 \
7 g2 j) y% q% F _7 _/ T3 b7 m CREATE TABLE `taddr` (
" Q. f' _/ `. F; D# y7 Y `id` int(11) NOT NULL AUTO_INCREMENT,
" f! h% z7 X- X- D _1 ]8 o1 b `country` varchar(100) DEFAULT '',: w: k& Y/ \" P+ ~. o4 r9 f
`province` varchar(100) DEFAULT '',
; B# m" h$ m* Z: G+ b. @ PRIMARY KEY (`id`), k# x/ @6 \: O2 S6 i P
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
# W" H2 V! k9 _# h8 A % T/ o+ a; M/ v) R7 g+ n K
CREATE TABLE `user` (
) K5 l) n% H/ O9 o `id` int(11) NOT NULL AUTO_INCREMENT,
6 A" w8 j6 [0 t. n `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
1 b3 F# ~' F, Q* ?% G. t0 B% { `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,7 R. ^& t) t. J" r. U
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
: @& ?& m; [5 [" ^+ P$ | `addr_id` int(11) NULL DEFAULT NULL,
/ M9 K" p: E% Y) ^3 V PRIMARY KEY (`id`) USING BTREE,/ K+ ?% U `2 B P/ \. {! [1 d: Y
INDEX `addr_id`(`addr_id`) USING BTREE
* m4 y+ o' W9 ^, g3 X ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;/ h+ |! i' N/ P: G* _2 l
) M$ ]( w1 Q0 K; ^, v3 o4 d
4 b5 r% Q) r$ W CREATE TABLE `type_time` (
( @ l' c) y% G3 I% D `id` int(11) NOT NULL AUTO_INCREMENT,- Z3 _" B& L* S4 t* j+ G8 S
`time` varchar(255) DEFAULT '[]',
' ~/ | S s! Q6 l3 B5 D `name` varchar(100) DEFAULT '',
* U- W I+ _4 n) f( u2 T( n. R PRIMARY KEY (`id`),
+ E6 c% F q1 a) W Q7 P) I INDEX `name_time_index`(`name`,`time`) USING BTREE
- M! C8 C6 Q6 v ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8& r0 e0 e. Z$ d" I9 [9 Q
e& K4 G1 F0 Q. W/ y9 _- |2 c
一、id; i- U$ j; x( A" x9 J0 m0 z
每个 SELECT语句都会自动分配的一个唯一标识符.
8 y( S% Y/ S! o* E; I/ Q6 W2 w* [ 表示查询中操作表的顺序,有三种情况:
& c8 z+ t" H$ g4 O% T6 W, U id相同:执行顺序由上到下
, z5 w( d r8 N5 Q5 B id不同:如果是子查询,id号会自增,id越大,优先级越高。: @& n* X6 r5 \ C
id相同的不同的同时存在/ O3 \, D1 @# H
id列为null的就表示这是一个结果集,不需要使用它来进行查询。: }( r( M2 m9 A$ L! D& c7 ?/ V9 ?
+ N5 y5 G1 z& I' J 二、select_type5 {' }) Q' E2 Q) s
2 j" v2 ?& X4 V y9 K
查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
& y! v3 J0 O6 x3 k& H3 @ 7 f) ]7 E' S; r. l8 k8 x& J3 P
2.1、simple
$ h6 C0 i$ }, A: R" H, s: { 表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
S9 r& P( g# q% `3 x
1 l, K3 s, D* G# k EXPLAIN select * from user1 A& v6 r L0 L1 b& b
- y, r4 W" Q$ z. P- l9 l
; S; @( D3 E9 \2 ~
4 L$ Z9 x5 X. e5 f4 Z EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
4 n a& C/ S/ r: Z- t4 k) D2 Z
1 h( K( \9 z: O0 j6 W 6 f. ]8 p+ T6 d5 B; i4 e
2.2 primary! ?3 N. ~2 T; B: G |- F. e
一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
8 Y3 ^8 q0 H4 M _& |4 b
. @$ b d+ G+ K U: x2 F; a explain select * from taddr t inner join (
6 }+ j# l m: y% h( A) |7 L, b select addr_id from user ) u on t.id=u.addr_id( Y: s y# v8 L8 N4 p: y2 g/ v% [
8 h5 X; O2 @. }! Q5 L& x: T$ v. r explain select * from user u where u.addr_id =1q 5 C1 \) a% h6 I( s/ {% |5 ^4 |% }" W
union all ! O9 O$ v7 ^6 }3 z
select * from user u where u.addr_id =2 : S2 \6 B4 t5 d0 Z7 b, c
2 J0 t% Z, f: m3 C) p' h
8 k. J0 ]1 G: `4 i5 Y; r
2.3 subquery2 r6 H* M( {& n H4 q G/ t
除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery4 a) W' Q7 J# q& `' A! Y) z
6 b# K% z" B( \2 e 2.4 dependent subquery
6 d; j( B l+ e3 F7 V + c7 e" r1 H- X6 J0 i* ]0 ~
与dependent union类似,表示这个subquery的查询要受到外部表查询的影响$ k, f W# e7 L$ E. K# W: a# R6 t
( w* U+ ~- F2 j! { x2 m explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
4 c+ y' p2 C. g6 m' D
8 ~' T: S& ?, {% {6 [: ^
2.5 union1 h/ N5 a+ o4 M$ ] p
union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
! L- k3 x& t" d# W
) v! [0 _! Y% S5 o 三、table
5 ]5 Q# f+ k. s L0 y8 e 显示的查询表名,如果查询使用了别名,那么这里显示的是别名
7 R9 x0 t! ^# |2 Z9 L 如果不涉及对数据表的操作,那么这显示为null
; a5 D! I) L- s# @+ { 如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。# I8 t( O0 A0 `" ~ q3 L8 q" t
如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。- A- o1 |! X3 _& ?/ _8 l+ H
; e. G& Y7 b# @
四、type6 ^6 \7 }; c4 q- u& X8 o" g
5 A" z" A4 ]0 S0 Y1 B% o1 k
依次从好到差:' o1 E0 d; k; P- |' e
system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
$ I; z C8 Z& A1 c1 H* |0 i index_subquery,range,index_merge,index,ALL
# K; e* s- p: I. p$ v# O3 U9 f) s
9 n5 v" M/ H& k' i& _/ C8 B9 u 除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引8 ~5 Q+ D1 Q1 `3 Z! d, Y$ \
" ~8 g6 M1 H# j( E' Y
4、1 system
# E$ O3 m9 S7 r1 C4 h6 A* K 表中只有一行数据或者是空表。
) K: o* B6 R2 |( E* @: R; d* m ) \& H" A& w+ ]6 q4 E- b; w; u
4、2const- Q) w/ t) K: K" v2 S7 A
使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
* P% I' }6 L4 n
* k/ d' Z; r! g' m) M 4、3 eq_ref
2 E" k" U; O" ~ a6 _8 R# ~ 关键字:连接字段主键或者唯一性索引。( Y5 U+ {; J2 ^0 O& s
此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.. L8 a7 F) d1 d* A/ R( ]5 O+ R) y% m
, n3 Y! {% {% O& c3 F+ z
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id' d" g2 _( e) d' J! I
; U/ y# o/ A( k
( [' u0 J' h& N( p( T
! K5 o+ n4 G' U0 P
! ]4 Z! F9 T- F5 x 3 H) l3 J' P( ~+ g- Z w# ^. ^
4、4 ref2 @0 S' E. y: @1 U @% R
针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
2 f' W, E3 T( H& }7 A+ E5 c
2 {9 s+ H [5 E' h4 T9 b 4.5 fulltext
% {# J4 _! E/ w3 [- o 全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引+ U) l1 O# k; L1 Y3 q4 u
! \5 q, X) ^1 J- U, ~$ ]! `9 b9 |$ N- H
4、6 unique_subquery+ ^) k& ^- V K [2 T" c% Z1 @1 S
用于where中的in形式子查询,子查询返回不重复值唯一值
3 z7 P1 [1 S1 y( u! @5 }7 q 3 G5 v! ^5 s k+ a
4、7 index_subquery
. z/ R$ {% {7 s0 c- g/ G 用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。2 \& `& X4 F2 e: J
! N3 c1 C. i6 S7 c% n' Y2 ?% f
4、8 range
7 {1 \5 `8 g+ x/ p 索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。 |6 _: q! w2 N
/ d: w/ a8 o( z explain select * from type_time a inner join (
9 l/ d% ], s# h/ ]7 E& l select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id7 x/ O& f; ^& J2 l& g- _. z7 j
. j$ O* x8 F5 X5 a3 F( T2 v
) ?* |5 H0 {5 [3 z5 ~' |* {5 Q
- M4 l6 P" @1 V6 K/ e$ i7 a
; c& Y5 t; h7 ^! @* U3 f
4、9 index
5 f7 ]7 D, q+ A" F4 s 键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。; ~; `! c& \. U7 l- T3 N
索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
! L i' ]' w& x7 A6 m3 r4 W ' B S9 I# Q! o/ \) F. K' G( y
explain select * from user group by addr_id8 x# o5 S1 ~% ?: } b+ u
7 D' C7 [1 J5 z9 Y / ?6 G2 b0 I/ I5 K
; Y0 u& p) X1 R) x9 a
; E$ L5 x# f* u3 o0 p4 G * S1 i# n Q; u. z2 a, C
explain select addr_id from user
9 p0 ~' `2 u0 x0 t' h8 [
* I/ b- {0 W7 u! o
- \* W5 M* `6 O2 E p( [0 U2 }, w }0 j) @' X
; X) ^+ m. l8 W3 [- C. y) g
4、10 all/ w+ L- Z O6 g4 U) v( Z% D5 r0 G" [
这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
) j8 n. R8 }& y; X 0 v& H. T+ ?! o, ^+ [
五、possible_keys1 `& Q) I1 t5 h" \# j4 p8 r6 V
0 I( o% _# J! ^5 E) ~. S3 s
此次查询中可能选用的索引,一个或多个
% ]8 _1 [+ j0 z2 @
/ i0 e }8 O8 L* ^( v 六、key
5 X+ }. x1 s* A9 g8 e0 Y 查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
a$ j3 l% {( I( V8 @$ _
8 u; g4 ^2 r. U5 O ^ 七、key_len0 w0 M5 N. B( A. m, Y
4 r- ?: X6 s% \+ F 用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查2 H. Y9 X# h: _6 s" V7 c6 L
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。3 t* A+ X: d7 a. R
另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。: ]; H( t) ~1 `! [
explain select id from type_time where name =‘2’ 用到长度303
. g" W# R6 h& `# ~, s
& n& N7 F& ?+ S
4 I, r5 N: J/ L5 @& h" C3 y/ } explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071 2 X4 _% w0 W3 X4 c1 J5 [
3 A; V: `* R' Y# I
% Z/ _7 R, z2 W" m$ f4 w B+ a
& d* b0 z: I! r3 F9 d7 O& k- z- u 八、ref6 ~7 }- _& K9 N G: G$ K6 @ Y
如果是使用的常数等值查询,这里会显示const# g/ G* A8 k0 v
如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段* c; Y. q& P; D5 r/ m* ~: b( ^
如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func& A+ v* T/ P: Y
/ e( |, a' z! I7 ]( x' S4 n* K+ _ 九、rows
8 J" ~6 Q' ^ c& K4 G% W$ e: ?! \( M* { 这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
0 l& @, Z& v3 `: x- `* o m% c+ l/ j9 e
十、extra
3 U# b9 u6 U F! ]7 g; s# s 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:2 T" U8 j9 d: d- k( L" j
/ M5 I1 [# d- X: M& r
10、1 using temporary5 a5 @, K& ]2 J. T( T
表示使用了临时表存储中间结果。
1 j3 `9 R$ p: S1 b0 s% `3 t( R MySQL在对查询结果order by和group by时使用临时表7 ~4 M7 N: U O* ]: p9 o
临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量, q7 o" X& u/ X( p
used_tmp_table,used_tmp_disk_table才能看出来。
$ A" H' \1 h, y" X2 e3 ]( C
' k& X- u# Y( q7 X5 i4 s explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
% t1 | S& _. `! v) m) p0 e 9 K# k9 \$ I) _1 G( |; H$ M
3 E! w- t! s3 j) I
- `, F7 @/ P7 e- ~' Y$ H 10、2 using filesort. c% h% j' {+ {$ e* k3 V) w" T
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
4 Y8 r1 M9 H* ]$ A H/ e
" c& m4 Z7 S3 A: F" O' _ 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。
* ^0 Z$ v2 r( E. N1 K MySQL中无法利索引索引完成的排序操作称为“文件排序“
1 t. ?; i6 N0 A1 f
; C: a/ T! M! M' ? 10、3 using index! F5 ?) w) B' r3 m- c
查询时不需要回表查询,直接通过索引就可以获取查询的数据。
% z6 v% u. G' f# U: F' Z 表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
0 ]/ U9 R/ M4 Z( M 错。
5 v8 c J! N6 ~# t! t; L; s 如果同时出现Using Where ,说明索引被用来执行查找索引键值2 a+ X& W0 H: b0 u% k6 k, b
如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。9 O9 `7 e/ t& o* ]
3 q6 c* g6 z, ]! ^% F 这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。0 H* M' b. G" a" L3 g
————————————————! k. _& W3 t" D; S0 W
版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
( |# S4 ?/ v( D# W+ A4 {1 @ 原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629/ ?' _+ N- z3 X
( q! B4 X/ {2 P% @6 r- n2 U4 p
, e' \; D/ s' t+ Y7 T
zan