在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 559570 点 威望 12 点 阅读权限 255 积分 173244 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 18 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
4 C- N# F3 u) ?7 } K" ^, @# u mysql索引和explain的详解 索引原理分析
. Y, u6 G. `1 ] w
' }/ B1 {* C% p9 D8 { 索引存储结构( K$ O; t1 F( M. O; P3 ?7 P$ X
索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引 L% {6 I. a, H7 W
MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
+ s1 ^: B0 N2 X' A0 C MEMORY/HEAP存储引擎:支持HASH和BTREE索引
3 q6 P: R- S3 W( M- b
+ r/ h8 H2 q; Z% p* a1 _ B树图示- b! S& H6 E8 h0 w* B
; ~, Z) ^+ n; S7 Y+ r B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
8 t* y' j( G9 P4 r , }3 h0 W# [# X6 v1 R( \7 s% H
; D2 b- s0 r8 n" q% ]: D
" z4 ~0 g& n8 B3 R
- e( X2 |! ?; h" L B树和B+树的区别:
; d/ [. |& h, U B树和B+树的最大区别在于非叶子节点是否存储数据的问题4 [! E& N5 L4 W5 n7 j; K
$ d9 n; e; N, D1 ?# p
在结构上:) ]- N ]/ h. Q
(1) B树是非也只节点和叶子节点都会存储数据。% M* S+ ?5 ^2 J
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。
$ a; i% }1 F- B6 ]' c& _
, V' U: x2 P+ \# q5 S 在性能上:" A% V% u' U$ E
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
8 G' R( D9 c6 @% U8 J4 _2 x (2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。4 r5 K' G4 w3 U' U: K0 Y; W
% f4 i" v$ A7 u2 W+ X: W
聚集索引(MyISAM)
8 |" C& l2 |# ~' f! I3 @ }* Z B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
+ t: {. ?4 w; m! x- ?: s- _ 索引。5 p* X; C" T% H# t, a2 Z
聚集索引包含主键索引和辅助索引都会存储数据指针的值。2 K5 c+ E& j# D" D/ \# v
- R- }% B5 {& |) L# |' ]
- D0 z1 J: G0 C9 F # o* ^9 O+ _: T6 D W
辅助索引(次要索引) 8 x( E; o6 ^9 c: o, p
在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,
0 W6 `+ W9 i' `0 M# E1 X/ D# b 而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示 - G6 _4 @0 o9 k( z, g2 X3 r
1 W4 |, ^- n+ P' K0 ?8 E0 C1 u& X, f
同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。0 W3 R; \! V6 ?& P5 j, w
y) i! G! f5 f
聚集索引(InnoDB)
' J2 ]6 p- T5 ]" f 3 q9 e- t9 C' P% b4 Z
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。- \) f, P' L' s: E
辅助索引只会存储主键值
# K% ^# j8 Y$ ~* r( s 如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
& h; n2 y9 d c% I5 }, ^3 z i& H 3 [* G. N: [; r: Z# z* Y" [9 M
主键索引
' F* E4 L, H$ u7 u, c2 l, L% ]/ w+ P9 | 1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
/ f" a) ]* H) Q; n+ [8 Y# z# s 唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。( p( D |0 I, t8 k8 f
, ~; G! o" | r4 C7 M ]+ G; a
( @0 k0 u! F/ v% a- j0 ?2 S5 M" X / Q4 D% f/ l' E* s3 W
9 |5 _6 j# [& V& V6 i9 g- l( m* g 上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。 4 n: N3 n& F! D% [0 g- `
# k& {8 y. T" [- H; o1 K
5 s/ n! d+ o1 C, M
D6 x+ N( P# u
: @! _+ k8 ?$ X+ D8 X F
# v2 W# e0 f$ o t5 d" [, R" P
mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。
9 F4 _" C# ~: T; V* i1 f' N " G6 h; |! q+ X% T# M: x
explain的详解
* E& s* v# N) e9 s' d' o0 e
& J: w, k# s& Z/ Q- g* I3 L 参数说明:
1 |. k8 d% i# @0 [: a' x6 q$ J$ { explain后会出现十列数据,下面将介绍这下面的十列数据。/ M; ]8 G* [9 S
5 C" r- r! t3 q g1 C id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
1 ?8 J% m1 }# I* W/ K; X8 Y
0 B& A# d0 b5 ~/ F: d 先附上案例表:3 c3 F6 `% O8 \6 f. k6 u
( h- l1 `5 u4 Q6 X9 w0 f2 O4 s
CREATE TABLE `taddr` (
/ j0 B& d9 _% i: P3 }4 ] `id` int(11) NOT NULL AUTO_INCREMENT,
6 Z+ m. r5 U7 r' P* d e' l* y `country` varchar(100) DEFAULT '',+ k3 G) f* S }
`province` varchar(100) DEFAULT '',
* e: x/ P" J/ t4 m4 ?2 b# g0 g PRIMARY KEY (`id`)) ~# W" |2 ?+ l; u4 C0 E0 E
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8+ p7 L' G" b5 |' t
; }, H1 Z. B! F7 I P
CREATE TABLE `user` (
9 b$ Z: j: i, g' d# I/ k) y- X `id` int(11) NOT NULL AUTO_INCREMENT,5 G) g9 }- T* G1 X0 z
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
6 m( G4 j/ T. s `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,$ J4 |( f) ?" a
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,3 s! q2 d$ I& B |1 W% p; o, f6 I
`addr_id` int(11) NULL DEFAULT NULL,
: R, `: G+ i' V$ W# c- e/ ` PRIMARY KEY (`id`) USING BTREE,
* O! P D- e4 S9 z3 S0 i7 x INDEX `addr_id`(`addr_id`) USING BTREE
5 \; g! ?& A/ f A. A* M1 m ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
$ C6 h* R& V, d
1 J3 R% U3 s4 ? E ; f! U4 C0 O/ @. X3 T
CREATE TABLE `type_time` (( j' _# ~* p4 E9 v/ X
`id` int(11) NOT NULL AUTO_INCREMENT,
- J& _% y+ u, ^1 `# m0 N* ? `time` varchar(255) DEFAULT '[]',
' L6 @$ ?% W" h* l) N+ X* ?2 M `name` varchar(100) DEFAULT '',2 N$ b( a+ l6 s# D/ s5 v) W
PRIMARY KEY (`id`)," k# T( L% Z0 N8 t# m" q" J$ Y
INDEX `name_time_index`(`name`,`time`) USING BTREE/ [# s1 G' J& ^3 L* l/ G$ ~! s& w
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf84 i8 \) x2 e% q* r) Y9 g1 X; k
" O; I h' z: c7 [- E8 H
一、id4 U8 P, Y( R6 {
每个 SELECT语句都会自动分配的一个唯一标识符.9 R$ Q. S4 a' X, P
表示查询中操作表的顺序,有三种情况:4 A: E% M& [% y
id相同:执行顺序由上到下
1 |& F* U- |2 _7 G- q* u id不同:如果是子查询,id号会自增,id越大,优先级越高。
& T; o( p) T/ |" [ id相同的不同的同时存在
. I/ d+ N( g {4 q id列为null的就表示这是一个结果集,不需要使用它来进行查询。
8 s& ^9 m9 L, B3 R5 {2 @) H ( c, e2 p% f7 O
二、select_type2 J9 l/ Z1 K$ k
$ @8 z. {$ z) M6 ^' T0 [, ^ 查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
3 q" I$ e- A' O5 q: K4 x
! l# B9 c# Z; Z6 C6 c6 b4 m* Z1 s m 2.1、simple
' U. \. l: Q* V, | 表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
9 P6 l) G; W" q/ Y7 a$ q# r* |
5 |! g7 }4 H) |6 U* z EXPLAIN select * from user7 J' p0 O+ V" O. M
2 n q; w; G+ {9 V) D6 t( A
! w, [% m5 P- b- p
8 q9 o3 o* o8 I8 O5 S; s% F% p" y EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id * y' ~* v1 i4 I% g. I& Q: y
$ T' ^0 [" H) L1 }/ B! f
: A" w" L7 [4 m+ K7 M1 a3 i
2.2 primary/ h0 B7 Y: E; P3 v4 E
一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
0 S5 Q/ d6 S" I' Z/ N1 W
! v7 W2 Z# P1 v explain select * from taddr t inner join (! O& M& G- B7 }3 O& Q( t2 L2 H9 }
select addr_id from user ) u on t.id=u.addr_id: c p& H; X2 O) z# T, p" a: K5 t4 b
- d& r9 u1 u$ C7 X9 T/ o( j! x explain select * from user u where u.addr_id =1q - C+ Q0 y; `* u' a* b6 D
union all ! ?, |9 P: J1 w7 W/ z) @" \4 B
select * from user u where u.addr_id =2
6 M' B7 k r1 f" N; q" W6 F: Y
+ B/ T, K) Z5 B
/ w( p& L- G% l" F$ p 2.3 subquery
& m6 {$ { r% U. w! l2 h7 e 除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
' z' t2 `) ?& x6 u8 J7 G
4 y4 g. n7 w1 a 2.4 dependent subquery
C$ q3 p4 S% r/ s9 {. V
' b n3 T. ^( f* E! C) w. D 与dependent union类似,表示这个subquery的查询要受到外部表查询的影响( F; n1 R! q$ m( G4 D
0 X( B: R! n7 i7 o explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u) s* O" H9 p5 n9 ?- Y# ^$ ?
% z* d+ t+ D0 `! M4 n
2.5 union9 [$ k9 c" K& F9 H
union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union5 ]* M# |0 T, Z2 ~ D1 r" z/ Z" B
- _1 [, | _: g+ H0 g( u# h( C 三、table
7 G; _& I4 j( ^, n7 M 显示的查询表名,如果查询使用了别名,那么这里显示的是别名
* \$ M7 ?2 y4 E: ]8 d. {: I1 Q 如果不涉及对数据表的操作,那么这显示为null
! t1 \1 w& ]7 N9 O# N: I. ] 如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。! Q$ h7 ?, k8 p, |1 o% e
如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。' i. j' E; e. d* C- y
6 E. z" T) O6 h# `! X( Y 四、type
( R4 W1 u) t @. c8 ~( o- S $ g. V2 w/ F5 g* a2 G4 ]
依次从好到差:" M5 t8 B& h- l" `5 m5 r/ C$ P
system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
6 k. d7 F) C( v7 q1 r M4 V index_subquery,range,index_merge,index,ALL9 m3 b2 a) c" X) P0 S
6 N }+ K. H( @9 n
除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引
+ N7 u; L8 I% @3 E3 H
% E9 k$ G# \9 h% }/ l, F* X 4、1 system
" X8 G$ u2 `% s 表中只有一行数据或者是空表。
! P. k2 c: A+ S# |0 A0 t( n: T" J # L1 n1 S) E0 l: U6 K/ U+ f
4、2const
" R% t5 W7 a* Q3 b 使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
* e7 ~9 s! i& k; m+ c& R& s + j. S: Z& g3 Q8 L/ }- b6 C
4、3 eq_ref
, _" R2 E1 P7 X; W 关键字:连接字段主键或者唯一性索引。8 _0 [6 c+ v" E! [5 X, Q
此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.
q: L) L3 E! v( K0 [/ I+ L0 L- i
! m( r- R5 M6 ], g' r$ @ EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
: J( { v1 s, x) b# g/ \2 U , W1 Y2 `! l$ H7 b, [
; R# E* o. H" C" a* m8 _4 c
! P7 g t/ W$ G! C2 m
& J, X5 P# L! S+ j3 R
& C: O6 `8 ]. Y$ }1 `& Y7 r 4、4 ref
; ~2 t9 k9 v. H- R 针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
& ~: e d' V }( r3 m- D; v# \: O9 r+ U
S5 l5 c. O+ v3 E6 N, u
4.5 fulltext' l& d- F; ~3 i" N1 L5 [, H# x" g3 ?3 z
全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引/ v5 d- s" T- Y& [+ {
2 V# Y. d7 K! N- w3 O2 }. @ 4、6 unique_subquery5 }0 E# j0 H# {" M/ q0 {
用于where中的in形式子查询,子查询返回不重复值唯一值: x- b. p. E! P, X2 \0 q8 x7 [; T
9 @; B+ R# r# C K3 S 4、7 index_subquery
f2 ]1 Y9 f& @ 用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。) g6 ^# `7 r' L" A
/ M8 C. ~' h8 P- C
4、8 range2 ^) v) }3 O& q" {4 P+ r* t! t c
索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。/ t+ R' S) H8 ~! T% C* x& ~ s+ h4 A
/ K+ H% [' u+ C% o! Z explain select * from type_time a inner join (
9 i4 j- x- @5 O" ~/ q select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id
2 F, S. E+ r; T9 P8 ^
% y8 n6 D8 H* D% y 6 U) g4 C7 m/ k' S
: s# W3 x+ g5 X6 c( D- b / y6 u9 U2 h' u9 ]% C1 Q* P
4、9 index
8 g/ g& _( t) G R$ b; \ 键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。1 L/ w8 [) U+ y' d3 W- Y
索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
0 F' b4 u! U1 f5 M) Q 0 F) P8 b$ k" N, o" v
explain select * from user group by addr_id; H4 b# Z3 Z( M: H! ^& c
" O& g9 s. G- b/ u5 Y) j2 P& ?! h) |
$ W: v4 I. [4 Q+ H
6 X6 u3 t3 I. T' P0 Z3 K
0 t" c* L* J% j n
, z& G& C7 r& n/ q( R
explain select addr_id from user$ J2 {0 ^( _% e" a2 o
" N6 a' @: e1 X
: z6 @# N$ y6 H, G+ X
8 Q0 x5 x) |) E2 \
$ z- X8 n0 }: J 4、10 all
) X [2 k; o- k/ ^' K; m 这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
2 R O) q( n( t ' Z, `8 L1 N+ U" L% P& F
五、possible_keys
$ d, r2 U; B, G 7 z4 U7 D* j3 D4 a7 k2 t( ~, l1 f
此次查询中可能选用的索引,一个或多个
, g1 h `- G- ^6 e2 H* | x, Y% \
/ e8 U6 _2 V$ N9 g4 y 六、key' n- v2 q; T. t1 N
查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
: ]. s. e6 J2 e& o- i1 @& f * d1 g9 @6 _$ W9 |0 |. a3 t1 |
七、key_len7 r2 x+ R8 c4 Q4 J, ?& X9 Z
% B, E+ d% l7 \3 T* \" h
用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查
7 S1 g, H& o+ y/ i4 p5 c 询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
% T7 }6 x) I E3 w' O$ z 另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。4 H2 `1 R4 q- J: d( r' ]1 x
explain select id from type_time where name =‘2’ 用到长度303
! Y7 d ^" x* q$ M , |1 {, A+ L" \- }
. f* n/ }5 P$ `; |5 B, O! o) Y3 O) p
explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071
8 e( r1 [5 |( f" s6 t0 t6 w3 x1 K
2 u5 L# n8 K7 x
. Z( F z1 X* S6 k& Y ! g5 o- r, H, ?: t
八、ref
: K7 E$ C* L$ ]0 a 如果是使用的常数等值查询,这里会显示const
5 P- n7 P9 ?" Z/ ]: I 如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段
* ~2 I0 C+ Q$ `/ y& Q 如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func* ^8 K/ i( ~3 C. k! ]* l* l
% T0 k0 O- F) f0 U7 c5 F) k
九、rows- o5 z% [; q' u, i: j* h$ F
这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
/ T/ D M1 f6 W3 y6 v: O% a " n- `% `* W/ L H# Q9 S) @
十、extra
3 {& w4 b, w- ]$ O: F- I) A. D 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:
. ^, p" o1 L( x7 c) q7 x8 O
6 ~- [/ R3 D5 ^' B1 Y 10、1 using temporary- T7 y- c2 v) B
表示使用了临时表存储中间结果。
- O0 b4 h3 D' f+ V) R8 l MySQL在对查询结果order by和group by时使用临时表3 H) k* {9 M. l2 x0 O) f. o; x5 [
临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,
|$ s) m( u4 `& h" l6 c- y- A% _. B used_tmp_table,used_tmp_disk_table才能看出来。* N5 N. J- D, L, W" w- O( P8 I
( C; q2 a+ q3 k0 S explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
2 x3 ? h- X# Z0 c4 ^* z% G
$ R! @5 C; Y% j: m* E
B5 _% Y0 h. l5 ]
5 z# f0 m4 q9 U$ G 10、2 using filesort$ d: u5 e8 g" D# w# o0 d- ~
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
: H& ]: n2 m) F4 f' [3 @
- ?& r: J. e% O4 X 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。# @9 f. _+ v( c* l7 f
MySQL中无法利索引索引完成的排序操作称为“文件排序“. K, g4 {4 z& O
1 s& W0 t* Q4 {! F% A. m 10、3 using index' d1 z" \( N: \$ w( Z5 R7 C5 y
查询时不需要回表查询,直接通过索引就可以获取查询的数据。& x" }( |5 f0 \" Y2 M
表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
1 J U. q0 y* v 错。/ V1 t7 I0 b1 g; _3 C2 F ?
如果同时出现Using Where ,说明索引被用来执行查找索引键值8 a0 |5 _1 M7 ?6 j
如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。
3 B4 ?) i9 i* ^! [5 V7 b+ @ ! A+ K2 w% s _. Y6 n6 e4 r6 R. z
这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。2 I! h4 z+ k6 K9 c+ M
————————————————; `' q4 ~/ a+ P9 f+ F
版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- J% P! ]) G, ^" w1 C* [& ?3 U 原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629
T& z) V2 j( z/ x, M( q. D2 }
" z) o0 N3 U' q : L* ? |8 m9 U% o. N2 Q! ^7 Q
zan