QQ登录

只需要一步,快速开始

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

mysql索引和explain的详解

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

5250

主题

81

听众

16万

积分

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

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

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

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

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

    * 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 \- o1 h. `. p& j8 c4 m: A: M" n; u
    B树图示" j" R+ L2 e1 \1 i* d

    ) v  n! w5 ^+ f6 G7 pB树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
    3 h! B9 z* N  O7 s% L8 C# c
    , N8 T) G* F% b) L- Z% q  _$ { 1.png
    / ~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; o1 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' BB+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
    # 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
    2.png
    ( }  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 3.png 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 4.png # 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
    5.png ( a0 H$ ?9 ?, u6 p
    ; J$ x& p: _: E) G; @" p) D
    & C* ^9 _0 [9 l6 q+ I. i% T
    6.png : _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* P1 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$ Pexplain后会出现十列数据,下面将介绍这下面的十列数据。, F' S) e* h4 Y+ I+ X

    ! @8 S! _. r7 Z/ ^- R- vid、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& aCREATE 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 aCREATE 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. jid相同:执行顺序由上到下+ 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 wEXPLAIN select * from user
    3 |5 [7 n7 g: n; B5 M7 Z/ K" D% P+ V1 Q, Q  W/ y" u3 e
    7.png : I. `1 _9 j* x7 {

    : x! M. D0 }( @2 B/ v+ |8 jEXPLAIN 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 9.png ! 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 10.png 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 all8 [7 n4 Q+ Q% o% h
    select * from user u where u.addr_id =2
    9 o3 [, P+ j- A/ [# c" r 11.png 1 P" w! b2 m! S1 R

    " v8 s1 z0 Z, [! r$ X- x3 q2.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' aexplain 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 ] 12.png
    & @% N1 G" W: L& ]3 L+ Q+ o1 W2.5 union
    # e  z; v% _, i! N/ Y5 Nunion连接的两个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( Esystem,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 j2 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, I2 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& V1 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 13.png . 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

    14.png
    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 }. \
    15.png
    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 16.png
    - [. 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 17.png
    % t2 K, z# ?( Y( g/ Q
    ( Z) G5 _0 u# v
    ; t, a9 ~( J) z4 }: ^" K* C4、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 mexplain select id from type_time where name =‘2’ 用到长度3035 \' k. c1 n5 i
    9 h% v( t( l6 W+ r  A2 y$ X% G
    18.png $ {# 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 19.png
    / 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( i10、1 using temporary
    $ Z2 ?) y8 Q2 Z% n4 B2 E表示使用了临时表存储中间结果。
      K; p1 ?1 C8 j# [$ S$ lMySQL在对查询结果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 20.png # 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

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

    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, 2024-4-27 04:32 , Processed in 0.388568 second(s), 53 queries .

    回顶部