QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 1740|回复: 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

    - N, G, {, R5 m- O& b- U1 P! ^6 cmysql索引和explain的详解索引原理分析4 \  u/ @" Z+ d- U+ E7 u! w, N1 ^* O
    & w1 s) A( @1 j- _' C& z3 _: o1 a
    索引存储结构
    - d' _5 v# f0 T# ]. Z" F& t索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引# o3 p+ `2 E& V+ ~' ^
    MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
    $ V1 `9 {- z  ^MEMORY/HEAP存储引擎:支持HASH和BTREE索引5 j  c8 Q- ?2 Z, g& |- ~! {9 [0 Y
      P( P7 T/ J3 N; @! a
    B树图示9 W# b, S) U) k# B! O) m

    + Y+ J4 h# s8 Y1 f& q- Z4 MB树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
    ) f  {7 u, i% R: T8 |* m6 S& f
    6 [- m3 y# \. f( P$ H- y0 r 1.png
    + ~3 a& Q; |* M$ B' R
    ( [9 X' k3 u* |$ t0 X( y# [/ U
    $ m# {, l. n+ g( Y" NB树和B+树的区别:' _' j& J7 y4 L6 Z$ V% V9 g
    B树和B+树的最大区别在于非叶子节点是否存储数据的问题
    2 J* ]* s. A' L/ V1 `3 v. O
    / g9 v3 U: L/ {6 I$ f9 y4 ?6 N4 X在结构上:9 W5 f# S0 l2 G9 K
    (1) B树是非也只节点和叶子节点都会存储数据。; g- F! R2 ^/ }) \
    (2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。$ M9 m/ Y/ F9 S8 {) x0 x

    % W$ T' A6 B  _: c, S7 v1 C+ T" g在性能上:
    + D8 h; d, T( u& l+ I  c9 w(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
    2 L* Z5 p8 D% R& ~& |& Z(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。
    9 s& [( V+ O0 O9 c6 Q4 p+ P: y7 t; O; _* c5 g  u  A
    聚集索引(MyISAM)/ L8 f& y5 L7 e% Q% K+ e1 G9 w% C+ M
    B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集+ X9 L8 {9 a: z/ v
    索引。
    5 G, _' z4 @1 k! c: Z. v+ s/ k+ q聚集索引包含主键索引和辅助索引都会存储数据指针的值。7 R% }8 V4 H  W: R
    ) R0 m, c; Y  _3 x$ L% ]
    2.png   P8 L1 `" X; G1 h4 T

    1 m  \! [2 d" M- [. A8 W辅助索引(次要索引)
    + }6 q6 I4 W2 v, L. t# Y$ A% s0 a$ X在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,. B" K5 \6 A# W& C# h: ~
    而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示! B) y" l0 ]0 _
    3.png 7 l4 ]- x- Y* p. ?2 I& J# C
    同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。$ P& f8 f+ n( v& s( E3 y
    0 e( z: s: ]/ t; W: a: Y$ ^6 v9 m  y# o1 i
    聚集索引(InnoDB)" d% a: r3 u: H( ]* U( @

    1 F* p% I( T% j主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。
    : _( _' z) P& g+ M辅助索引只会存储主键值
    . O6 T* ^+ }1 f( H/ s1 l如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
      y- J0 @+ d% T7 ]4 r5 J: X" g6 Z3 T2 k( Z1 O1 ]" N6 K/ ~  I
    主键索引
    + A) @: J" Z$ c8 T1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
    ! `2 u2 n# u* b7 ?5 F唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。
    % {# |' Z, k& ?5 I& e% s. `0 [& P! L0 M8 l- V' j! ^0 ?
    4.png 2 i: P& f$ J5 K* Q" d! T

    0 ]% |5 [0 Q8 R/ b8 g4 r
    - O, x# M% A0 p! {( H- N. l: c. t7 s上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
    & H8 ~' r; U' q) l 5.png / U& x" f( w' \, U# D
      ^7 p! i* d: a# c8 n: z4 R

    2 m" g) W7 T2 U 6.png
    " g' K9 U* i) E
    / i9 X8 `0 J& ]1 ~# N# Q1 j/ a* n+ r" U3 U5 m6 X9 D  ~; ?
    mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。
    , `" i2 u  R! I" L" W
    4 _4 O5 d+ _8 \explain的详解
    ' M( M9 e' }' j7 n  Q9 i4 g% E% O# ]  t/ k( Q* \: u) Z
    参数说明:
    ! T$ z9 c7 x9 x, ~explain后会出现十列数据,下面将介绍这下面的十列数据。4 S* w) d* ^4 k1 |* W' C
    / r6 `/ K# u! |& W9 }, k& k
    id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
    . i8 L$ ?7 x' y! P- u) W1 ~
    % O$ g* ^+ ?$ ~/ n9 ]( @先附上案例表:
    , q5 j1 ^  a, L3 T6 O+ F, t5 z! `
    ! P1 _' d/ ?, s9 z' Q& pCREATE TABLE `taddr` (
    ; f, G( p7 J2 S, R$ B' I  `id` int(11) NOT NULL AUTO_INCREMENT,
    " C3 _& u7 T. O6 o$ a  `country` varchar(100) DEFAULT '',2 T7 D9 A- i, G7 Y9 p* o
      `province` varchar(100) DEFAULT '',0 ]8 ]% |7 o4 T! m; i
      PRIMARY KEY (`id`)( a, c; l8 v& ]" t) _& t
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8+ y! L+ K2 g1 I4 c- M7 V4 h

    ( Q' f- |/ K' f# A* p5 U$ N& |CREATE TABLE `user`  (& z1 O8 y! N/ o: u7 N# Y
      `id` int(11) NOT NULL AUTO_INCREMENT,9 i3 j' y% x) H0 b# {/ H; U; I
      `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,  l" O5 K+ ~3 n$ G3 j
      `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,% ?$ S, B* @- y  a: i& t9 C; p
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      Q' `: @6 \: w# ^; l9 g' ?# ?0 T  `addr_id` int(11) NULL DEFAULT NULL,8 Q, [5 N0 x* Y$ ]
      PRIMARY KEY (`id`) USING BTREE,
    3 W; E* u6 A& o2 C1 e  A- Y" q  INDEX `addr_id`(`addr_id`) USING BTREE& X" o* E" j6 F1 ?* R2 ]5 j! K
    ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
    . [2 I  y1 C8 J" ]" J% d- s
    ! h% H2 N/ v0 L) B7 K5 F5 I! ^* X/ A+ A% h7 j5 k
    CREATE TABLE `type_time` (
    , O' p% h6 @, w- v  O  `id` int(11) NOT NULL AUTO_INCREMENT,( R. n( d. C1 m8 n
      `time` varchar(255) DEFAULT '[]',+ V, d  }2 B/ x
      `name` varchar(100) DEFAULT '',
      F  h( s) s% t8 p  PRIMARY KEY (`id`),
    ! C- |, \! l% M% }1 ?  INDEX `name_time_index`(`name`,`time`) USING BTREE  V9 d* g" f* T( K) ]
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
    ) Q  h8 X+ Z6 S7 P6 s
    5 h% s7 d3 S1 }  K8 Y' _5 V一、id
    & R( t9 R/ {# Q. I8 L& W5 d每个 SELECT语句都会自动分配的一个唯一标识符.
      L" v$ H0 \% Y& A' P( Z3 B表示查询中操作表的顺序,有三种情况:
    1 l/ q+ p. H1 [; Oid相同:执行顺序由上到下" ]9 @. N4 p- i$ x
    id不同:如果是子查询,id号会自增,id越大,优先级越高。
    3 H& N/ }+ P1 }. p! t5 b- oid相同的不同的同时存在$ \" s1 x+ W7 t' {% I8 g1 Y( E2 R2 J& w
    id列为null的就表示这是一个结果集,不需要使用它来进行查询。
    3 Q+ U/ n9 c# B  c; v: h# }* k' y
    - G  I# _* O9 I5 J/ K/ |% k) B二、select_type
    & @, _4 N9 L5 W5 \) ]
    * Z8 v7 q+ t, _( A查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
    8 V. c, ]3 @& g$ _/ {. F9 P+ L: s3 Z) r( S! {% Z
    2.1、simple
      B/ M/ I8 `8 Y7 U% j表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple5 ~; B1 {1 z0 J; U% a  U' r
    ) L7 t( V" W* _3 I" d% T5 s5 z
    EXPLAIN select * from user5 {7 I( H) ^# S" Y

    - G$ X- F4 |/ |8 {( w* } 7.png
    : m* G6 _; F1 C/ m. t
      S0 ^& ^% B% ?% X' Q' VEXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id- Q3 s  ?* q1 Z8 W( q" {" S, h
    9.png
    ( f( G' X8 w, I% G2 P/ l) Z4 i7 V3 s) C
    2.2 primary
    1 R* v( Q+ P9 e" f# ~一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。0 }/ h0 V- j( L* ]& z) u; E

    1 }/ w" w  z4 w& Mexplain select * from taddr t inner join () p0 e  _9 K* a( \" l
    select addr_id from user ) u on t.id=u.addr_id
    & j+ J7 v* a- |+ @7 n( e 10.png
    9 O3 \) }& z" t9 S9 V) O9 L) |explain select * from user u where u.addr_id =1q
    + D! O' J5 p4 R/ F2 \' j/ e! M1 runion all+ z8 k' k- P2 n, A. R: \& f! l" D
    select * from user u where u.addr_id =2
    1 @9 w  R/ r; z/ N. o 11.png
    " n& a/ d7 m& ^! j9 P1 n" k9 `  L, R$ Z# P5 @* ?( ]
    2.3 subquery
    : P) c, T' P% l% ]0 T除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
    4 v. d4 L8 P. n" u% F. Y
    & R2 a/ H- M$ U) C% h$ P- `1 k- K, d2.4 dependent subquery% D  x4 b+ d4 x# O

      y# O$ z3 d, n9 V7 X9 T与dependent union类似,表示这个subquery的查询要受到外部表查询的影响
    , I) a; p5 x& [. T2 a: t  u  r/ f* U* K* R* Y+ o' S1 E9 J3 Z
    explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
    ; U2 {( Z7 D$ d1 {. c7 ?4 j 12.png
    7 B) H3 _0 a6 g6 E& M2.5 union, E. y  O, k: G, u; |
    union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union
    ; c& ]( j5 v6 B& f/ ?5 d$ F" E- V! O0 F  T% w
    三、table5 K) A* a3 y' h; q; b
    显示的查询表名,如果查询使用了别名,那么这里显示的是别名4 F8 m$ ?9 W0 G7 q  @- ~2 E& W6 Z7 X
    如果不涉及对数据表的操作,那么这显示为null
    ! c5 g2 N/ G; O+ u" d6 E- C' t' r$ Y如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
    ( M2 a1 j0 ?' z) D! ~" p0 @如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。
    ! `5 s! _3 m7 z" u6 ~+ y% i; d+ ^4 ?+ G$ J/ H6 t: E
    四、type9 e4 q- ^$ @9 Q& p& W& z
    0 x7 Y' ^9 X! U
    依次从好到差:2 ?# h  w" N9 I
    system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,: B; O! l9 g# q+ t' l4 ]7 _
    index_subquery,range,index_merge,index,ALL
    . c6 W4 O$ N! e- |/ e
    3 u: S1 j8 _1 Z0 [除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引
    1 l5 w% d$ V5 \! b0 x: M9 L( V
    ' j/ C, u, I5 x* W8 Z4、1 system
    : r4 t  L( x' _; O, |表中只有一行数据或者是空表。# {) {9 c2 S* s  T4 R8 ^; K/ b
    5 O- g( j4 C5 R" A" v: r) \( ]
    4、2const8 v: S& i/ g- O; e. c
    使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。5 d2 ^6 u& \4 e' ~( t
    6 K0 |1 i$ R% I8 \' [! S  R$ v
    4、3 eq_ref" i  h0 F/ [( C! p$ g6 ?) r- P
    关键字:连接字段主键或者唯一性索引。
    3 o/ A5 e* q, J; F/ j3 O$ l# r; ~9 f此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.
    ! c8 b9 e6 z8 l/ c% a6 F! Y! D6 {2 e
    EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id! e6 q/ K0 `8 {0 e! y" S

    + }" Z# E/ d9 N) Z( K+ N$ c: y+ L8 X9 T. X9 A1 R5 E' R
    13.png 4 h6 {* r4 x. O/ n4 ]% I

    ! m; q7 [$ s4 m: O3 ^, c8 O
    " [* c5 b; k4 d# z6 e- @

    4、4 ref
    ! w/ d$ F. f, s, o: E; n3 g针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。

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

    14.png
    # v5 c4 z  U5 r5 |) Q- c+ J  l! N0 T5 F. s; \9 ]! ?
    4.5 fulltext/ `! n8 a6 s- h1 c/ l3 C$ ]. O
    全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
    2 L2 h1 W4 c2 Q/ s$ ~, y5 H( }3 j5 c$ s- I* E% D  x
    4、6 unique_subquery; A9 J. N% k8 C% }
    用于where中的in形式子查询,子查询返回不重复值唯一值+ C! b! Q5 U# {- ]; I$ J/ s- H

    1 ~" |) y: x4 o7 }/ O2 U+ [4、7 index_subquery% [1 T) y4 M8 k! P6 i
    用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。
    2 ]9 P4 ?+ E; p# L$ D  r! U0 I6 z& I3 U: r, R
    4、8 range
    . h' E0 k$ ^8 \0 u' {: O索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。
    9 S$ N2 y/ n! l/ u; X* L: j% k' R3 R5 [
    explain select * from type_time a inner join (
    3 M& {2 G, K6 k$ _select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id; ^- [: u; h3 r4 s6 E( L

    8 w$ ^0 c9 u  F! Y  u1 ]
    - Y/ R5 w4 o" N 15.png
    ; L2 R+ L+ X! h2 w# g: O  T2 R8 Z2 x" ?  U  P. x2 ^1 \4 F5 t% y
    4、9 index
    ) i% |3 n& q) {( V键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。
    2 q( \8 d( @% G7 S" i索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
    * M" i6 h( j0 |5 r: Z* c1 o. ?( }/ V8 p* o4 o
    explain select * from user group by addr_id
    1 L+ N8 Q" e$ g# r; h* t+ v6 A6 h/ R0 e& [) C
    # ^* a( `# ^% w) [# D- f/ r
      ^# y! B" ?* H' m, ?, U+ n
    16.png
    0 C, q% g) ~; v' q$ |& L* x2 p2 N8 b2 o  \; Y* B5 n
    explain select addr_id from user! G. N0 ]6 ~, o% Z  o! X

    8 S# I% i% n3 e' @" m+ M, G2 @* P 17.png & Q7 r9 r6 l+ `! j7 E0 m1 y1 Y  R9 V1 E
    1 }0 |5 E  u- ^
    ) O: T8 A: P8 X! \
    4、10 all
    9 D. `% q. T9 a! W5 O5 @! v* D9 U这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
    9 n5 C# t) X/ |7 j; m3 g9 r: s- s; f" g* E
    五、possible_keys
    ; _' X8 z; [( M4 m# N  Q! ~" x% E" M$ q- J
    此次查询中可能选用的索引,一个或多个
    3 q5 H6 D$ l& _3 v& n6 l4 \7 i
    5 t& e. T' W6 t: V2 D* c六、key
    # w+ ~* A! U! q- w- |查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。& K  l  G1 A2 l0 }' N+ Y: v
    8 {. ]$ u9 b/ y7 C, z. y
    七、key_len
    8 Z4 v7 M: V$ e; N/ ?+ P! ~7 S2 O
    : k. J3 |7 q/ _9 q2 w1 F% Q4 M/ b用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查' _2 F7 z6 r% [: P& y3 b8 F
    询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。+ f* E, r1 _' I, f9 c/ l0 v
    另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。
    ) M0 @- p8 a  d; z+ cexplain select id from type_time where name =‘2’ 用到长度303
    / Z+ Y& \1 [" q# e+ o% g) J# B$ D# }7 V6 }1 |3 `
    18.png
    2 A/ g) c) ^4 {explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 10711 h' Y/ W+ t; R4 [' u  w
    3 @( ]9 ], g6 X- Y$ P( {
    19.png / {8 D% Q* W+ Y& k' {  R3 l" M

    , P  z$ G$ r1 f, ?八、ref
    5 y, Y5 {) S/ d6 d7 ]  D; k# F  _如果是使用的常数等值查询,这里会显示const6 E- y: f5 W, k: }( {% `
    如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段4 ?' s/ C. N1 T  W" b8 G1 D
    如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
    3 s' I  J" E+ X- w$ q3 V9 r
    $ t7 h. m. Y; r九、rows
    ' O; Z, z- z8 _* x; m这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)3 Z  S) {+ Z3 Y" s+ O/ f

    ! X0 z8 ~: [. B: L, Y& @十、extra3 U4 D4 [5 [3 N& R: l- |! U
    这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:4 A5 ]% H+ f5 F: R9 w& N0 {1 V1 k" c

    2 s1 Y/ a1 h2 W" ~+ ~% M4 V10、1 using temporary
    2 d* D; i$ U. E表示使用了临时表存储中间结果。  Y) V+ \7 a$ o1 M/ P7 G  ^
    MySQL在对查询结果order by和group by时使用临时表; s5 E% w# S, R3 d$ H, T% e
    临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,
    . N% q; Y& h$ W9 vused_tmp_table,used_tmp_disk_table才能看出来。; v. \8 @2 Q' a4 J- ^

    ( X+ a2 o" D/ f) ?; K& Cexplain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
    ' h' Q% W3 e$ _* d3 I1 E9 `: W) l2 a% B+ n( \; w+ n
    20.png
      w/ X: t2 D4 E9 c
    1 N5 z3 U, I- i7 j; I# d0 O( S( y10、2 using filesort1 N( ]6 [9 E. b! H' M
    排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中7 ~8 ^1 v# h: Y

    + s; {; V4 ]7 J1 ^说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。+ E+ Z! m7 e/ G1 l- K: f2 N
    MySQL中无法利索引索引完成的排序操作称为“文件排序“
    % t( C" d% P) r4 E9 v- |2 B( [
    , u% R! ]/ L, {! V5 w10、3 using index
    / H% n* s/ A% \( |查询时不需要回表查询,直接通过索引就可以获取查询的数据。! M+ t! }( }& H
    表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
    * E7 S& \3 B9 B& L: w错。
    ) f( I  k3 c6 u: l) ^: v* ?4 {如果同时出现Using Where ,说明索引被用来执行查找索引键值
    * O/ Q: o5 R) P7 s( T如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。
      g# C* i$ R; ]8 G9 O
    ; n2 I, T1 _  o! X3 K这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。
    0 ~4 T, e  `  q————————————————
    , z. M6 p9 [, O' Q, ?: L版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    8 ?- u0 C2 ~+ L$ j原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629' K5 k) d' g0 C' k
    . I+ h7 u3 U& G, X4 P6 Z5 G8 }

    1 [% }. d' z. a

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

    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-9-8 16:37 , Processed in 0.331406 second(s), 54 queries .

    回顶部