QQ登录

只需要一步,快速开始

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

    4 C- N# F3 u) ?7 }  K" ^, @# umysql索引和explain的详解索引原理分析
    . Y, u6 G. `1 ]  w
    ' }/ B1 {* C% p9 D8 {索引存储结构( K$ O; t1 F( M. O; P3 ?7 P$ X
    索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引  L% {6 I. a, H7 W
    MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
    + s1 ^: B0 N2 X' A0 CMEMORY/HEAP存储引擎:支持HASH和BTREE索引
    3 q6 P: R- S3 W( M- b
    + r/ h8 H2 q; Z% p* a1 _B树图示- b! S& H6 E8 h0 w* B

    ; ~, Z) ^+ n; S7 Y+ rB树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。
    8 t* y' j( G9 P4 r, }3 h0 W# [# X6 v1 R( \7 s% H
    1.png ; D2 b- s0 r8 n" q% ]: D
    " z4 ~0 g& n8 B3 R

    - e( X2 |! ?; h" LB树和B+树的区别:
    ; d/ [. |& h, UB树和B+树的最大区别在于非叶子节点是否存储数据的问题4 [! E& N5 L4 W5 n7 j; K
    $ d9 n; e; N, D1 ?# p
    在结构上:) ]- N  ]/ h. Q
    (1) B树是非也只节点和叶子节点都会存储数据。% M* S+ ?5 ^2 J
    (2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。
    $ a; i% }1 F- B6 ]' c& _
    , V' U: x2 P+ \# q5 S在性能上:" A% V% u' U$ E
    (1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。
    8 G' R( D9 c6 @% U8 J4 _2 x(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。4 r5 K' G4 w3 U' U: K0 Y; W
    % f4 i" v$ A7 u2 W+ X: W
    聚集索引(MyISAM)
    8 |" C& l2 |# ~' f! I3 @  }* ZB+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集
    + t: {. ?4 w; m! x- ?: s- _索引。5 p* X; C" T% H# t, a2 Z
    聚集索引包含主键索引和辅助索引都会存储数据指针的值。2 K5 c+ E& j# D" D/ \# v
    - R- }% B5 {& |) L# |' ]
    2.png
    - D0 z1 J: G0 C9 F# o* ^9 O+ _: T6 D  W
    辅助索引(次要索引)8 x( E; o6 ^9 c: o, p
    在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,
    0 W6 `+ W9 i' `0 M# E1 X/ D# b而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示- G6 _4 @0 o9 k( z, g2 X3 r
    3.png 1 W4 |, ^- n+ P' K0 ?8 E0 C1 u& X, f
    同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。0 W3 R; \! V6 ?& P5 j, w
      y) i! G! f5 f
    聚集索引(InnoDB)
    ' J2 ]6 p- T5 ]" f3 q9 e- t9 C' P% b4 Z
    主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。- \) f, P' L' s: E
    辅助索引只会存储主键值
    # K% ^# j8 Y$ ~* r( s如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
    & h; n2 y9 d  c% I5 }, ^3 z  i& H3 [* G. N: [; r: Z# z* Y" [9 M
    主键索引
    ' F* E4 L, H$ u7 u, c2 l, L% ]/ w+ P9 |1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以
    / f" a) ]* H) Q; n+ [8 Y# z# s唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。( p( D  |0 I, t8 k8 f

    , ~; G! o" |  r4 C7 M  ]+ G; a 4.png
    ( @0 k0 u! F/ v% a- j0 ?2 S5 M" X/ Q4 D% f/ l' E* s3 W

    9 |5 _6 j# [& V& V6 i9 g- l( m* g上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。4 n: N3 n& F! D% [0 g- `
    5.png
    # k& {8 y. T" [- H; o1 K
    5 s/ n! d+ o1 C, M
      D6 x+ N( P# u 6.png : @! _+ k8 ?$ X+ D8 X  F

    # v2 W# e0 f$ o  t5 d" [, R" P
    mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。
    9 F4 _" C# ~: T; V* i1 f' N" G6 h; |! q+ X% T# M: x
    explain的详解
    * E& s* v# N) e9 s' d' o0 e
    & J: w, k# s& Z/ Q- g* I3 L参数说明:
    1 |. k8 d% i# @0 [: a' x6 q$ J$ {explain后会出现十列数据,下面将介绍这下面的十列数据。/ M; ]8 G* [9 S

    5 C" r- r! t3 q  g1 Cid、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
    1 ?8 J% m1 }# I* W/ K; X8 Y
    0 B& A# d0 b5 ~/ F: d先附上案例表:3 c3 F6 `% O8 \6 f. k6 u
    ( h- l1 `5 u4 Q6 X9 w0 f2 O4 s
    CREATE TABLE `taddr` (
    / j0 B& d9 _% i: P3 }4 ]  `id` int(11) NOT NULL AUTO_INCREMENT,
    6 Z+ m. r5 U7 r' P* d  e' l* y  `country` varchar(100) DEFAULT '',+ k3 G) f* S  }
      `province` varchar(100) DEFAULT '',
    * e: x/ P" J/ t4 m4 ?2 b# g0 g  PRIMARY KEY (`id`)) ~# W" |2 ?+ l; u4 C0 E0 E
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8+ p7 L' G" b5 |' t
    ; }, H1 Z. B! F7 I  P
    CREATE TABLE `user`  (
    9 b$ Z: j: i, g' d# I/ k) y- X  `id` int(11) NOT NULL AUTO_INCREMENT,5 G) g9 }- T* G1 X0 z
      `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    6 m( G4 j/ T. s  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,$ J4 |( f) ?" a
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,3 s! q2 d$ I& B  |1 W% p; o, f6 I
      `addr_id` int(11) NULL DEFAULT NULL,
    : R, `: G+ i' V$ W# c- e/ `  PRIMARY KEY (`id`) USING BTREE,
    * O! P  D- e4 S9 z3 S0 i7 x  INDEX `addr_id`(`addr_id`) USING BTREE
    5 \; g! ?& A/ f  A. A* M1 m) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
    $ C6 h* R& V, d
    1 J3 R% U3 s4 ?  E; f! U4 C0 O/ @. X3 T
    CREATE TABLE `type_time` (( j' _# ~* p4 E9 v/ X
      `id` int(11) NOT NULL AUTO_INCREMENT,
    - J& _% y+ u, ^1 `# m0 N* ?  `time` varchar(255) DEFAULT '[]',
    ' L6 @$ ?% W" h* l) N+ X* ?2 M  `name` varchar(100) DEFAULT '',2 N$ b( a+ l6 s# D/ s5 v) W
      PRIMARY KEY (`id`)," k# T( L% Z0 N8 t# m" q" J$ Y
      INDEX `name_time_index`(`name`,`time`) USING BTREE/ [# s1 G' J& ^3 L* l/ G$ ~! s& w
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf84 i8 \) x2 e% q* r) Y9 g1 X; k
    " O; I  h' z: c7 [- E8 H
    一、id4 U8 P, Y( R6 {
    每个 SELECT语句都会自动分配的一个唯一标识符.9 R$ Q. S4 a' X, P
    表示查询中操作表的顺序,有三种情况:4 A: E% M& [% y
    id相同:执行顺序由上到下
    1 |& F* U- |2 _7 G- q* uid不同:如果是子查询,id号会自增,id越大,优先级越高。
    & T; o( p) T/ |" [id相同的不同的同时存在
    . I/ d+ N( g  {4 qid列为null的就表示这是一个结果集,不需要使用它来进行查询。
    8 s& ^9 m9 L, B3 R5 {2 @) H( c, e2 p% f7 O
    二、select_type2 J9 l/ Z1 K$ k

    $ @8 z. {$ z) M6 ^' T0 [, ^查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询
    3 q" I$ e- A' O5 q: K4 x
    ! l# B9 c# Z; Z6 C6 c6 b4 m* Z1 s  m2.1、simple
    ' U. \. l: Q* V, |表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
    9 P6 l) G; W" q/ Y7 a$ q# r* |
    5 |! g7 }4 H) |6 U* zEXPLAIN select * from user7 J' p0 O+ V" O. M

    2 n  q; w; G+ {9 V) D6 t( A 7.png
    ! w, [% m5 P- b- p
    8 q9 o3 o* o8 I8 O5 S; s% F% p" yEXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id* y' ~* v1 i4 I% g. I& Q: y
    9.png $ T' ^0 [" H) L1 }/ B! f
    : A" w" L7 [4 m+ K7 M1 a3 i
    2.2 primary/ h0 B7 Y: E; P3 v4 E
    一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
    0 S5 Q/ d6 S" I' Z/ N1 W
    ! v7 W2 Z# P1 vexplain select * from taddr t inner join (! O& M& G- B7 }3 O& Q( t2 L2 H9 }
    select addr_id from user ) u on t.id=u.addr_id: c  p& H; X2 O) z# T, p" a: K5 t4 b
    10.png
    - d& r9 u1 u$ C7 X9 T/ o( j! xexplain select * from user u where u.addr_id =1q- C+ Q0 y; `* u' a* b6 D
    union all! ?, |9 P: J1 w7 W/ z) @" \4 B
    select * from user u where u.addr_id =2
    6 M' B7 k  r1 f" N; q" W6 F: Y 11.png + B/ T, K) Z5 B

    / w( p& L- G% l" F$ p2.3 subquery
    & m6 {$ {  r% U. w! l2 h7 e除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
    ' z' t2 `) ?& x6 u8 J7 G
    4 y4 g. n7 w1 a2.4 dependent subquery
      C$ q3 p4 S% r/ s9 {. V
    ' b  n3 T. ^( f* E! C) w. D与dependent union类似,表示这个subquery的查询要受到外部表查询的影响( F; n1 R! q$ m( G4 D

    0 X( B: R! n7 i7 oexplain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u) s* O" H9 p5 n9 ?- Y# ^$ ?
    12.png % z* d+ t+ D0 `! M4 n
    2.5 union9 [$ k9 c" K& F9 H
    union连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union5 ]* M# |0 T, Z2 ~  D1 r" z/ Z" B

    - _1 [, |  _: g+ H0 g( u# h( C三、table
    7 G; _& I4 j( ^, n7 M显示的查询表名,如果查询使用了别名,那么这里显示的是别名
    * \$ M7 ?2 y4 E: ]8 d. {: I1 Q如果不涉及对数据表的操作,那么这显示为null
    ! t1 \1 w& ]7 N9 O# N: I. ]如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。! Q$ h7 ?, k8 p, |1 o% e
    如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。' i. j' E; e. d* C- y

    6 E. z" T) O6 h# `! X( Y四、type
    ( R4 W1 u) t  @. c8 ~( o- S$ g. V2 w/ F5 g* a2 G4 ]
    依次从好到差:" M5 t8 B& h- l" `5 m5 r/ C$ P
    system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
    6 k. d7 F) C( v7 q1 r  M4 Vindex_subquery,range,index_merge,index,ALL9 m3 b2 a) c" X) P0 S
    6 N  }+ K. H( @9 n
    除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引
    + N7 u; L8 I% @3 E3 H
    % E9 k$ G# \9 h% }/ l, F* X4、1 system
    " X8 G$ u2 `% s表中只有一行数据或者是空表。
    ! P. k2 c: A+ S# |0 A0 t( n: T" J# L1 n1 S) E0 l: U6 K/ U+ f
    4、2const
    " R% t5 W7 a* Q3 b使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。
    * e7 ~9 s! i& k; m+ c& R& s+ j. S: Z& g3 Q8 L/ }- b6 C
    4、3 eq_ref
    , _" R2 E1 P7 X; W关键字:连接字段主键或者唯一性索引。8 _0 [6 c+ v" E! [5 X, Q
    此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.
      q: L) L3 E! v( K0 [/ I+ L0 L- i
    ! m( r- R5 M6 ], g' r$ @EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
    : J( {  v1 s, x) b# g/ \2 U, W1 Y2 `! l$ H7 b, [

    ; R# E* o. H" C" a* m8 _4 c 13.png ! P7 g  t/ W$ G! C2 m
    & J, X5 P# L! S+ j3 R

    & C: O6 `8 ]. Y$ }1 `& Y7 r

    4、4 ref
    ; ~2 t9 k9 v. H- R针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。

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

    14.png & ~: e  d' V  }( r3 m- D; v# \: O9 r+ U
      S5 l5 c. O+ v3 E6 N, u
    4.5 fulltext' l& d- F; ~3 i" N1 L5 [, H# x" g3 ?3 z
    全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引/ v5 d- s" T- Y& [+ {

    2 V# Y. d7 K! N- w3 O2 }. @4、6 unique_subquery5 }0 E# j0 H# {" M/ q0 {
    用于where中的in形式子查询,子查询返回不重复值唯一值: x- b. p. E! P, X2 \0 q8 x7 [; T

    9 @; B+ R# r# C  K3 S4、7 index_subquery
      f2 ]1 Y9 f& @用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。) g6 ^# `7 r' L" A
    / M8 C. ~' h8 P- C
    4、8 range2 ^) v) }3 O& q" {4 P+ r* t! t  c
    索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。/ t+ R' S) H8 ~! T% C* x& ~  s+ h4 A

    / K+ H% [' u+ C% o! Zexplain select * from type_time a inner join (
    9 i4 j- x- @5 O" ~/ qselect id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id
    2 F, S. E+ r; T9 P8 ^
    % y8 n6 D8 H* D% y6 U) g4 C7 m/ k' S
    15.png
    : s# W3 x+ g5 X6 c( D- b/ y6 u9 U2 h' u9 ]% C1 Q* P
    4、9 index
    8 g/ g& _( t) G  R$ b; \键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。1 L/ w8 [) U+ y' d3 W- Y
    索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。
    0 F' b4 u! U1 f5 M) Q0 F) P8 b$ k" N, o" v
    explain select * from user group by addr_id; H4 b# Z3 Z( M: H! ^& c
    " O& g9 s. G- b/ u5 Y) j2 P& ?! h) |
    $ W: v4 I. [4 Q+ H
    6 X6 u3 t3 I. T' P0 Z3 K
    16.png 0 t" c* L* J% j  n
    , z& G& C7 r& n/ q( R
    explain select addr_id from user$ J2 {0 ^( _% e" a2 o
    " N6 a' @: e1 X
    17.png : z6 @# N$ y6 H, G+ X
    8 Q0 x5 x) |) E2 \

    $ z- X8 n0 }: J4、10 all
    ) X  [2 k; o- k/ ^' K; m这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。
    2 R  O) q( n( t' Z, `8 L1 N+ U" L% P& F
    五、possible_keys
    $ d, r2 U; B, G7 z4 U7 D* j3 D4 a7 k2 t( ~, l1 f
    此次查询中可能选用的索引,一个或多个
    , g1 h  `- G- ^6 e2 H* |  x, Y% \
    / e8 U6 _2 V$ N9 g4 y六、key' n- v2 q; T. t1 N
    查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
    : ]. s. e6 J2 e& o- i1 @& f* d1 g9 @6 _$ W9 |0 |. a3 t1 |
    七、key_len7 r2 x+ R8 c4 Q4 J, ?& X9 Z
    % B, E+ d% l7 \3 T* \" h
    用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查
    7 S1 g, H& o+ y/ i4 p5 c询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
    % T7 }6 x) I  E3 w' O$ z另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。4 H2 `1 R4 q- J: d( r' ]1 x
    explain select id from type_time where name =‘2’ 用到长度303
    ! Y7 d  ^" x* q$ M, |1 {, A+ L" \- }
    18.png . f* n/ }5 P$ `; |5 B, O! o) Y3 O) p
    explain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071
    8 e( r1 [5 |( f" s6 t0 t6 w3 x1 K
    2 u5 L# n8 K7 x 19.png
    . Z( F  z1 X* S6 k& Y! g5 o- r, H, ?: t
    八、ref
    : K7 E$ C* L$ ]0 a如果是使用的常数等值查询,这里会显示const
    5 P- n7 P9 ?" Z/ ]: I如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段
    * ~2 I0 C+ Q$ `/ y& Q如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func* ^8 K/ i( ~3 C. k! ]* l* l
    % T0 k0 O- F) f0 U7 c5 F) k
    九、rows- o5 z% [; q' u, i: j* h$ F
    这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)
    / T/ D  M1 f6 W3 y6 v: O% a" n- `% `* W/ L  H# Q9 S) @
    十、extra
    3 {& w4 b, w- ]$ O: F- I) A. D这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:
    . ^, p" o1 L( x7 c) q7 x8 O
    6 ~- [/ R3 D5 ^' B1 Y10、1 using temporary- T7 y- c2 v) B
    表示使用了临时表存储中间结果。
    - O0 b4 h3 D' f+ V) R8 lMySQL在对查询结果order by和group by时使用临时表3 H) k* {9 M. l2 x0 O) f. o; x5 [
    临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,
      |$ s) m( u4 `& h" l6 c- y- A% _. Bused_tmp_table,used_tmp_disk_table才能看出来。* N5 N. J- D, L, W" w- O( P8 I

    ( C; q2 a+ q3 k0 Sexplain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id
    2 x3 ?  h- X# Z0 c4 ^* z% G
    $ R! @5 C; Y% j: m* E 20.png   B5 _% Y0 h. l5 ]

    5 z# f0 m4 q9 U$ G10、2 using filesort$ d: u5 e8 g" D# w# o0 d- ~
    排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
    : H& ]: n2 m) F4 f' [3 @
    - ?& r: J. e% O4 X说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。# @9 f. _+ v( c* l7 f
    MySQL中无法利索引索引完成的排序操作称为“文件排序“. K, g4 {4 z& O

    1 s& W0 t* Q4 {! F% A. m10、3 using index' d1 z" \( N: \$ w( Z5 R7 C5 y
    查询时不需要回表查询,直接通过索引就可以获取查询的数据。& x" }( |5 f0 \" Y2 M
    表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不
    1 J  U. q0 y* v错。/ V1 t7 I0 b1 g; _3 C2 F  ?
    如果同时出现Using Where ,说明索引被用来执行查找索引键值8 a0 |5 _1 M7 ?6 j
    如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。
    3 B4 ?) i9 i* ^! [5 V7 b+ @! A+ K2 w% s  _. Y6 n6 e4 r6 R. z
    这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。2 I! h4 z+ k6 K9 c+ M
    ————————————————; `' q4 ~/ a+ P9 f+ F
    版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    - J% P! ]) G, ^" w1 C* [& ?3 U原文链接:https://blog.csdn.net/fajing_feiyue/article/details/105616629
      T& z) V2 j( z/ x, M( q. D2 }
    " z) o0 N3 U' q: L* ?  |8 m9 U% o. N2 Q! ^7 Q

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

    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, 2025-9-17 15:35 , Processed in 0.369581 second(s), 53 queries .

    回顶部