在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 82 收听数 1 能力 120 分 体力 564647 点 威望 12 点 阅读权限 255 积分 174617 相册 1 日志 0 记录 0 帖子 5313 主题 5273 精华 3 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
$ t: ~& p6 R: P9 W& d) a% l
mysql索引和explain的详解 索引原理分析
+ d. y6 B8 S4 J% T2 V
( C* u" t v4 U0 F0 C! } 索引存储结构
$ z- z1 c" C$ T* F5 ? x8 N% @ x" I 索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引
8 a$ v i! k! @+ ]' e MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
* l, |& b6 O# x. P) H MEMORY/HEAP存储引擎:支持HASH和BTREE索引
" n7 \1 O1 l8 b" R! [ z$ A
4 ` C( n( K9 e B树图示
1 d- a7 a: E9 N" \ 1 s7 ]" p: r, v, ~' O) b( n
B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
: f& y& o9 A" ? ) _7 H& T* K' Z* h5 T% S
3 L7 p3 p5 R$ H2 I
% |8 ]( m3 X& F4 G ; K; W) B, E9 N' o7 [
B树和B+树的区别:9 j* n( o) X2 B$ z8 k
B树和B+树的最大区别在于非叶子节点是否存储数据的问题' p( q' P4 ?4 \, ^2 J
" U3 A0 _6 B; f: A2 N5 o9 E! @- Y( A6 E$ G
在结构上:* j6 R3 [, P' ~4 r
(1) B树是非也只节点和叶子节点都会存储数据。! L8 t7 B6 ~$ P
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。
+ A) M5 | L1 f& j6 A% ?
- K. ^$ R) |/ a4 Q) R 在性能上:4 p- y1 n$ ^+ e1 k* b5 x
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
. @' _0 S% [5 e) D0 Y6 t (2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。5 y/ _! j, y$ y2 z0 q8 h4 `1 G
. D; o" x# `. \( O' Y' o$ o 聚集索引(MyISAM)
( ~6 Q; g0 ^( w- M! b% p9 B7 a B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集# |; ?4 W; ]0 I3 o; ~
索引。
. |8 _; i* d* u9 v1 f% N9 q 聚集索引包含主键索引和辅助索引都会存储数据指针的值。" d* r6 x1 Y' t, K# C$ _2 ]
1 |" {, ^/ E/ N6 R/ n9 ?) L
X" o$ ?2 R. a: a: J" L, {. F
% K/ |/ A. y3 V* s 辅助索引(次要索引)
6 R- T& I7 k" J# k: Y& ]+ `; y2 U 在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,
3 T" ? M! j% s4 C1 |! B 而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示
, O& \( t" b [! u' W# y
3 f4 w1 R+ X) X; g+ T6 m3 D
同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。5 O, n9 n" T) @. t0 `
3 x+ U' H3 w4 d# K$ R1 ~" H6 v
聚集索引(InnoDB)6 A& d7 p: g; Y7 o
6 t# I: o7 Z" J
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。8 x9 _( U$ V& ]! J
辅助索引只会存储主键值7 a4 e5 L8 H, o' H! s* f# G4 Z
如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。: _7 |. w1 A" m: O7 p
, n: k' r( ~5 P# |! Z l \ 主键索引! i! c: `2 d' \
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以. N- `7 \4 Z0 ?- D$ n
唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。$ r. X# V" @& k5 S
8 v# s1 ^" r, F1 n% ~
* E7 _) h' N2 X% `8 L* n
( U M4 P. h4 s! I! Z* Z
0 @. A8 p) R, D( t2 a2 |+ v8 R
上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。 4 }! B' Y" C/ W0 y# Q! u8 q8 P
( @) d1 b0 D+ J; q
1 O3 z7 L# D* u, q) v4 v4 Q 9 U4 Q* g( [- d) x
! s6 M$ `. C' Y7 a: R" }5 e# M! { & e0 Q9 q( r$ r1 S) I* f
, V1 a l9 A0 k2 i mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。$ ^% t; U8 k9 B
f' q4 ? {( {5 E/ c explain的详解
# f! u9 K1 i# V4 V+ k5 a
5 n' D2 Z; W; t5 A# m/ Q* D 参数说明:
0 u8 W# s' o$ D+ R explain后会出现十列数据,下面将介绍这下面的十列数据。
F7 ^9 K9 M' }8 b6 e) r) t# p % S) Z8 Q0 i$ t
id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra& s4 N/ W) C- i f8 V% F4 W% p
0 O' L7 i+ ?- _8 Y 先附上案例表:" S; O3 x8 C1 U
/ B/ M! O, J! E4 ]3 Q: U3 |$ M CREATE TABLE `taddr` (( }1 D' Q9 j' E0 r
`id` int(11) NOT NULL AUTO_INCREMENT,) r h+ \( W' |- E
`country` varchar(100) DEFAULT '',
$ W0 k j, K: ]/ W `province` varchar(100) DEFAULT '',
, d1 v" V. q+ D5 T' R/ b0 c PRIMARY KEY (`id`)
/ H0 x o: _6 _6 c3 a; V* X2 h ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
9 l0 S+ N8 \9 V( X" S ) k0 W" \/ s0 ^" V0 [7 {( k( N
CREATE TABLE `user` (
" ~' P, E% I# s+ v m, |) W `id` int(11) NOT NULL AUTO_INCREMENT,
- D- X% T2 p4 z `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,/ r& K. Y4 e4 H# _
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, f* d) T- d; S3 L' d
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
9 w8 J2 {1 s+ b( e' z `addr_id` int(11) NULL DEFAULT NULL,8 l1 f0 D, f) p
PRIMARY KEY (`id`) USING BTREE,+ z+ d+ O! Y# T7 d6 P# k( L Q7 o
INDEX `addr_id`(`addr_id`) USING BTREE
+ y; i. k: E8 p3 ? ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
. A7 h$ w# Q2 H! ?
0 |- T% ~6 t- a1 l9 K 9 b q+ x! Q5 {! i E5 ]5 A$ u
CREATE TABLE `type_time` (( c: {% n; o+ D, U/ T9 V
`id` int(11) NOT NULL AUTO_INCREMENT,# a, ^" x2 w' G7 _9 {1 O' a1 J; |
`time` varchar(255) DEFAULT '[]',
# N3 d) P& a J `name` varchar(100) DEFAULT '',0 p% Y9 C1 f1 Z" d+ M) Z+ U
PRIMARY KEY (`id`),4 T) j) I" ~3 a" c: B/ T8 U# c- q
INDEX `name_time_index`(`name`,`time`) USING BTREE
* Z9 b2 m' z* X5 x# U( p ~* K ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
0 ~$ x6 `* n1 z: U/ }1 D$ l # ?+ ?% q2 y% v4 f V+ K
一、id
) h8 |/ b% n `! z' C- ] 每个 SELECT语句都会自动分配的一个唯一标识符.
! i0 H( N$ W- q" b 表示查询中操作表的顺序,有三种情况:+ V H# ?. z' X' c; i+ [! H
id相同:执行顺序由上到下
8 z# G. Y4 J- Y1 i id不同:如果是子查询,id号会自增,id越大,优先级越高。
0 a# R$ Z) t. b- Z1 k' H id相同的不同的同时存在
" L; o) f1 m2 } id列为null的就表示这是一个结果集,不需要使用它来进行查询。
" i3 u$ _ {0 g, \& e& H2 q
, ^2 Y# c# @- a 二、select_type
4 E. b+ _: t& h1 ]
% `# @, X! [( b* K$ u7 Q0 G+ y 查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
3 D( {- B( w6 R- ]: v& Z B
. ^, r9 S; E9 B9 ?$ Z5 i! o2 Q& W+ r 2.1、simple; x8 ]. h* p$ v" H/ D5 T2 `
表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple5 Y5 t: c5 ^4 W. v8 x
* f( V2 C9 E0 A9 G/ I# V& n EXPLAIN select * from user6 n7 K' x" q% j
. s* d S( Q9 s& E
7 C9 h; l' ^6 g
7 g, H4 V; E S* H4 t. ] EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id ( O) K w# O) y2 |$ F' O& P; C
* w: J! ]( P5 ?% I: j. G
: v$ h5 o' V+ H5 _4 s) F. a
2.2 primary
( ], Y# F* p' \/ c 一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。$ f. N4 O) p: u" T, ?
6 s$ J9 ~7 N% t5 @ explain select * from taddr t inner join (! z2 ^. E" ?- ^; Z/ Z# {" m: `0 z
select addr_id from user ) u on t.id=u.addr_id9 J* x @5 p3 ?1 l! X: v- G- `& k
I3 q$ u% x1 f$ G
explain select * from user u where u.addr_id =1q
+ N- L; H" I& f5 F5 ^" J3 u union all
: Y1 }% ]! w, V/ x/ p select * from user u where u.addr_id =2 / P3 ~ W* Z2 o
" l! m3 w3 S! K/ \. B6 K8 Z
* B( |! J7 Y- A0 O: f! _6 M
2.3 subquery
2 ?1 I7 u% y2 ?1 G# E 除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
7 m9 Q/ u/ j/ w$ ]8 i ) G" ~& V h0 q8 d2 o' v
2.4 dependent subquery4 X6 u8 N8 a+ u' q1 u7 D
5 p' A. b/ c6 \8 R- v7 h8 g E
与dependent union类似,表示这个subquery的查询要受到外部表查询的影响8 W3 Q1 f$ w/ {+ L( i. B
; E5 a- r8 t$ d explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u2 Z& Z3 F' p. W
6 v1 j2 K/ b) [& x! L 2.5 union
) z- P8 r: I& w" T+ ~1 l9 H% Q union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union$ v1 f8 P& J9 v, L3 Z$ ?: C
8 X6 J; ~3 _4 O! B( d5 I 三、table
$ G9 _- T: m$ T# }0 C7 k 显示的查询表名,如果查询使用了别名,那么这里显示的是别名
e& e# \. O) b/ T8 J, U 如果不涉及对数据表的操作,那么这显示为null. k2 Z$ p$ H7 x# G1 a! ?+ ?. }
如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
; E O6 G% `; a1 T$ z. C 如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。
0 q) |# ]9 }% a3 E- w/ j* H & W6 o$ a; [: Y" m& x2 h; n6 U9 m# t
四、type& {4 W5 r' N2 Q6 Z
- `# n D- a2 @! H+ S+ M- D
依次从好到差:. M7 Y3 S8 K: T9 I
system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
# q. m( p- X; G, H/ _ index_subquery,range,index_merge,index,ALL Z* R( Z* {1 ^ ~- h! b" T# o9 N2 ~: V
( i. N! H% j1 F 除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引
2 r- e, x: i. N" j" \
8 f; k" w4 J2 k, B2 G8 u& x& X2 B 4、1 system, ~% [' m8 R* _5 F2 ^' Z
表中只有一行数据或者是空表。6 B7 X( q' y, B9 u! `& w
5 \/ Q4 @, c+ ]8 w0 ?
4、2const; K3 o5 @; |8 I- u2 T1 D; M
使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。) F, a; ` D# _; A6 J: s" m8 J' b G
( A' ]. k3 Q5 f* l 4、3 eq_ref; _) o8 s+ K' e$ p! j# {9 E
关键字:连接字段主键或者唯一性索引。& |7 Q: e' ~/ Z! D
此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高./ O+ B! a& o7 P) Y
4 B5 R [5 q( x2 j. L
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id+ v$ E$ R# f& s8 w
) L- d5 a, ?! q
7 D: ^' @" f! t
! ^. t6 j9 w; x3 T
% s# H1 {' p& h6 M. Y
! W5 }3 L9 A4 T0 z7 P* v9 J7 \0 { 4、4 ref
2 ^1 d1 t! V7 g5 h 针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
$ a6 h& X8 ]! R) R1 I
; m2 b0 h9 F6 f# F" Z% W7 b; S
4.5 fulltext C9 y) f- p& }( k0 H1 `
全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
8 ~, c: ^& h* A/ ] b. u7 \
* e5 c: o5 I+ ` J: \+ `* O 4、6 unique_subquery
9 l9 x3 u5 [7 g( N `3 `. k2 ^; d 用于where中的in形式子查询,子查询返回不重复值唯一值, s! L( D# W- k$ l% ~4 Q
3 z% Y h# J6 C% C `$ e 4、7 index_subquery; l( V7 E" y* P8 i! e" y+ @' E5 e! [
用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
0 T" u- G& a+ i f" b! f; Z' D
# i# g" ~# n, U2 v. n6 l3 m 4、8 range
# w/ A5 S* G6 | 索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。0 L. ~# w1 i" k3 v
2 ?7 A5 c1 @! j, j: U
explain select * from type_time a inner join (/ C b( I' d6 w" C( I- G
select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id% W3 v! t$ E! u% j6 e
% |: x" }# Q# K! E
. O' k+ }6 _7 b f& t- M9 \
# n' m& p- W1 x
- w5 Y& e1 a0 n N8 J. l- R
4、9 index
3 S* i1 i; z- S& F 键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。9 M& G! r! l+ }7 w3 c4 M
索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
' K6 i U3 B5 O. N" G! R " V) u( }' o% i8 H# p% }
explain select * from user group by addr_id
* W3 S3 i! ?' h" }3 l/ @7 } . f R: @8 c9 t1 m. N0 Z
6 h* Y4 o) S! g" C9 e q
& P0 U9 K" `1 {/ h3 r, d
. l. N: h. b3 H$ J, } ) E9 @. L, I/ \
explain select addr_id from user
0 K/ C9 u2 \1 h
* J/ K' {& p, x5 Y" v
6 y) h1 r$ Y( H% _' n. V1 U! I% l
" N* u' l7 O( W( J! b
6 w" d& d5 E& C6 p6 Q: a 4、10 all0 B0 Y; A$ }1 k4 N8 n
这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
( l1 H& h; R7 F# s- q: Q8 P* h
$ b8 t' m+ l' j 五、possible_keys7 _( k% g1 ^9 T" ]6 d" ]
! s u0 l3 a, G* \- m2 j 此次查询中可能选用的索引,一个或多个( l! M# C" n' b( c4 t
! r0 l0 J% o) O' c! m6 `3 c 六、key* Y U* b/ F' }( D# s1 K
查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。2 v4 f' |8 W7 J Z: \
6 c' H0 Z( l; z! U8 n 七、key_len
3 N; X5 x* O* ?/ o5 h/ m
8 m. t+ G- n- X4 x. D% e7 v 用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查( T/ {3 [# ~( p: L3 k/ I, S( F
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
9 \3 @7 ~: }0 ]! i5 D 另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。
" G' y- }% G+ H8 @% r explain select id from type_time where name =‘2’ 用到长度303% y- g" F/ ~, D- h% e( S8 `2 ~! ~
' r& o5 v: u5 K" G# R( M
4 w$ t* S& q4 _: u( Q explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071 - j, t$ J0 ?) u0 a1 s9 k; `
" X; z" [6 p1 M. s% ]
( z, P0 t; X j: q; Y
- v l8 F' ?. l
八、ref* G( Z$ h6 j; @
如果是使用的常数等值查询,这里会显示const& a, X* L6 Z8 @" z+ U
如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段
5 F, f, f) g4 p+ y 如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func( s7 N) E a# U& S! T. S7 O u/ l
# p8 u9 P' }! _3 ~9 o; ]
九、rows
# G' j+ o1 B) E 这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
! H( x9 V s5 @, r8 D' I/ X0 R * t) t u7 e* H! }8 j& d1 O Q
十、extra
) K) X$ L7 w4 s& v 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:' C/ |. C1 [. k9 [
1 f+ p" S3 i" p; g8 A
10、1 using temporary# y* y l$ a. f$ u; c& w3 _2 w$ H
表示使用了临时表存储中间结果。. S8 ?1 b! Q b; r: I r/ M
MySQL在对查询结果order by和group by时使用临时表
' Y& z% @7 T) B/ ?1 F 临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,% h2 Y! H/ p1 ?( G- t( z/ Y) \
used_tmp_table,used_tmp_disk_table才能看出来。
" v& J+ i9 m" r6 T* w" _$ f
- r2 m5 n9 S, C! \$ B0 a6 Z0 B explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id# A8 j* s8 O7 J
( }. ~! V& X3 Q$ I
" Q2 R. y9 }; {
/ h7 \, M5 j4 R8 j7 X0 a5 |% | 10、2 using filesort; j4 e# O. u" D; _5 {! M6 y
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
# M0 w9 j& {# B) B5 g
. `, w- U% x1 }* j 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。
. D; N* a' E t, O U# k MySQL中无法利索引索引完成的排序操作称为“文件排序“) D: Q { S5 z5 h* |9 z
: G Q5 z; `2 o
10、3 using index
' S- @* j8 l- a9 i+ @ 查询时不需要回表查询,直接通过索引就可以获取查询的数据。" {' A( }: _( u1 T2 L" D' G
表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不" P0 L3 i8 h+ I$ x# N4 m1 b/ n
错。* h$ [/ U1 r0 I5 `
如果同时出现Using Where ,说明索引被用来执行查找索引键值
% F) `7 j; ?9 g5 l# S5 j$ Z 如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。( y- i# U" _1 g: r# v- P# z
, l- X. o) k$ A" g5 L% C% w 这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。
, @$ }: ?: A) i& N# J5 P" \" ]: Q ————————————————
D. R; x, y+ f4 a1 E 版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
, t0 g& D0 X+ M 原文链接:https://blog.csdn.net/fajing_feiyue/article/details/1056166298 z* }# Y4 t5 k6 S9 q/ z# l
1 f6 r: G0 ]; a0 ] . z; \( R* B) O3 h7 X& K
zan