QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1676|回复: 0
打印 上一主题 下一主题

mysql索引和explain的详解

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2020-5-3 15:46 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta

    / w& s/ s' W. F! Tmysql索引和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  QMEMORY/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 ^% p0 n7 p6 }1 E+ }" V3 z' q# e
    1.png
    # ~: k2 o( P- v9 b8 N; @7 U
    . {+ M3 p9 U1 u4 n6 m8 [8 a8 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/ _ 2.png ' ]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
    3.png
    " 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 4.png
    . e9 r$ T, W: E/ T) q) K& [$ }% C2 `: ~" l
    % h( e/ a% l, \) r
    上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
    ) ]- p" I% b& p3 B 5.png
    8 k# o, m/ @! `% a% \1 p
    - m5 ~: @3 X* Q" i
    5 x" }! m# T- r 6.png
    ' b. }8 x+ t8 j
    1 T8 A' J4 D, M3 s8 ~8 Y+ ]" }
    ) D. d# b4 t$ F8 X1 Q' d- Dmysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。/ 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' iid相同:执行顺序由上到下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 i2.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& QEXPLAIN select * from user$ z! B2 y2 V6 [
      i, D0 D8 k5 X, s. F
    7.png , 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 9.png : g# S1 @5 z) M

    1 O0 U9 {5 V9 U0 ]: o! N) P2.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 fselect addr_id from user ) u on t.id=u.addr_id* `! \3 d1 X4 ]- d  Q
    10.png
    - ~( s6 b- D8 H& V, C3 _7 oexplain select * from user u where u.addr_id =1q& b) b, w" w4 ?4 V
    union all
    * A! i% V" N' ^& I- r3 R/ Pselect * from user u where u.addr_id =2
      t+ h5 T3 C$ o( x2 W' _- N! V9 P/ L 11.png & S" n5 b; d+ t% |2 Q' s! E

    7 l: c  B& k! T2 k6 h0 u) G: T2.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 12.png , F' |* R2 `4 h' i4 h3 e+ Y) B4 `
    2.5 union
    6 _; A7 l* y1 g* P4 W: H* e- aunion连接的两个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 qindex_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 C4、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 F4、2const
    / t' L2 |) z9 o* Y) _9 N/ }使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
    & C3 ?; c$ b/ d4 V/ u- z7 n
    - r% ]; `( k6 }6 d, P4、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 13.png
    : [# p4 A+ i! ]  {3 r# l' g3 ?" 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

    14.png 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+ Kexplain 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 15.png
    ; ~. |, 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 16.png & 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 17.png ( t4 c4 ?, G8 L; s; Q
    3 ]- I+ F% p) O+ l

    ( d" h# R% }5 e# }- P4、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  m7 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
    18.png ; 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
    19.png
    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/ S10、1 using temporary  K& c# \0 X6 w6 v& d0 o- W6 ]
    表示使用了临时表存储中间结果。
    1 e2 z/ h) i2 P' k# f6 k1 B6 c9 IMySQL在对查询结果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 @
    20.png
    # 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% nMySQL中无法利索引索引完成的排序操作称为“文件排序“
    ' _* E/ b' N; s0 \, d0 ~, }/ 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

    20.png (13.61 KB, 下载次数: 398)

    20.png

    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-22 06:05 , Processed in 0.415102 second(s), 53 queries .

    回顶部