QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1702|回复: 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
    ) ?' @2 e: _0 I3 w' D# S; P( W
    mysql索引和explain的详解索引原理分析
      M4 H* ]& a' J, K2 F4 d# ?* o- N2 {! E( l  Z
    索引存储结构
    $ z' h4 }4 G! H/ n$ y索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引
    & n6 P- P7 w% M: ^5 N6 [, \MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换' k2 [+ C% G! s6 i  a' [9 W- D
    MEMORY/HEAP存储引擎:支持HASH和BTREE索引* j' c* x4 B' P1 Y! {  f: n' M% @
    8 [8 K) E, a3 a: E! w4 j7 P& I2 D+ J
    B树图示
    4 K# E- I, r" l( k# z0 ~/ V2 x
    8 n0 A# k; U/ A6 T+ dB树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。# \. j  J3 ?* ~, A6 F+ T* ?
    / u4 Y  m" K: I% C; w# d$ s3 z4 ~% N
    1.png
    8 p$ @& k$ B, Q: Z% o0 I5 Z/ S# ~, \0 N- M

    6 n6 `% s8 N' oB树和B+树的区别:& L8 _7 t; d' s, P2 _
    B树和B+树的最大区别在于非叶子节点是否存储数据的问题
    " e  t3 Q$ y8 ~, b0 ?
    : g: h6 J; ]! R2 R- e0 L- w5 p0 f" s在结构上:% {" q) K4 `  V
    (1) B树是非也只节点和叶子节点都会存储数据。# I1 `- q8 F! d+ \% y+ }* G
    (2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。% j+ Y/ Q* Z1 M+ `  W  s4 J% p) `
    / ]% W: I# Q  p- {, d
    在性能上:9 y, U" C# G) u# ^4 D& n
    (1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
    ' y4 L% q& V) N5 B(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。! {& W$ I) `9 ^$ _$ ]' Q- H) m  N1 C

    % O7 [9 Z* I  w1 u% a7 W9 F' i聚集索引(MyISAM)
    ( p, C% H% h, e; E9 L7 OB+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
    8 e, ~' T) p( `: T索引。# v4 x( e' G# O+ h
    聚集索引包含主键索引和辅助索引都会存储数据指针的值。
    2 A' a! B1 y# z7 X9 s6 v# y& k- L6 k, m
    2.png ( D( M& W4 m5 u/ r$ X5 i) _4 l- P: m
    * R5 ]  _! V* {& _& r9 d' A7 |) C
    辅助索引(次要索引)5 k6 h/ B) r& z! Q/ C1 `
    在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,7 @2 O7 g. o" m
    而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示* Z# l  L" K" X1 Z3 d! Q6 I! j
    3.png
    # N" Q# [( D/ _# R( y& `同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。, p, e  s8 o- s5 r4 U' M

    ! c# T9 B& W$ h5 n9 J3 t& E7 T聚集索引(InnoDB)* n% r0 P3 H7 f8 D. I
    2 y- @' F% j# D! m5 p( H
    主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。/ u# h4 G5 B5 m  z* d+ M# N8 [
    辅助索引只会存储主键值
    7 C5 J( z- ]9 w0 \$ F: C" H# B如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
    : `! U7 c- V; p0 D- O3 R# h. d- [! P/ Z* s! A
    主键索引  |' i4 z; l! C+ A
    1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
    . T- Z$ Z% Z2 M! t) e唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。5 Y* a8 N& m9 i% W  A
    " T9 O2 E6 _0 ]8 Z8 ~* p% ?4 @  }8 [! x
    4.png 7 Q- p8 g5 m; \7 @
    8 u6 B( K6 m0 F% ^) V9 Y
    1 u8 ~* C0 U2 C$ s/ u
    上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
    ; r+ P- {3 x( `' s) r 5.png 7 V6 b; _: a* J; ~# _: d6 i
    8 J* L1 K- J. d  J' Z
    2 }' `) V5 [. S9 x: W0 f
    6.png
    ; z; X# C- V$ _& V9 `  ^
    3 d. B* W# r! R0 v2 h; b/ d1 H( j7 r4 Z: ?, H3 u, O
    mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。+ e; W8 t$ E6 C: L$ R. L. G

    . L- i' ^% w. |$ j* Zexplain的详解7 u% O& X# o4 z8 S& q0 J( o
    $ c1 k( @* [: S% z1 ^, A4 U* u' l
    参数说明:
    0 R8 i5 W2 Q$ T$ @; o/ O! kexplain后会出现十列数据,下面将介绍这下面的十列数据。4 g" w) S' D( n- {; C* H- D

    & X" J: g, ~. V. z5 H9 jid、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
    " p1 F; x5 Z) f9 O0 [. J6 y3 q) I* J* R8 t) `7 S( g* ]7 O1 K' j
    先附上案例表:
    . J6 V7 W! b. D4 B  i' t3 \
    7 g2 j) y% q% F  _7 _/ T3 b7 mCREATE TABLE `taddr` (
    " Q. f' _/ `. F; D# y7 Y  `id` int(11) NOT NULL AUTO_INCREMENT,
    " f! h% z7 X- X- D  _1 ]8 o1 b  `country` varchar(100) DEFAULT '',: w: k& Y/ \" P+ ~. o4 r9 f
      `province` varchar(100) DEFAULT '',
    ; B# m" h$ m* Z: G+ b. @  PRIMARY KEY (`id`), k# x/ @6 \: O2 S6 i  P
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
    # W" H2 V! k9 _# h8 A% T/ o+ a; M/ v) R7 g+ n  K
    CREATE TABLE `user`  (
    ) K5 l) n% H/ O9 o  `id` int(11) NOT NULL AUTO_INCREMENT,
    6 A" w8 j6 [0 t. n  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    1 b3 F# ~' F, Q* ?% G. t0 B% {  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,7 R. ^& t) t. J" r. U
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    : @& ?& m; [5 [" ^+ P$ |  `addr_id` int(11) NULL DEFAULT NULL,
    / M9 K" p: E% Y) ^3 V  PRIMARY KEY (`id`) USING BTREE,/ K+ ?% U  `2 B  P/ \. {! [1 d: Y
      INDEX `addr_id`(`addr_id`) USING BTREE
    * m4 y+ o' W9 ^, g3 X) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;/ h+ |! i' N/ P: G* _2 l

    ) M$ ]( w1 Q0 K; ^, v3 o4 d
    4 b5 r% Q) r$ WCREATE TABLE `type_time` (
    ( @  l' c) y% G3 I% D  `id` int(11) NOT NULL AUTO_INCREMENT,- Z3 _" B& L* S4 t* j+ G8 S
      `time` varchar(255) DEFAULT '[]',
    ' ~/ |  S  s! Q6 l3 B5 D  `name` varchar(100) DEFAULT '',
    * U- W  I+ _4 n) f( u2 T( n. R  PRIMARY KEY (`id`),
    + E6 c% F  q1 a) W  Q7 P) I  INDEX `name_time_index`(`name`,`time`) USING BTREE
    - M! C8 C6 Q6 v) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8& r0 e0 e. Z$ d" I9 [9 Q
      e& K4 G1 F0 Q. W/ y9 _- |2 c
    一、id; i- U$ j; x( A" x9 J0 m0 z
    每个 SELECT语句都会自动分配的一个唯一标识符.
    8 y( S% Y/ S! o* E; I/ Q6 W2 w* [表示查询中操作表的顺序,有三种情况:
    & c8 z+ t" H$ g4 O% T6 W, Uid相同:执行顺序由上到下
    , z5 w( d  r8 N5 Q5 Bid不同:如果是子查询,id号会自增,id越大,优先级越高。: @& n* X6 r5 \  C
    id相同的不同的同时存在/ O3 \, D1 @# H
    id列为null的就表示这是一个结果集,不需要使用它来进行查询。: }( r( M2 m9 A$ L! D& c7 ?/ V9 ?

    + N5 y5 G1 z& I' J二、select_type5 {' }) Q' E2 Q) s
    2 j" v2 ?& X4 V  y9 K
    查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
    & y! v3 J0 O6 x3 k& H3 @7 f) ]7 E' S; r. l8 k8 x& J3 P
    2.1、simple
    $ h6 C0 i$ }, A: R" H, s: {表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
      S9 r& P( g# q% `3 x
    1 l, K3 s, D* G# kEXPLAIN select * from user1 A& v6 r  L0 L1 b& b

    - y, r4 W" Q$ z. P- l9 l 7.png ; S; @( D3 E9 \2 ~

    4 L$ Z9 x5 X. e5 f4 ZEXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
    4 n  a& C/ S/ r: Z- t4 k) D2 Z 9.png
    1 h( K( \9 z: O0 j6 W6 f. ]8 p+ T6 d5 B; i4 e
    2.2 primary! ?3 N. ~2 T; B: G  |- F. e
    一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
    8 Y3 ^8 q0 H4 M  _& |4 b
    . @$ b  d+ G+ K  U: x2 F; aexplain select * from taddr t inner join (
    6 }+ j# l  m: y% h( A) |7 L, bselect addr_id from user ) u on t.id=u.addr_id( Y: s  y# v8 L8 N4 p: y2 g/ v% [
    10.png
    8 h5 X; O2 @. }! Q5 L& x: T$ v. rexplain select * from user u where u.addr_id =1q5 C1 \) a% h6 I( s/ {% |5 ^4 |% }" W
    union all! O9 O$ v7 ^6 }3 z
    select * from user u where u.addr_id =2: S2 \6 B4 t5 d0 Z7 b, c
    11.png 2 J0 t% Z, f: m3 C) p' h
    8 k. J0 ]1 G: `4 i5 Y; r
    2.3 subquery2 r6 H* M( {& n  H4 q  G/ t
    除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery4 a) W' Q7 J# q& `' A! Y) z

    6 b# K% z" B( \2 e2.4 dependent subquery
    6 d; j( B  l+ e3 F7 V+ c7 e" r1 H- X6 J0 i* ]0 ~
    与dependent union类似,表示这个subquery的查询要受到外部表查询的影响$ k, f  W# e7 L$ E. K# W: a# R6 t

    ( w* U+ ~- F2 j! {  x2 mexplain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
    4 c+ y' p2 C. g6 m' D 12.png 8 ~' T: S& ?, {% {6 [: ^
    2.5 union1 h/ N5 a+ o4 M$ ]  p
    union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
    ! L- k3 x& t" d# W
    ) v! [0 _! Y% S5 o三、table
    5 ]5 Q# f+ k. s  L0 y8 e显示的查询表名,如果查询使用了别名,那么这里显示的是别名
    7 R9 x0 t! ^# |2 Z9 L如果不涉及对数据表的操作,那么这显示为null
    ; a5 D! I) L- s# @+ {如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。# I8 t( O0 A0 `" ~  q3 L8 q" t
    如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。- A- o1 |! X3 _& ?/ _8 l+ H
    ; e. G& Y7 b# @
    四、type6 ^6 \7 }; c4 q- u& X8 o" g
    5 A" z" A4 ]0 S0 Y1 B% o1 k
    依次从好到差:' o1 E0 d; k; P- |' e
    system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
    $ I; z  C8 Z& A1 c1 H* |0 iindex_subquery,range,index_merge,index,ALL
    # K; e* s- p: I. p$ v# O3 U9 f) s
    9 n5 v" M/ H& k' i& _/ C8 B9 u除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引8 ~5 Q+ D1 Q1 `3 Z! d, Y$ \
    " ~8 g6 M1 H# j( E' Y
    4、1 system
    # E$ O3 m9 S7 r1 C4 h6 A* K表中只有一行数据或者是空表。
    ) K: o* B6 R2 |( E* @: R; d* m) \& H" A& w+ ]6 q4 E- b; w; u
    4、2const- Q) w/ t) K: K" v2 S7 A
    使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
    * P% I' }6 L4 n
    * k/ d' Z; r! g' m) M4、3 eq_ref
    2 E" k" U; O" ~  a6 _8 R# ~关键字:连接字段主键或者唯一性索引。( Y5 U+ {; J2 ^0 O& s
    此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.. L8 a7 F) d1 d* A/ R( ]5 O+ R) y% m
    , n3 Y! {% {% O& c3 F+ z
    EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id' d" g2 _( e) d' J! I
    ; U/ y# o/ A( k

    ( [' u0 J' h& N( p( T 13.png ! K5 o+ n4 G' U0 P

    ! ]4 Z! F9 T- F5 x3 H) l3 J' P( ~+ g- Z  w# ^. ^

    4、4 ref2 @0 S' E. y: @1 U  @% R
    针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。

    EXPLAIN select u.id,u.addr_id,a.* from taddr a left join user u on u.addr_id=a.id

    14.png 2 f' W, E3 T( H& }7 A+ E5 c

    2 {9 s+ H  [5 E' h4 T9 b4.5 fulltext
    % {# J4 _! E/ w3 [- o全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引+ U) l1 O# k; L1 Y3 q4 u
    ! \5 q, X) ^1 J- U, ~$ ]! `9 b9 |$ N- H
    4、6 unique_subquery+ ^) k& ^- V  K  [2 T" c% Z1 @1 S
    用于where中的in形式子查询,子查询返回不重复值唯一值
    3 z7 P1 [1 S1 y( u! @5 }7 q3 G5 v! ^5 s  k+ a
    4、7 index_subquery
    . z/ R$ {% {7 s0 c- g/ G用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。2 \& `& X4 F2 e: J
    ! N3 c1 C. i6 S7 c% n' Y2 ?% f
    4、8 range
    7 {1 \5 `8 g+ x/ p索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。  |6 _: q! w2 N

    / d: w/ a8 o( zexplain select * from type_time a inner join (
    9 l/ d% ], s# h/ ]7 E& lselect id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id7 x/ O& f; ^& J2 l& g- _. z7 j
    . j$ O* x8 F5 X5 a3 F( T2 v
    ) ?* |5 H0 {5 [3 z5 ~' |* {5 Q
    15.png - M4 l6 P" @1 V6 K/ e$ i7 a
    ; c& Y5 t; h7 ^! @* U3 f
    4、9 index
    5 f7 ]7 D, q+ A" F4 s键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。; ~; `! c& \. U7 l- T3 N
    索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
    ! L  i' ]' w& x7 A6 m3 r4 W' B  S9 I# Q! o/ \) F. K' G( y
    explain select * from user group by addr_id8 x# o5 S1 ~% ?: }  b+ u

    7 D' C7 [1 J5 z9 Y/ ?6 G2 b0 I/ I5 K
    ; Y0 u& p) X1 R) x9 a
    16.png
    ; E$ L5 x# f* u3 o0 p4 G* S1 i# n  Q; u. z2 a, C
    explain select addr_id from user
    9 p0 ~' `2 u0 x0 t' h8 [
    * I/ b- {0 W7 u! o 17.png
    - \* W5 M* `6 O2 E  p( [0 U2 }, w  }0 j) @' X
    ; X) ^+ m. l8 W3 [- C. y) g
    4、10 all/ w+ L- Z  O6 g4 U) v( Z% D5 r0 G" [
    这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
    ) j8 n. R8 }& y; X0 v& H. T+ ?! o, ^+ [
    五、possible_keys1 `& Q) I1 t5 h" \# j4 p8 r6 V
    0 I( o% _# J! ^5 E) ~. S3 s
    此次查询中可能选用的索引,一个或多个
    % ]8 _1 [+ j0 z2 @
    / i0 e  }8 O8 L* ^( v六、key
    5 X+ }. x1 s* A9 g8 e0 Y查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
      a$ j3 l% {( I( V8 @$ _
    8 u; g4 ^2 r. U5 O  ^七、key_len0 w0 M5 N. B( A. m, Y

    4 r- ?: X6 s% \+ F用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查2 H. Y9 X# h: _6 s" V7 c6 L
    询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。3 t* A+ X: d7 a. R
    另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。: ]; H( t) ~1 `! [
    explain select id from type_time where name =‘2’ 用到长度303
    . g" W# R6 h& `# ~, s
    & n& N7 F& ?+ S 18.png
    4 I, r5 N: J/ L5 @& h" C3 y/ }explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 10712 X4 _% w0 W3 X4 c1 J5 [

    3 A; V: `* R' Y# I 19.png % Z/ _7 R, z2 W" m$ f4 w  B+ a

    & d* b0 z: I! r3 F9 d7 O& k- z- u八、ref6 ~7 }- _& K9 N  G: G$ K6 @  Y
    如果是使用的常数等值查询,这里会显示const# g/ G* A8 k0 v
    如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段* c; Y. q& P; D5 r/ m* ~: b( ^
    如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func& A+ v* T/ P: Y

    / e( |, a' z! I7 ]( x' S4 n* K+ _九、rows
    8 J" ~6 Q' ^  c& K4 G% W$ e: ?! \( M* {这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
    0 l& @, Z& v3 `: x- `* o  m% c+ l/ j9 e
    十、extra
    3 U# b9 u6 U  F! ]7 g; s# s这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:2 T" U8 j9 d: d- k( L" j
    / M5 I1 [# d- X: M& r
    10、1 using temporary5 a5 @, K& ]2 J. T( T
    表示使用了临时表存储中间结果。
    1 j3 `9 R$ p: S1 b0 s% `3 t( RMySQL在对查询结果order by和group by时使用临时表7 ~4 M7 N: U  O* ]: p9 o
    临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,  q7 o" X& u/ X( p
    used_tmp_table,used_tmp_disk_table才能看出来。
    $ A" H' \1 h, y" X2 e3 ]( C
    ' k& X- u# Y( q7 X5 i4 sexplain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
    % t1 |  S& _. `! v) m) p0 e9 K# k9 \$ I) _1 G( |; H$ M
    20.png 3 E! w- t! s3 j) I

    - `, F7 @/ P7 e- ~' Y$ H10、2 using filesort. c% h% j' {+ {$ e* k3 V) w" T
    排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
    4 Y8 r1 M9 H* ]$ A  H/ e
    " c& m4 Z7 S3 A: F" O' _说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。
    * ^0 Z$ v2 r( E. N1 KMySQL中无法利索引索引完成的排序操作称为“文件排序“
    1 t. ?; i6 N0 A1 f
    ; C: a/ T! M! M' ?10、3 using index! F5 ?) w) B' r3 m- c
    查询时不需要回表查询,直接通过索引就可以获取查询的数据。
    % z6 v% u. G' f# U: F' Z表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
    0 ]/ U9 R/ M4 Z( M错。
    5 v8 c  J! N6 ~# t! t; L; s如果同时出现Using Where ,说明索引被用来执行查找索引键值2 a+ X& W0 H: b0 u% k6 k, b
    如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。9 O9 `7 e/ t& o* ]

    3 q6 c* g6 z, ]! ^% F这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。0 H* M' b. G" a" L3 g
    ————————————————! k. _& W3 t" D; S0 W
    版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ( |# S4 ?/ v( D# W+ A4 {1 @原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629/ ?' _+ N- z3 X

    ( q! B4 X/ {2 P% @6 r- n2 U4 p
    , e' \; D/ s' t+ Y7 T

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

    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-6-11 07:06 , Processed in 0.334597 second(s), 53 queries .

    回顶部