在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 564692 点 威望 12 点 阅读权限 255 积分 174630 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
8 l; f) q- B$ |0 j( H7 W! V mysql索引和explain的详解 索引原理分析
9 \" H3 C ?' l, J4 I6 u _
7 |0 R' j/ i/ E t+ r 索引存储结构. X7 P5 _0 ]' u2 X' [/ @" U
索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引
+ f1 c# R' ]6 H7 T, V5 M MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换7 A( u6 d$ j, `7 K& u! p; Y
MEMORY/HEAP存储引擎:支持HASH和BTREE索引
! t, ]. ?4 Q# ~, @ U ) j0 y' K" O& C: W8 ^* Z8 r
B树图示: |- Y1 F% K s) f% C; M
# L1 e% f4 g1 q9 U: Z. h3 {
B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。2 [% y6 p! |% J8 k( y1 U4 C( r% \& X
; C1 ~1 r5 H% h( x8 h
: w9 L5 E5 s4 @. U1 ~
# X3 x5 ~! {* ?, C, v
% _ b6 X1 X5 Q( y
B树和B+树的区别:
8 R- N: ^8 l" `9 } B树和B+树的最大区别在于非叶子节点是否存储数据的问题
6 G* t9 f" ?4 r7 z9 A6 r/ b: J
8 {+ N+ c( @# e. ]# F& o 在结构上:
7 k4 W& H% ?+ R4 v d (1) B树是非也只节点和叶子节点都会存储数据。, F9 c, R* U* ^% u7 F* k& {
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。0 n- b v$ O5 O& m; S {
8 D" W% F8 l2 N9 a+ p7 [3 u 在性能上:
/ }( b- C5 O/ a2 \0 L$ P2 J (1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。$ \1 N' |# H, z+ c" y& j$ A w
(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。! P. K$ w6 c3 N- h0 \! A& j9 l
: i5 i7 k2 m- z6 Q 聚集索引(MyISAM)0 z: p- M, E- ~0 J
B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集9 {' H2 H3 d1 S
索引。
" K: O6 X# E9 z+ ] 聚集索引包含主键索引和辅助索引都会存储数据指针的值。
6 J, y/ A M/ G
- X2 @0 j/ {0 j0 K
- ?0 i$ T+ r( |9 j# L! C0 N7 D- E# ~" a L " Z% \ P% j; I: j% l% D
辅助索引(次要索引) ) ?; W9 n; v$ N8 n. V
在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,
, r) @# d! X6 T9 O 而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示 + S) u: I2 {( {% `. U% i
+ U5 ~( L# y% k6 P2 G+ ]4 b
同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。
$ y, m- y: v/ V! ]/ B 9 b! A0 a1 J) ~7 U4 s* Z
聚集索引(InnoDB)9 d, [1 s1 k+ P# E# l% {* q/ ]: S
$ _) d1 k; ]# {/ e) A: w2 S
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。6 J! O9 \# J- R7 N" _+ L$ o
辅助索引只会存储主键值) h" U: H; t2 u$ H& N
如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。2 H+ o; x9 B: `3 h: m
( s# R a' k% ^# { 主键索引( c* u$ V8 P' }( a5 G
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
/ s _" Q/ a" I 唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。2 d$ h' }) A& a* n. w+ W# K
) S* @2 X& H% J8 n0 R8 \
2 v" t& m& U3 D" V( M8 d) A
, S4 b- t( J4 h8 p+ P
7 n, E: q9 T" ]7 ~% ]' `$ q 上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
3 u9 c( u. v# }2 Q" y
( n6 e- a& ~) p/ _4 m( S4 j" u + R% y- p+ u* y g0 S) ?( T- u$ b& ?# }
9 |- k: V& ^) S/ s, v- E- E
7 K/ r6 }' T4 a" d2 a7 r- S7 S 4 E! N% }$ M+ p% m; P% \
7 l% M0 n& H7 X: e u0 B mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。
, t/ z: W: x8 i& W5 R
- q5 ~2 R5 j8 G2 J0 u4 C/ X5 N explain的详解1 f6 a7 \+ z% R; n
' q2 E2 W* [1 o }( Q
参数说明:+ k/ A0 |) P5 n/ ]
explain后会出现十列数据,下面将介绍这下面的十列数据。
3 P6 g2 m' W" t# T! m) K
z2 W" F3 F1 w id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
+ e$ y/ t* I/ U - j& y \. {' O; i) ^+ {- ~' E
先附上案例表:! `, K8 f5 D2 k; R
1 T9 s7 _- D5 l
CREATE TABLE `taddr` (! T& |, P, }' q8 @: x0 S
`id` int(11) NOT NULL AUTO_INCREMENT," |4 ~0 B7 v8 ~9 X; V) S2 u+ {4 q0 c
`country` varchar(100) DEFAULT '',
6 X% h6 x$ N! C( S/ a `province` varchar(100) DEFAULT '',' o1 N% X9 w1 e, w4 }8 y8 S
PRIMARY KEY (`id`)
4 `/ e1 a4 d7 g! V V ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
' R, Y) {, s5 m1 j- G% E . `( H) e. F8 S3 h, s; B
CREATE TABLE `user` (! k7 @; [0 G( c+ t4 U
`id` int(11) NOT NULL AUTO_INCREMENT,4 j1 X; B2 @! j* u
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,' Q7 l3 c5 _& @- O/ o8 F( l Z
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,( c' j0 Y6 o5 \$ j( Q8 I0 ?
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
# [( R. [; k# H, N. N `addr_id` int(11) NULL DEFAULT NULL,- I9 H a8 a. x4 N
PRIMARY KEY (`id`) USING BTREE,
- F$ j t! b5 i4 Q" S7 S: K; K+ E INDEX `addr_id`(`addr_id`) USING BTREE
! n9 h6 K4 K5 h* Q9 Q) k- ? ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
% k7 r* X* j* i$ l# g2 B( F: n 1 f* W6 N: r- {- D
2 j, B3 a! t8 Z) M
CREATE TABLE `type_time` (
4 N, j. S; s3 ^. i `id` int(11) NOT NULL AUTO_INCREMENT,
* A3 P5 Y( D7 S$ h& Z R" l `time` varchar(255) DEFAULT '[]',
% U; a; s1 o$ U! P9 m& f `name` varchar(100) DEFAULT '',$ u0 c0 x |" M3 {! J+ t/ w* @7 B9 g
PRIMARY KEY (`id`),
0 z& p/ z8 n, N' t0 }, M INDEX `name_time_index`(`name`,`time`) USING BTREE
* T$ ~& ]( g2 Q, l5 P ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8# f' R0 T q. [; \( b' ?- }( w. y5 P
$ r- T5 e/ P; O# }3 t: C 一、id
( G9 f1 ^. k! N T 每个 SELECT语句都会自动分配的一个唯一标识符./ Q% m9 e$ _6 D4 ~
表示查询中操作表的顺序,有三种情况:- c4 l5 Y. [' q& _
id相同:执行顺序由上到下2 `* w5 _. l& H5 L" h
id不同:如果是子查询,id号会自增,id越大,优先级越高。( N: O* @$ w' E, E+ |5 L
id相同的不同的同时存在- T' |! i5 I0 P$ |
id列为null的就表示这是一个结果集,不需要使用它来进行查询。
: }. w0 ^7 d8 {9 l0 a4 B) Y
3 g9 V( q2 Z: O* p0 h z 二、select_type
3 E; {8 ]# t6 n0 { 4 i q [, ]5 X' e. b9 i9 _0 f
查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
8 S$ o+ s, r6 r6 Q
: _: q9 V4 f) ^' G1 }8 d 2.1、simple: T. o9 _/ b! \6 ]& j$ t
表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple; B6 N& Y' @2 ?" Q: l x
" \0 D! Y- y; @1 w( ? EXPLAIN select * from user% b1 Y& y6 [! I7 J9 D' l
8 r# l. Y' N. ^, U( D8 h
6 v' u/ T1 u3 f h- E! T 1 f$ u1 {! u3 @; p# T |
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id 7 _8 {; A6 N' d, x
+ l8 b& I7 Y( J; E2 f2 y. y. S
4 P% N* U( l/ A& z% ]4 p
2.2 primary
$ V, s$ V2 S9 ~ 一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
1 B3 i, K G' x. O# ?( F 8 w. h1 ^9 J5 C0 y) z9 L
explain select * from taddr t inner join (
4 G# h# e7 n F* M select addr_id from user ) u on t.id=u.addr_id7 H5 P' }" I8 O) k% K6 q S" d2 ~$ H
M U& L5 W9 U1 k* w% w- G explain select * from user u where u.addr_id =1q
. M6 T& G1 e9 ]" Z+ u8 V union all
; d& D6 z p- D9 X- G3 ^: F9 z select * from user u where u.addr_id =2 ( ^3 i) ^1 l" t# | `8 M
# t' Z7 S, s% f1 Z
! O7 z+ r& h6 ^0 v# s7 U/ @ 2.3 subquery
; R# r# P& _- r9 ? 除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
; p' T. A4 @1 j0 B7 ~6 B' k3 t
% O9 }6 L. v, U8 K6 ` 2.4 dependent subquery
5 m: c& s! E7 T8 X
! }( B5 x9 S4 e8 N' y6 d/ I; d9 Y 与dependent union类似,表示这个subquery的查询要受到外部表查询的影响 y5 ~" k9 m& ^' m. I) n- |+ O
6 [9 X: j" @) d) S$ r9 P, P# ?
explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
1 {6 w8 `% e$ V4 M' ~* a( B
$ i* x6 T6 ~, P; w' `% Y 2.5 union8 c" |3 i6 B' c$ ~
union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
m$ q. \/ J0 S. p" v# t+ b- l+ ? % ?7 X, y$ U5 i
三、table
+ H% v# m; h3 m+ K, e! Z/ A9 _ 显示的查询表名,如果查询使用了别名,那么这里显示的是别名
' N5 R' J9 r7 ~ J& z1 u0 t 如果不涉及对数据表的操作,那么这显示为null
' W$ p8 [8 ?, _7 R( W9 d7 U& c 如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
4 S+ O. v4 S* ]9 o' D7 P7 u- `5 A 如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。7 X1 h4 X7 S& |( y5 t6 H8 o
+ |1 |( {& ?) F( H6 t+ J 四、type; u% m4 W4 y& U
( K5 ?0 i- s( G7 g
依次从好到差:
: f, o9 g9 X7 w* r% i system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
6 o3 _0 Q" T+ f4 ~7 O index_subquery,range,index_merge,index,ALL
. c% t0 ~# x* X6 \8 u ]7 e 0 T& t ]7 [& @& R* R
除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引4 W9 {* s$ h+ e
! G7 r5 |! \* l8 @4 C& p
4、1 system
& i" f6 u5 o/ x& j 表中只有一行数据或者是空表。0 [% T) _5 s6 v" b. v( Q1 U
" W& x% g% ^4 J: x$ \+ \4 o
4、2const
( s& ^( J! i! z# {) t5 | 使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。; T# N8 G- O5 m: @& L
( E: X' Z: ] e! n. ]3 c' W% H9 n% i
4、3 eq_ref
+ s7 l: \* ]6 z/ `. L 关键字:连接字段主键或者唯一性索引。
( L& Q) L1 w& n' k' {+ J; | 此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.
/ d; Q1 L$ _6 O' o9 W
) t- s; g E1 M' u& J+ V: J EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id* Q7 q* I5 k! Y5 y% E ?
7 C+ t* a, q5 A# f( Y: ]" h
0 e% e" L% S/ w; ]. a5 {
7 I0 S) m7 r& ?
# C9 g. r2 r5 t4 P0 T4 f- d2 y5 ?8 t+ A ; `' |' `6 l' J
4、4 ref6 M. h# K5 L7 [% m% d
针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
6 I+ u0 I+ D# z3 Q, t# P
6 j- m- q/ b+ G! o6 m+ [* z 4.5 fulltext' {# {' _0 s% e9 q
全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引0 V, K4 d9 Q+ u$ f0 M
0 g& C: o5 @( r 4、6 unique_subquery5 S5 f: I" ^6 k' d3 p
用于where中的in形式子查询,子查询返回不重复值唯一值: F4 s' s! B0 v3 C- v
( a6 |. v- _; F0 A 4、7 index_subquery; Q0 J% h; n& l S2 K+ t a
用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
: F; h; F# ^/ x 7 Q. z+ A* D* t
4、8 range
: J4 I* S- q; }, I; y 索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。9 O+ z9 v& a$ _% |& |& G7 u
, A% G. Z; p2 W
explain select * from type_time a inner join ( M' T( {' Z# r m
select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id6 K d7 C$ _/ M+ {
) t8 _9 k* U3 }3 Y& d @; m( d
{. P" I+ U! w0 c. z- R: B% @* ]; |
* Z3 u) I: H) H
" X* I3 b9 Z4 j" Q 4、9 index( ?' C5 c( U, B$ b* j1 _
键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。
0 o% c' B1 S$ j L 索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
: }+ E" H- @* s+ o1 b
& x% K! ?' J" H. T- o2 g2 } explain select * from user group by addr_id
) \/ a( n! u. T7 H: X# ~4 X+ D
3 w; d6 T- u3 H. B2 P/ d# V& P ; @- Z. E+ F3 V( w$ ?0 N; L0 l/ c X
# N; B6 V6 c6 O2 C3 N, R( T3 D
# u3 c8 f3 m# D: N' s $ i: r! n+ d& E2 l
explain select addr_id from user
2 o5 C: ~$ z% m: p" F( F 0 f5 A3 W( ?1 c
! h# N) K$ S% n/ r ?9 O; ^$ y# P% T; K9 D$ h
7 ]+ J8 u5 D' S) y0 o
4、10 all* V, F' }& N8 Q3 _) l
这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。, g% ~6 { [# I* L
5 J0 z' H9 X8 I- m
五、possible_keys4 V/ J8 F# w) s4 m" L& g9 F
( R: L( I6 I3 G( }8 Z% _
此次查询中可能选用的索引,一个或多个1 B7 ] b+ @2 Z% D$ j2 P$ a
2 G0 Q$ N! N" s3 }4 h N
六、key
, X3 k5 ?% y( z9 B! X) i6 E 查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。* w. f, N% a7 ^. j [
* R6 P$ I4 Q: z) K! {/ t% q. {
七、key_len
7 D$ L$ }1 L0 [. z% M9 k/ v ) l* k) j2 D6 `
用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查. U0 k1 L" W: u! m* r$ P
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。; D1 m9 G7 m; h+ v
另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。4 b% q& i0 @/ p+ u
explain select id from type_time where name =‘2’ 用到长度303
$ y) e( b4 w; J0 L$ }* y, @ , ~/ [* ~" h4 R, c1 y2 L3 E
; c% W( @1 R1 w, \1 F8 K, V+ w5 t
explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071
8 j/ ?9 S& c r. v6 F% O
$ z3 G8 |% V0 s! ?) T2 ?6 W5 f- ^+ S
0 M; k& m; L) h; X# X2 p
, M) A- n2 j5 l P 八、ref2 M. R, F3 S! v# H0 J* i# ^# ~2 u% D
如果是使用的常数等值查询,这里会显示const" p/ l4 [2 ?& ]0 J9 w# m
如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段7 B% |" l, t2 ?: O( O
如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
8 F [; l* o' e( g( c7 p; F
7 k. \) m! I4 }' I 九、rows
, ~& @1 K$ ~" [! W+ ]7 U 这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)2 _& C' |9 d7 `) q
! k# F6 v3 d% q
十、extra
' ^$ ~% k! \7 L: J, [5 s 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:, i8 L- B, E& N+ m, ?5 `$ E
6 {3 J7 l- v* F7 g
10、1 using temporary
1 W' S- [5 U8 F( `8 X 表示使用了临时表存储中间结果。' U" _) a. w9 U! \$ N1 n
MySQL在对查询结果order by和group by时使用临时表* e; {. n3 {' j
临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,$ I. D2 `# D' ?/ F9 ?9 M
used_tmp_table,used_tmp_disk_table才能看出来。
h9 V* ?) U0 b+ L4 I, T( ~
4 g4 m+ d n8 k0 p' n explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
# x5 d# U1 f# j, t8 v ] 9 U" F; f2 }4 H) I" V+ W
" O2 n; n0 k) Q, B- u! _- R ! P5 m( G: R# i& a4 B& b
10、2 using filesort( r+ I: J% i3 N7 A
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中- D/ w. P9 P9 U* v: \& U
( n+ c7 _2 B( V6 W; f 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。: S; D \: n6 q$ v9 t J# r% c
MySQL中无法利索引索引完成的排序操作称为“文件排序“
( k- J* o$ x/ Z5 Z : c0 @% @ L* ]2 G* S7 _: q$ z( ]* @
10、3 using index
- e6 j4 u2 q1 s! R 查询时不需要回表查询,直接通过索引就可以获取查询的数据。3 E. I' K- N( n l
表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
: ^4 E& e: p- n, Y( J n, K 错。% W( b( r: F$ _; ], w. F
如果同时出现Using Where ,说明索引被用来执行查找索引键值3 k! b& c5 l5 n; Y5 j
如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。
8 [* R. ?: T1 \5 t- @/ {
* f+ [$ P/ |/ ` s 这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。8 H& k6 E; f+ j V
————————————————
, P. E. |$ c% b 版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。" l* E& H6 `; c+ w0 B) h: J& B: l# X
原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629
9 I9 x1 u7 |" k8 I . F8 y/ H- k m' ~) h
8 L2 n/ }7 t Q$ b3 p
zan