在线时间 1630 小时 最后登录 2024-1-29 注册时间 2017-5-16 听众数 81 收听数 1 能力 120 分 体力 541115 点 威望 12 点 阅读权限 255 积分 167713 相册 1 日志 0 记录 0 帖子 5324 主题 5250 精华 18 分享 0 好友 163
TA的每日心情 开心 2021-8-11 17:59
签到天数: 17 天
[LV.4]偶尔看看III
网络挑战赛参赛者
网络挑战赛参赛者
自我介绍 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
群组 : 2018美赛大象算法课程
群组 : 2018美赛护航培训课程
群组 : 2019年 数学中国站长建
群组 : 2019年数据分析师课程
群组 : 2018年大象老师国赛优
* V$ d; I4 x" o. [ mysql索引和explain的详解 索引原理分析
1 u l. |& t! K( v : j5 e2 F a& _8 ]9 L4 ?. U* }
索引存储结构
/ b/ F: o! x& m 索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引( \ {3 z- Z! S) ?. i; J1 d+ b
MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换* F4 M7 J) j5 E$ a
MEMORY/HEAP存储引擎:支持HASH和BTREE索引
_2 j" u% k$ c' ~9 \- o 1 h. `. p& j8 c4 m: A: M" n; u
B树图示" j" R+ L2 e1 \1 i* d
) v n! w5 ^+ f6 G7 p B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
3 h! B9 z* N O7 s% L8 C# c
, N8 T) G* F% b) L- Z% q _$ {
/ ~7 r! b, m; Q) ? : P$ N4 U" Q4 |9 ]# X
+ `# J( e5 d6 k/ H- I( w2 b3 ` B树和B+树的区别:" H; N9 ^& p# p0 T$ U! y, O
B树和B+树的最大区别在于非叶子节点是否存储数据的问题
. H: z: Y5 L% O! Q' ]9 p; o 1 s# f' n! v2 q# T
在结构上:
7 t2 S2 G" ^: E! O4 j (1) B树是非也只节点和叶子节点都会存储数据。3 L' n2 S: y3 Q2 D3 m9 O- q5 V$ ^
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。% |1 i v1 B( g0 f# R) `: Y
. u2 l2 Z) U0 f* s* [ 在性能上:5 {- [5 m0 B' w0 c1 c; _1 V
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。2 c+ B- y7 k" Q8 S8 y
(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。$ B& q3 o1 k8 ]$ B% ?
2 Z6 {: X- I- B$ C7 x: B0 O e
聚集索引(MyISAM)
3 @3 F1 F2 a' B B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
# A6 N+ G9 g1 I$ f 索引。7 g7 i4 T4 i" {8 K7 A- [% m
聚集索引包含主键索引和辅助索引都会存储数据指针的值。1 C; o$ h! C5 I9 R0 x
x) E3 ]# Y3 n5 [) h
( } l. v7 U. H0 y- y
- N8 z& w+ G5 K. n/ Q. V 辅助索引(次要索引)
0 |! L* H; r* b" x 在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,
$ M8 I+ F7 }/ u6 @) W0 @: M 而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示
* B l K- o9 y. a
0 c% N s7 q4 x [ u
同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。) L# A- e- m5 Z* O5 k
9 I& x) m( F" o* p4 @
聚集索引(InnoDB)* Q8 ^3 H, C3 S3 S c1 Y" w
6 s' f5 j9 P# s0 w4 D; n O 主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。
) L2 p( I) U. M5 ?- z! W4 ]# Y& w5 T 辅助索引只会存储主键值- O8 c- V7 i4 B8 ~- N; G5 j
如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
) v/ ^$ c: i! `. X1 I) N3 L
! g! J5 o+ R! \$ F4 {$ b3 L6 X 主键索引- Y5 i& w2 c3 y0 u5 G" X
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以7 E) F* C/ Q6 o" D O
唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。- x; S# e6 A' k& X( S, f, O' }5 ?
1 R. e q0 r4 ?$ a
# q' R# p7 W8 A4 V
5 P, i; Q2 Z) R3 h5 d$ m5 T
" @) g. s1 z, _$ x' |3 F6 o6 w 上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。 5 X* [3 w8 w" M# f0 k2 q
( a0 H$ ?9 ?, u6 p
; J$ x& p: _: E) G; @" p) D
& C* ^9 _0 [9 l6 q+ I. i% T
: _0 x" ?2 K% E' A1 X9 p4 g) Z* _
7 ~+ P* `2 a6 ^ : C' ^" k! g/ M, s( l- L- F
mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。
2 {" S- Z* {: n5 d0 t k* P 1 T) B0 b% V7 l' A
explain的详解- ~. A! P* B+ o1 A8 R# _5 ^8 |
: R9 t! L3 D) M. l r% M0 c 参数说明:
6 J, Q% R$ a7 G Y$ P explain后会出现十列数据,下面将介绍这下面的十列数据。, F' S) e* h4 Y+ I+ X
! @8 S! _. r7 Z/ ^- R- v id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra. v1 Z" f. P* O# o
) L1 d- n8 Y' Z
先附上案例表:% ]" p* ~! n% D# i4 d' O; A
! N- Q( m" t4 X4 c. @2 r5 I
CREATE TABLE `taddr` (
& Q7 L: p3 a: G4 U `id` int(11) NOT NULL AUTO_INCREMENT,
0 r9 t4 g8 l9 [* z8 z `country` varchar(100) DEFAULT '',
" I9 m# e* H9 F, O/ c+ S# F5 Z `province` varchar(100) DEFAULT '',/ M6 y+ W; P8 s! W2 f
PRIMARY KEY (`id`)
! n! a; o; o4 `& r) x0 |6 B ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
3 v8 V# Z! c2 |0 ~2 [' _$ C- O
$ u% a5 Z: K" ?# @: {- h3 q& a CREATE TABLE `user` (
% J9 p3 m- W1 e" Z `id` int(11) NOT NULL AUTO_INCREMENT,* W8 x( T4 T: V3 w
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL," K5 y/ n+ g9 @0 j
`password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
/ Z7 o& C# L7 {) B$ O; L `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,* ^( x. R' _' i, s, A% T; t x
`addr_id` int(11) NULL DEFAULT NULL,
: E- `8 Z, J% @* | PRIMARY KEY (`id`) USING BTREE,) F" q. E5 O0 x, s
INDEX `addr_id`(`addr_id`) USING BTREE
3 ]# y" ^" `9 u# K% f: U" M ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;# X2 u! ~8 ^" j
, K; L" s) u. R8 {, X; I
' C Z2 V9 K6 I) _$ y7 a CREATE TABLE `type_time` (
" B0 Q( ?8 ?/ O `id` int(11) NOT NULL AUTO_INCREMENT,
: Q9 c% }& v+ @7 y, q9 B% g `time` varchar(255) DEFAULT '[]',
& X |# t- _) E2 { `name` varchar(100) DEFAULT '',
1 x. Q7 n" M* Y8 Z PRIMARY KEY (`id`),
' b9 p" ]9 g# u INDEX `name_time_index`(`name`,`time`) USING BTREE" t w: t# ~& w3 Q: n+ I
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
$ Q! \3 C) n% ? 1 }# Q" r2 k$ c/ H7 u
一、id
( e, D' J- l: ^/ a! {2 a4 P0 x 每个 SELECT语句都会自动分配的一个唯一标识符., j$ Q5 i+ t6 T" ^* g
表示查询中操作表的顺序,有三种情况:
, d6 d% u0 z: W. j id相同:执行顺序由上到下+ d& f6 x+ K/ A2 J
id不同:如果是子查询,id号会自增,id越大,优先级越高。. e) O- N. y* x, g3 U
id相同的不同的同时存在/ k1 a, s% q5 T' c* z& I
id列为null的就表示这是一个结果集,不需要使用它来进行查询。
0 Q* Q& i* u# N* n0 D+ h
; _2 @: z) T1 ] K 二、select_type
- h8 J+ E( C/ i% l6 h
+ I! {" B8 U8 o, H 查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
% v9 }+ Y$ P* H2 a! Y6 { ; ^' X& r* f4 o3 U) g
2.1、simple
# r4 E: t2 i S5 } 表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
2 a2 B5 y, Z" t3 j
/ E0 O. H( A1 e4 n. Z* S0 w EXPLAIN select * from user
3 |5 [7 n7 g: n; B5 M7 Z/ K" D % P+ V1 Q, Q W/ y" u3 e
: I. `1 _9 j* x7 {
: x! M. D0 }( @2 B/ v+ |8 j EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
) h5 O! }" Y. x1 a" Z0 X
! r1 a* R- v8 V) G( L
P( Z, [$ z$ \* K3 p' v& ` 2.2 primary9 [9 b. b* W3 K& q9 d8 j
一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
' u7 f# \$ F6 \6 L) t9 m* a $ S* l. O. ~) d' n
explain select * from taddr t inner join (& o# b& {$ k `& C" E# f3 Y
select addr_id from user ) u on t.id=u.addr_id
1 B4 g6 D3 F3 F" Q" I; F- X0 X
8 ]0 _2 ^8 R1 p0 o% ?4 R0 i2 \
explain select * from user u where u.addr_id =1q L: q; P/ d- c. E' O4 N9 s
union all 8 [7 n4 Q+ Q% o% h
select * from user u where u.addr_id =2
9 o3 [, P+ j- A/ [# c" r
1 P" w! b2 m! S1 R
" v8 s1 z0 Z, [! r$ X- x3 q 2.3 subquery# a8 e5 g5 \: f$ n
除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery) ~* z$ ]: r; ]9 w( D9 D1 D; x
4 ~$ h; \* |, L/ @: I. E* S
2.4 dependent subquery
, X. A1 {! J7 i6 e, e% s
N! d7 U2 N5 l* C6 ] 与dependent union类似,表示这个subquery的查询要受到外部表查询的影响2 l4 r( m& S! t3 Z
5 Q/ {; L, B& W0 U# V' a explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
: f1 L B( z" A" {8 z8 ]
& @% N1 G" W: L& ]3 L+ Q+ o1 W 2.5 union
# e z; v% _, i! N/ Y5 N union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
* r* {2 S. B3 @
, K" A+ d3 A" N1 h8 y2 }0 s( _ 三、table
6 k3 `0 k3 }4 o9 n( C: T; C9 H 显示的查询表名,如果查询使用了别名,那么这里显示的是别名
# x9 S5 T; R( C" W, [" I; G 如果不涉及对数据表的操作,那么这显示为null
# ]$ @5 k$ A; p% D. z 如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。8 D5 B3 _% X4 d" V/ i z, i
如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。
2 N' a. [" a1 k S9 l% M
1 U+ s) ?& V) X) W9 W 四、type
f( v0 W' t' N. M* \8 X ' \ V- u) L" W: `2 i) W b( A
依次从好到差:
1 s+ n7 v' v% o0 w( E system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,: ~5 @2 W$ }2 T6 F2 Q
index_subquery,range,index_merge,index,ALL
/ u+ d, V( i% X( i# X4 S3 j 2 i3 A- u/ X3 w4 v# a0 H' @9 }
除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引
0 o1 @5 }; T, W! j7 W; C& A# b7 B * h! C9 O* n3 w, g) n3 P) I
4、1 system) m7 i1 r" w: [& C' \+ |
表中只有一行数据或者是空表。0 Y/ h# _) t$ ~
, t+ j3 ]( u! ~3 M( G
4、2const' i1 T: `. A* ^
使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
6 T1 g" \+ Q, I 2 O- r4 D7 j/ o1 |( m
4、3 eq_ref" x/ T7 J# k3 [# {6 k7 e4 {) W
关键字:连接字段主键或者唯一性索引。
/ y( O; m+ _: i3 _1 Q( S 此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.
7 b2 x/ d# `* x7 d: B, l& V 1 x! F& \) Y+ a/ M% P0 r& f3 j" `
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id2 f( J3 O L a$ C. y* E* u
3 q: G; E. Q) M# ]3 U
5 A7 j' c/ x" ^5 y7 R7 X
. z/ R# l* E8 v2 L7 W" T. U( [0 r
$ y$ P U7 P) V: m( N8 ?1 A
* D L0 t% e w) X5 c$ A: [ 4、4 ref+ |+ A* n/ p6 s) X% Q( W1 ?
针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。
EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id
2 ~! G: h. e, q5 `; E . Q0 c+ X! M; i; Y1 B2 N: P
4.5 fulltext9 p% V6 j* K5 O( r, {$ n. |$ }
全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
Z$ A+ U- J) Z
( `9 ^( ^3 ]. K) [ 4、6 unique_subquery
" q! }, r! P9 k: q' Q 用于where中的in形式子查询,子查询返回不重复值唯一值
* P- M: s( o$ q7 N, w - m+ [. p$ ?# G4 W, q; K
4、7 index_subquery
g6 F0 T5 D5 C& X* |( _ 用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
1 Z4 }- ], a% z7 I( G
6 B8 S$ t7 f+ k/ Z* u' s" d; ` 4、8 range w4 j' I- k7 `: A" q, `
索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。
" x$ y- R- g9 o# m+ t . h# {, M! c# k7 ?1 m$ [" {' ^! C
explain select * from type_time a inner join () p6 r5 f1 W# @$ U0 x
select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id
% r9 d! N# k& Y. Q/ g/ W" E# _7 k , Z# ]: ]2 _5 N0 \6 Z$ _& c
0 b% I9 x$ t" u+ I, f5 }. \
6 o( Y7 v# j6 F" T9 g9 g. r
# \2 o* H. Y8 u+ p- P5 c' V# X! \ 4、9 index4 y2 [1 \5 V* g% e4 K$ _
键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。6 L9 Y5 T. c4 F. P4 i/ H1 @. O& S( x5 [
索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
6 n' ~2 j2 j& v8 P , ]' s5 Q! I# t' g5 M, ?! @8 [4 B
explain select * from user group by addr_id
! {) w: k+ B) F2 B% w: Y) L/ I . R B0 E2 e4 R2 z- O% e
6 |( A: [* t5 m4 q, g0 Z3 S# i
- J9 b7 q' n+ f2 u* q
- [. g% z' m8 X p$ B4 }
0 V- H7 }+ c D# S/ ^" P3 f( l: _ explain select addr_id from user
# m. m, O9 B1 j8 W
2 j( U: J! A4 X/ n' }; \: i
% t2 K, z# ?( Y( g/ Q
( Z) G5 _0 u# v
; t, a9 ~( J) z4 }: ^" K* C 4、10 all$ I4 t& X3 K7 U0 _; `/ [( {( C
这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
! C( X+ h3 N2 D4 n4 k B' g! D% k + {6 {: v& g, J& d5 r& @
五、possible_keys* ]9 B; S2 y% l/ v% M( W* b
9 `* C: `4 n7 S; c& d0 G7 C 此次查询中可能选用的索引,一个或多个
5 G! W4 V' @1 e: l$ `1 ~ 5 Q0 J) l. V2 O1 D
六、key
5 D6 C2 V# Y8 G1 ? 查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
6 s& u2 B! f! D9 w + ?; g' \% r8 M# E0 M/ A9 R
七、key_len4 K' R( I" |$ m; p/ ~, s" \+ r
. s% D& b+ r( m8 W2 P: Z
用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查! u- y, D$ _/ ?# ~* f- d
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
0 H3 T# x' m* K3 o9 v 另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。
5 g# }& [* j4 r8 z n, O( Z0 m explain select id from type_time where name =‘2’ 用到长度3035 \' k. c1 n5 i
9 h% v( t( l6 W+ r A2 y$ X% G
$ {# z0 v/ u8 g4 R" L& r2 j/ {
explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071 n x/ ?( N% r% l" A
1 S; Y- X8 b1 e. P3 q
/ U, Z) e- d% M* r% q ) O+ B1 }; `4 o5 o/ t
八、ref+ v% S% f& e1 T6 J% m/ P% Z
如果是使用的常数等值查询,这里会显示const
# n6 T/ q0 U% d9 ` q9 M 如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段5 a( t& J3 P+ b N# ~ L# i+ u
如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func, H1 p! w0 ~" W* I5 J' G* G$ E) r
: T; \' _7 o: X 九、rows1 _- X& n) C0 m. C+ ~
这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
( M$ M# L2 _& o9 z3 E. J
, B$ L' l# i. U2 e 十、extra
% b# ~6 L* Y! x2 o) ^ 这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:
, F' c% [) |1 B4 ~: Q0 Y
. ]& K1 G* s; L4 h, L4 `( ]* S( i 10、1 using temporary
$ Z2 ?) y8 Q2 Z% n4 B2 E 表示使用了临时表存储中间结果。
K; p1 ?1 C8 j# [$ S$ l MySQL在对查询结果order by和group by时使用临时表
% r. } T4 {0 ~) d; H" h- V 临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,# Y4 K. i6 O% z" y
used_tmp_table,used_tmp_disk_table才能看出来。' ?; P0 W5 o4 ?2 l \+ Q9 q
9 S ?2 ]# {% D5 d- L. O
explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id( {" E7 W5 ]- T! e' }; a8 `" ?- Q" s, p
- }3 D( O$ B9 B7 I5 X! S
# V4 C1 y, ~7 U) I J
5 f& B& [& [! L% z
10、2 using filesort- d7 ?& X/ I6 j/ w3 m5 @
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中% h& S6 S# I: f$ V J9 h
. P6 d$ R* ]4 @. g8 U1 W; I 说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。1 k( e2 B) m' {& R9 ?
MySQL中无法利索引索引完成的排序操作称为“文件排序“# q( F0 M/ Q9 q6 K; [
# n6 Q2 R) E6 f) t1 z
10、3 using index
% m( b+ x, M3 o9 r7 v) A 查询时不需要回表查询,直接通过索引就可以获取查询的数据。8 m; t' }$ z' @* \) Y: b
表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
6 W' q1 {+ }: U) o! E 错。
+ x+ P0 ~4 J2 w- W; L6 F1 O 如果同时出现Using Where ,说明索引被用来执行查找索引键值
. f. h+ r8 a' I' ?7 D5 v) q& w 如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。2 Z, c, \& z' ^( S. V' {
+ {2 @. u4 f7 N1 f/ K9 _
这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。! J5 H6 D& k" j+ p! F/ f- V
————————————————9 z1 p/ Y/ y! q2 Z
版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
6 D5 g$ k; b$ O$ r: F( a) K 原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629
/ J* p- w( m# z0 |- ?# O: N- w7 h
0 J/ i3 ]1 ^9 U0 \0 d9 ]1 Z
) }, o ~# r2 J% z% s5 O
zan