在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 563428 点 威望 12 点 阅读权限 255 积分 174251 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
/ w& s/ s' W. F! T mysql索引和explain的详解 索引原理分析
! q! m0 V6 @8 ~* j" ` % ?. h4 [. M: a! m
索引存储结构* ]% `: r# W; [, k- x
索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引$ H3 M8 Q; X% Q
MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
0 f; u4 q3 n+ V2 [* J Q MEMORY/HEAP存储引擎:支持HASH和BTREE索引4 K5 `: e* M& b6 E, B& K+ ~$ W) k/ |
4 i4 v. |3 x$ j
B树图示3 W* j, d+ a- \( l( t, X
3 C5 x2 N% h7 \ B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
% M1 g* H* G+ Q+ `5 r1 ^% p 0 n7 p6 }1 E+ }" V3 z' q# e
# ~: k2 o( P- v9 b8 N; @7 U
. {+ M3 p9 U1 u4 n6 m8 [8 a 8 L( s5 o: Z. _3 H5 g! @# S
B树和B+树的区别:
! u9 y& I- H9 A& N$ i* t1 } B树和B+树的最大区别在于非叶子节点是否存储数据的问题
0 I8 L- z8 i3 `& s
^2 G$ B8 b/ ~9 n0 s$ i+ [ 在结构上:
( p- a6 z, [0 n2 _% @. g (1) B树是非也只节点和叶子节点都会存储数据。: N8 S6 D% V# t+ [
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。, U' ^0 q* M6 c G
" c x+ ]. _+ v% L; m, ]6 s
在性能上:9 T- S* u0 H; U P# t
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。/ ~: B9 z; ^: {3 v
(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。
) X7 }# o- A$ g! ]6 r0 ` 3 a" |8 E' j; {$ j3 q2 ]; Q6 @
聚集索引(MyISAM)9 a8 u6 l, l, F0 H+ ~
B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集( e( w4 T& _$ h
索引。
. o R- E# b# W0 v- [. c 聚集索引包含主键索引和辅助索引都会存储数据指针的值。3 l# x9 }8 U t, r
# n8 ~0 |& i/ v$ H/ _
' ]0 d* q! y& |( I$ ?& [
) h# p. }. r- _
辅助索引(次要索引)
% V" v, }7 S0 F7 m5 M1 z 在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的, ! z, K" q) G7 _* \" i9 [7 A2 `
而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示 $ l2 G# S0 t! ]0 N! Z. E
" W2 v- L4 _. D8 _ 同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。
- d" Z H6 U9 N$ p8 T
1 c0 |+ a0 }8 h% K9 V1 e; N5 V! D 聚集索引(InnoDB)/ G- Y- T5 G0 ]8 i/ f) O9 O' x
' m( p/ |" \# f6 @% b
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。' z3 o" a% }+ b+ d$ l
辅助索引只会存储主键值: N. P) u9 k9 e4 S4 R4 V% N7 O! {
如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
% r: f- o, p9 j
% H5 s5 r$ U$ R, V" _5 F M. J' e 主键索引" u, \: d) }1 t' t
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
) c" z4 R" o9 b% W; f7 r$ g8 u 唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。
- a" B; Z5 M3 @6 h; H2 @
' M5 r: l6 s& B3 Y6 b
. e9 r$ T, W: E/ T) q ) K& [$ }% C2 `: ~" l
% h( e/ a% l, \) r
上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
) ]- p" I% b& p3 B
8 k# o, m/ @! `% a% \1 p
- m5 ~: @3 X* Q" i
5 x" }! m# T- r
' b. }8 x+ t8 j
1 T8 A' J4 D, M3 s8 ~8 Y+ ]" }
) D. d# b4 t$ F8 X1 Q' d- D mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。/ c; D! }% W2 o# I9 c* h2 x$ ]' Z
/ C7 U# o9 Y- V; ]- H& j9 j) z
explain的详解
* {0 J. b {4 g9 [$ w
- _* q# c* {$ \( Y" ?* ~! z 参数说明:& q8 `& f# O- \+ q2 S2 V8 l
explain后会出现十列数据,下面将介绍这下面的十列数据。3 ?" h$ w" q( h8 i3 u: b
8 [( R9 G! I0 c. U. Q$ P. L
id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra+ R- X7 T( N, I/ @7 ]. x% W
) U6 X) x$ P! X, R$ A/ m
先附上案例表:# W2 ~9 e7 Q% R' m3 }: ]
3 Y ?& P( ^; X. O0 |2 p
CREATE TABLE `taddr` (
2 L# J8 Y2 \3 Z3 ~3 Z3 J3 K `id` int(11) NOT NULL AUTO_INCREMENT,6 [: ]$ n( ~0 V# ]* G0 t9 Q
`country` varchar(100) DEFAULT '',8 y& ?* m5 y: g& C* |" N9 _7 h
`province` varchar(100) DEFAULT '',
! _! k4 o9 K% q2 A" F2 U' q3 p0 _% ] PRIMARY KEY (`id`)
$ |/ N# A1 |: b- o/ t ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8# m0 m- u0 P% v1 I G! l
% c' S4 W" L( w0 c
CREATE TABLE `user` (
& H3 O% M5 L' _; x7 E `id` int(11) NOT NULL AUTO_INCREMENT,& m1 ?+ L& p7 T
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,- q, _& r" _) R" d# {8 O8 S1 E
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,1 | p2 F8 F7 Q" d+ D$ L, J1 ]/ j
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
) U% {; k- \( z) a5 w4 n6 L `addr_id` int(11) NULL DEFAULT NULL,
* @! `! ?2 {6 B& [/ s PRIMARY KEY (`id`) USING BTREE,
3 s6 h. t/ o$ K6 J) e+ U/ D INDEX `addr_id`(`addr_id`) USING BTREE
6 v0 q, U6 Z8 f9 `* k ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
/ [) L3 }- e# A
2 E1 ^% }" r0 L! N* R . G; S; v4 l; {! m, F& v
CREATE TABLE `type_time` (
- z2 {; X7 y6 C1 H5 m `id` int(11) NOT NULL AUTO_INCREMENT," j; H. p. A+ Z/ x+ M$ S9 `- e
`time` varchar(255) DEFAULT '[]',
3 U& G& C9 x3 a; v `name` varchar(100) DEFAULT '',
4 j: m- Y" b/ e3 W. a+ ` PRIMARY KEY (`id`),
+ Q- r0 ~+ Z: |( W% G5 X INDEX `name_time_index`(`name`,`time`) USING BTREE! V; s7 c2 {* O X
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8$ q. F1 F( P! J- p" r: d
' o# r9 t4 d- [' g3 l" I7 T8 f 一、id7 v- R8 p) V( A* w5 t$ c1 g
每个 SELECT语句都会自动分配的一个唯一标识符.
# Y! g. F) g/ _$ i& L& ]1 J3 f5 t 表示查询中操作表的顺序,有三种情况:
/ a: s5 L. }: Z7 B- l' i id相同:执行顺序由上到下4 k% U' e& {; r
id不同:如果是子查询,id号会自增,id越大,优先级越高。+ {9 m3 c4 Q9 P* E/ o' B
id相同的不同的同时存在4 u; H7 r+ z2 j7 p
id列为null的就表示这是一个结果集,不需要使用它来进行查询。+ ?3 n( r6 G3 w
' j0 E9 N" f$ v- U. }! R
二、select_type
6 b: D* y1 a$ W& S& Y; U! j . E: Y3 x' L( e5 g$ y- N) M6 J: b- a
查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询+ G& u$ d q0 [4 @, A3 W
/ Q5 [' b2 q" h7 t2 h6 i 2.1、simple# F& Y9 {6 z: S c, X
表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple/ U4 Y% I/ W; W" \1 ]5 Z( |
8 Q8 _4 P+ {/ D& Q EXPLAIN select * from user$ z! B2 y2 V6 [
i, D0 D8 k5 X, s. F
, E- s+ Z: u3 b# [8 w
: q( {, M7 R2 q7 ^( g
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
% K7 H x( C: K. g* h1 e
: g# S1 @5 z) M
1 O0 U9 {5 V9 U0 ]: o! N) P 2.2 primary
, M, y/ e' V' A* b0 v, D; ? 一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
& E' e" f; r( E! |5 v
# o! }, o1 a, @ explain select * from taddr t inner join (
7 _* [, t+ f- z) G2 ^0 T0 f select addr_id from user ) u on t.id=u.addr_id* `! \3 d1 X4 ]- d Q
- ~( s6 b- D8 H& V, C3 _7 o explain select * from user u where u.addr_id =1q & b) b, w" w4 ?4 V
union all
* A! i% V" N' ^& I- r3 R/ P select * from user u where u.addr_id =2
t+ h5 T3 C$ o( x2 W' _- N! V9 P/ L
& S" n5 b; d+ t% |2 Q' s! E
7 l: c B& k! T2 k6 h0 u) G: T 2.3 subquery
5 K7 K4 }, P0 T% u# |7 a- Q 除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
9 R) p. A9 m. }# u $ i; b1 t2 A" Z, D
2.4 dependent subquery
- t- C" j' E+ m( S & p* ?1 g, {/ v5 ]
与dependent union类似,表示这个subquery的查询要受到外部表查询的影响
5 q! `" G- A! N1 @ 6 b; W% T/ Q( R: J' c1 O
explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
/ |" g% m" r! U+ v. E; i1 y1 H0 p* l
, F' |* R2 `4 h' i4 h3 e+ Y) B4 `
2.5 union
6 _; A7 l* y1 g* P4 W: H* e- a union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
, C2 n1 l/ w; p; J" [ ' O8 T) y9 v1 {% p! A/ ]& m$ W0 o
三、table& y+ q' E: C1 Q+ S4 a- W9 x! L
显示的查询表名,如果查询使用了别名,那么这里显示的是别名6 h" W5 j% t5 F) |( z( S
如果不涉及对数据表的操作,那么这显示为null
% x2 E* D, J( _3 _8 ] 如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
5 F! ]# G ^2 \; r4 Q4 G5 Y 如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。# N) D# T8 C3 R
' c! e5 J" t6 T/ j 四、type
2 N4 S3 J* M5 S3 K8 w0 X n, x
; j( Y" V& c1 N- o( H) X& z8 ~ 依次从好到差:, R, \! {( c: v* H Z& {
system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
|, \$ R+ Z% M5 J, |/ y7 q index_subquery,range,index_merge,index,ALL
8 _0 _& o$ s4 o , O$ O9 m" M8 x1 |, H( t' R
除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引' Z0 c8 {! f6 r, c2 l# l+ h7 L
" F; Q2 Z( b0 b: k, E2 C 4、1 system
; P z; m% i% Q6 f# m# J+ [7 J 表中只有一行数据或者是空表。0 H0 O T6 Z2 d( Z5 e0 \
# G, x5 c; M! T1 a/ a8 F 4、2const
/ t' L2 |) z9 o* Y) _9 N/ } 使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
& C3 ?; c$ b/ d4 V/ u- z7 n
- r% ]; `( k6 }6 d, P 4、3 eq_ref
' N, r. A" G$ o. w 关键字:连接字段主键或者唯一性索引。
( w+ p, Y& A3 e 此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.* I1 I7 t. _' \# o: s
! S; J+ v {5 q7 C7 p/ D. N7 F, h
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id: P2 b& W3 y8 Q% w5 o. W
$ d. ], r2 g, \# K) d8 {8 T* n- ?
1 X |" @9 V2 S% ] C& c0 D. U% p
: [# p4 A+ i! ] {3 r# l' g 3 ?" i C, H! p3 U0 l# g% C
* G6 C' M! O; C4 N: D
4、4 ref
( z9 I/ ~* \3 s3 d, v 针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
1 T7 G" D+ N, G5 p& ]1 J' O& \8 q
0 D% l [; g4 ^) N, ` 4.5 fulltext
. N% o5 ?9 j. x% f( `% B, |: m/ s; | 全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
8 G. k+ K2 C8 F; N* H6 y# p" {/ z + K6 w3 A8 u' f0 c- [1 ^
4、6 unique_subquery
4 }' Z6 [ }; r" D* @1 c- m8 O& b 用于where中的in形式子查询,子查询返回不重复值唯一值
2 s" P7 F; s" U: F% E7 } - r/ _4 r3 ]5 N$ M6 V2 a
4、7 index_subquery
/ y+ i( q8 e+ ^, X( o- [ 用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
5 I! W0 U$ G# X5 w
6 }! F, V8 o5 v) |% ` 4、8 range3 g) s8 c' D" k3 ]: |( _3 j
索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。
1 v" l9 h8 j! Y2 a5 p
1 d K# C: ]6 m+ K explain select * from type_time a inner join (2 u. `" \. m% V( T2 l
select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id: V: c' w( A) E! v- t
$ l7 u+ J2 e$ ~ E$ p
6 [- j; c6 b' H, d1 [% s
; ~. |, R' h- W. G" \ - C# c t2 k5 ]# L) t( u0 k) V
4、9 index0 z# E- a' E4 l! f
键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。7 e- |7 `4 e k9 N
索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
6 x7 Q: T; `/ D & a$ u: O$ n3 j2 U
explain select * from user group by addr_id& \& y! p4 D4 i$ i
5 Q! N5 |4 P8 a
% L$ ], |$ d0 H" a8 `
% M: P2 ^# j' W- |+ G! n
& l+ G4 [. U! h8 G
" p; i: E6 g* l5 P; E" H9 }, m# t
explain select addr_id from user
- r* Q8 C2 t( [ |& @
5 Y7 f' v3 `3 \: r
( t4 c4 ?, G8 L; s; Q
3 ]- I+ F% p) O+ l
( d" h# R% }5 e# }- P 4、10 all, z$ a* W; @% r. Z: n3 Z
这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。" L( k; I. v$ s2 b4 u3 \
9 v/ d$ B" j: V/ q# c! ~' w" r0 J 五、possible_keys% o: k# C6 J6 `' I1 {' h
. q! Z1 h2 ^ v( H$ A, i$ A 此次查询中可能选用的索引,一个或多个% W' @. u6 Z' t% G, A" |) L
4 ~4 w/ {3 X! u5 Y; m! `
六、key
- n$ T% L7 E+ {$ B: h4 R. H+ r 查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
% }8 Q T# Y3 N6 r5 f" H m 7 B! ~" [' b' n2 M1 ?" f
七、key_len) y- g! V( ^) j" }. d
% Q" i3 v- z% C$ i( E$ \! } d 用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查( P( L. P0 [8 g# R1 g
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
. n# N/ a2 ^% t5 j/ O: U( _) _ 另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。: n# T" K& Q6 v4 Q& T1 y
explain select id from type_time where name =‘2’ 用到长度303
2 \$ y& u/ L' J2 @6 Z! f/ r" F7 B ) y. Y; q" c6 _% q2 ^" a2 k
; o0 w9 W5 e6 {# l: j' {
explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071
: z- e4 J7 F$ n x: @" l + ]' [$ Z- u% l- }+ Z. S
9 y9 c/ A- D/ T; {' v! E
+ s6 `# \2 z* R9 v% ]5 c: U 八、ref
! r/ m) P' S3 r. @ M, [% j* I 如果是使用的常数等值查询,这里会显示const
% T* z3 K" w2 y 如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段5 q. k; v, _- l" X
如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func6 z1 L: B* O4 K+ k1 x1 ]3 ?8 V) T' h
- d! P0 K0 v# T! r; k; u+ @9 x5 E
九、rows/ C4 t8 j8 |+ I4 Q" w) I3 i/ A
这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
" z: ^" b+ }- P ( ~+ m; C- O. P1 |9 K8 B- I
十、extra
7 i! i- s2 m2 }% M 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:
6 U$ f' `, q, Q# G: v
, ]( D" h( d: |# e# j/ S 10、1 using temporary K& c# \0 X6 w6 v& d0 o- W6 ]
表示使用了临时表存储中间结果。
1 e2 z/ h) i2 P' k# f6 k1 B6 c9 I MySQL在对查询结果order by和group by时使用临时表- b: z2 _ a6 M& W/ ^+ u& N# n0 Z
临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,4 O( z% m$ X3 G0 ]" o
used_tmp_table,used_tmp_disk_table才能看出来。
# y, D5 \) x0 _% |6 s5 t , Q& K4 u, ~5 K: X7 ]/ |) u7 y# Q
explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
' X% ^( F$ t6 ?, j. X* | 3 h2 L% l2 q$ X- k/ J8 d, A* G F7 @
# h( S$ ^3 l6 G- _& b, @; g + B9 R# F3 \9 H* P* K+ j$ T
10、2 using filesort6 b* X' R" G$ G# N F9 `
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
( x( S* v8 N8 ~+ q" x
6 R, o; k, L0 R; J9 B/ r 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。
& I* E/ Q- m4 v8 n% n MySQL中无法利索引索引完成的排序操作称为“文件排序“
' _* E/ b' N; s0 \, d 0 ~, }/ T0 I4 U* m# I% J9 g: h
10、3 using index
! e! r( g5 u2 E7 ?- f6 p 查询时不需要回表查询,直接通过索引就可以获取查询的数据。
$ d, X6 O: a6 X7 c8 u 表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不1 |$ g; s: d; o! d) h* P! m3 J3 k
错。
" P9 b3 O" Q$ L* D) `3 S 如果同时出现Using Where ,说明索引被用来执行查找索引键值
0 U+ S, H5 R& y 如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。( v- ~5 R$ J- W+ J& u
3 q% @- z N( _9 C& L6 Z 这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。
{% Q( ^' @2 G/ P; K8 D2 |# P ————————————————& S* [. @+ ~; h: l% Q/ `- {
版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。' p% x: H$ c6 E4 c; u
原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629
: j+ h/ k9 P4 N8 I# E. d5 ]0 o% V
" }' n' z2 K6 i. N
+ x7 d n6 L# l$ j% ?% q% ^4 I) t
zan