数学建模社区-数学中国

标题: mysql索引和explain的详解 [打印本页]

作者: 杨利霞    时间: 2020-5-3 15:46
标题: mysql索引和explain的详解

+ z, w" e  |0 V) s( Y5 u+ b0 n3 I) Smysql索引和explain的详解索引原理分析! K: f% r# O6 R* w

" i6 ?4 u: C/ ?6 w" \1 j索引存储结构
4 a. l" u5 A: R3 n2 C' p! f索引是在存储引擎中实现的,也就是说不同的存储引擎,会使使用不同的索引% H% j4 l' Q9 B. o. ^3 T
MyISAM和InnoDB存储引擎:只支持B+ TREE索引, 也不能够更换
( Q2 d/ S! R$ @MEMORY/HEAP存储引擎:支持HASH和BTREE索引2 a! y# a' j% m+ u; B5 \9 H5 J
2 v* q; t) w( `5 y0 i
B树图示2 ?( {9 i, |. [7 f2 c
: s' m! R7 S, K5 X3 E- C" m# j5 _
B树是为了磁盘或其它存储设备设计的一种多叉(下面你会看到,相对于二叉,B树每个内结点有多个分支,即多叉)平衡查找树。 多叉平衡。7 S/ p; r/ d; r. U

! W5 O" b* x: l 1.png , l! z) ^- U9 D3 P& D2 [" _1 f
* I$ Q5 Y+ C4 b$ q4 I& n
2 g/ |5 G6 G+ ]5 I
B树和B+树的区别:
, \* B$ D+ H/ T$ qB树和B+树的最大区别在于非叶子节点是否存储数据的问题7 B2 b+ N/ J4 m6 `0 l5 t

. _8 b9 J% x; ?, _在结构上:) s% D& N# k  m5 U$ b4 H2 l0 j
(1) B树是非也只节点和叶子节点都会存储数据。+ |) C4 a9 t4 V' f% J1 c' k7 k
(2) B+树只有叶子节点才会存储数据,而且数据都是在一行上,而且这些数据都是指针指向的,也是有顺序的。
! m) ]: K3 S6 s8 H- B9 V8 l) ?: ^$ K; l& v% A
在性能上:! a( ~5 y, I- S4 R0 Q$ d
(1)对于B-树相对于B+数据,B-Tree因为非叶子结点也保存具体数据,所以在查找某个关键字的时候找到即可返回。而B+Tree所有的数据都在叶子结点,每次查找都得到叶子结点。所以在同样高度的B-Tree和B+Tree中,B-Tree查找某个关键字的效率更高。B-Tree在单条数据读写有着更强的性能。. l% W; [9 ?. o) z
(2)但由于B+Tree所有的数据都在叶子结点,并且结点之间有指针连接,在找大于某个关键字或者小于某个关键字的数据的时候,B+Tree只需要找到该关键字然后沿着链表遍历就可以了,而B-Tree还需要遍历该关键字结点的根结点去搜索。这个也决定当连表查询的时候mysql比起mongo有显著的优势。更重要的是由于B-Tree的每个结点(这里的结点可以理解为一个数据页)都存储主键+实际数据,而B+Tree非叶子结点只存储关键字信息,而每个页的大小有限是有限的,所以同一页能存储的B-Tree的数据会比B+Tree存储的更少。这样同样总量的数据,B-Tree的深度会更大,增大查询时的磁盘I/O次数,进而影响查询效率。
, ~+ v) ^5 }; r7 y. x
1 O/ u; a8 ]2 S$ f  a. Y" `7 U! h6 L3 W聚集索引(MyISAM)
# i/ w9 D  p* c  _B+树叶节点只会存储数据行(数据文件)的指针,简单来说数据和索引不在一起,就是聚集$ U# v% y# n5 B1 |5 n7 I
索引。
/ L9 X" ?3 Y; G( U聚集索引包含主键索引和辅助索引都会存储数据指针的值。5 h) t5 ?& ?. m# g
1 F9 d+ ~% i' i, I; W& u8 g+ c
2.png 7 V4 ]" Z% P8 i; k

" U- z' q& F+ R' g辅助索引(次要索引)$ p& _! [; o; ]
在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯一的,: P  G$ \' w! C% @
而辅助索引的 key 可以重复。如果我们在 Col2 上建立一个辅助索引,则此索引的结构如下图所示: r) B( y# O  |+ r4 }" U/ O
3.png ) z! Z- U' d' V  n4 u8 W
同样也是一颗 B+Tree,叶子节点中保存数据记录的地址。因此,MyISAM 中索引检索的算法为首先按照B+Tree 搜索算法搜索索引,如果指定的 Key 存在,则取出其data 域的值,然后以 data 域的值为地址,读取相应数据记录。
" {& j- _8 q' r% W6 t6 s9 _
" i, @- ?+ W& _: D; U- x聚集索引(InnoDB)
- `5 t! c9 e7 n4 Q  r9 [; q* e2 {1 X
主键索引(聚集索引)的叶子节点会存储数据行,也就是说数据和索引是在一起,这就是聚集索引。1 @5 G2 J7 b. }$ E& M
辅助索引只会存储主键值5 K' e% _6 T5 ^
如果没有没有主键,则使用唯一索引建立聚集索引;如果没有唯一索引,MySQL会按照一定规则创建聚集索引。
/ t; n- f& R: T. p5 d3 S
  {* D. w1 L. A$ L  V主键索引" P* K' s: F- w0 ?$ K7 ?
1.InnoDB 要求表必须有主键(MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以/ h: ^# f. L- Y2 O/ o( o" L
唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。; q% h! E" |- U' g/ P

! V3 Y1 y6 W2 D" r" b 4.png 6 L3 K: s) ?4 X

- w, h, a; T- k9 J
6 T7 t& D( ?1 u  J+ d* d上图是 InnoDB 主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为 InnoDB 的数据文件本身要按主键聚集。
* g* V7 \$ p9 N 5.png
& S1 c. {4 r' c  u, G! ]/ @9 ]: w" N- f$ `. d% {( h
( M) a5 k1 C0 M6 B! d5 D
6.png
) z. O/ F1 E* Q" H6 k2 O% Q1 d7 ?5 a7 K" ]' G' @
( H* `* |# p! L2 R/ ^- `6 T
mysql创建索引的时候和用法与索引息息相关,要建立合适的索引和理解一些索引的执行计划,就需要认识索引的结构。! M3 [# i6 K/ G8 e* C7 \
$ \8 h/ Z6 m7 w. G
explain的详解" k9 G9 s+ ]6 x0 I2 h3 V
. K0 d8 o7 C- ^' y
参数说明:
4 }) u6 a( Q" a! ~$ P; h- i2 Sexplain后会出现十列数据,下面将介绍这下面的十列数据。
4 p8 U8 h& }3 c* b9 Q( \" e  r0 S
id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
" a; N( u$ {: F, u
2 o0 H" u; o, k5 @$ d3 `3 Q7 V$ [& {  R先附上案例表:6 h9 v7 }& y5 t: Q$ j; Q
/ ?# \5 f+ h5 H2 j- z5 o7 ^
CREATE TABLE `taddr` (
. T6 a$ F1 `% d' @  `id` int(11) NOT NULL AUTO_INCREMENT,
# M$ _; ~8 G2 N4 ~9 D. M3 @  `country` varchar(100) DEFAULT '',
* q& R+ {8 c  N$ g! g8 @  X  `province` varchar(100) DEFAULT '',
/ t& g' l: x* q( z* t; v  PRIMARY KEY (`id`)1 K  @+ N+ K6 E" B% U2 i/ U% N8 ]
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
0 F, z" l) L7 l
- i% ?" i! i1 U  m  PCREATE TABLE `user`  (  q1 w7 x) _+ t; i7 }4 I; t
  `id` int(11) NOT NULL AUTO_INCREMENT,
1 [% l8 D; X8 T; N. g. x  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
3 _  Z9 c7 ]! l# s$ A8 q/ T+ k  `password` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
% H( h" p' v3 [( `; L  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,  }; K* F  l4 S
  `addr_id` int(11) NULL DEFAULT NULL,
* y  f9 [" ^/ F* Y$ ^  PRIMARY KEY (`id`) USING BTREE,) H2 q! i; O5 b
  INDEX `addr_id`(`addr_id`) USING BTREE
1 p( Y  Q+ e( L. y2 E3 U- U) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;( k% N& R$ ]8 p+ s
3 R3 u; }& X% V0 i
+ E- F8 y7 U- Z
CREATE TABLE `type_time` (
2 Z/ n" p- {& X* D  `id` int(11) NOT NULL AUTO_INCREMENT,
0 w3 s7 {5 y$ X  `time` varchar(255) DEFAULT '[]',6 l7 W/ Z  n- K( Y- ]
  `name` varchar(100) DEFAULT '',. u; T; V. Z* t& F$ l2 g6 t% u
  PRIMARY KEY (`id`),
( ~6 I4 ]: ~6 G: R  INDEX `name_time_index`(`name`,`time`) USING BTREE& d7 z8 |3 b' u
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
% m6 M6 `3 X4 M7 M$ r, e8 J5 o6 V" U: K! z. u
一、id
8 e3 z- x7 \$ E! Q) `( z* r5 h. ~每个 SELECT语句都会自动分配的一个唯一标识符.
& L# k. C5 H$ \1 s: o: o表示查询中操作表的顺序,有三种情况:( @" M) N; g9 Y
id相同:执行顺序由上到下
& \4 y5 J' Z( f0 xid不同:如果是子查询,id号会自增,id越大,优先级越高。: @! g& W( E- h) D8 ]
id相同的不同的同时存在
2 q. |3 a* Y9 b9 M  r) ^id列为null的就表示这是一个结果集,不需要使用它来进行查询。
- p5 Q1 B, e+ E& B1 P& T( U- q$ k
二、select_type" E/ v  }& ], Y. U
+ W, s! Y( f: [& ^) B) C
查询类型,主要用于区别普通查询、联合查询(union、union all)、子查询等复杂查询; ?1 J9 R9 V' @3 p( ^

4 o3 a& W- i* N. ?# Y. F9 \- q2.1、simple
; G- B2 N3 ], h- o, g  U表示不需要union操作或者不包含子查询的简单select查询。有连接查询时,外层的查询为simple
4 e( M! G5 {' U5 f* @
2 @9 _7 F0 M% s  HEXPLAIN select * from user
. }/ i: c, b# D6 |
2 h& ]" O9 B7 U 7.png
/ U, g) m5 `. @8 K: {/ \
+ ~% n# x. w/ F& `' z: LEXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id# `* E# U8 x  o8 z0 e* X( w. |
9.png
- G" Q) l4 c$ g7 ?
- _4 T# N+ n1 n/ `2.2 primary
$ J3 ?( x, A, w. ^' _1 ~' l一个需要union操作或者含有子查询的select,位于最外层的单位查询的select_type为primary。
8 W! r; i7 \: O0 j9 T- b2 Q, B
6 y# Z; w/ S' l0 {) }explain select * from taddr t inner join (
/ Q* o  N* t6 v9 t- M% {+ G' lselect addr_id from user ) u on t.id=u.addr_id
$ g6 u9 h3 S4 `& S( C1 y 10.png - K- p& B0 F$ j0 t  ^. y
explain select * from user u where u.addr_id =1q
* q2 h; J) M% \, `# z( |union all
, `8 @! P+ j1 z0 R1 w/ X& P% S: e" ^select * from user u where u.addr_id =2
! E8 U+ G3 M& t 11.png
+ X" s. D8 v: s% Y% I" Q! _
6 E" z* g8 v  p' P" l2.3 subquery0 k# t+ {# E" O- s( f
除了from字句中包含的一查询外,其他地方出现的子查询都可能是subquery
$ s/ L& W6 b, Y: J' z; X/ F
! g* D1 n6 E, r2 f" [8 t2.4 dependent subquery
$ F" ^) K9 H) b2 z9 ]7 U
. U  |6 P. q6 f6 T7 Y与dependent union类似,表示这个subquery的查询要受到外部表查询的影响
% R1 _7 N- h2 w; I3 |0 j& d) T" M; W5 Q, ?# Z
explain select u.name,(select t.province from taddr t where u.addr_id=t.id) from user u
0 M. c( a/ t; e; m 12.png
* P; w' s& |$ |$ Q. L: o; h; g2.5 union
( y, ]9 N. j% B  R6 Y. G2 s1 z: Kunion连接的两个select查询,第⼀个查询是PRIMARY,除了第一个表外,第二个以后的表select_type都是union+ j& u/ C, q& x3 z, k& P. M: F
- i* z3 f  C& x* ]" W
三、table5 u4 g) t3 o' L: D- H0 S1 {
显示的查询表名,如果查询使用了别名,那么这里显示的是别名
. I7 n+ R! M% n# q/ z如果不涉及对数据表的操作,那么这显示为null+ N. |% ]- w2 R' k6 Q  G
如果显示为尖括号括起来的就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。
1 C3 E* {5 ~/ P, j: B1 [- b如果是尖括号括起来的<union M,N>,与类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集。# j, Z( Z* f6 N- S! L
. Q% ]3 U* d' k% M, O( k8 j
四、type5 {4 f% {- n! E3 ~; M1 T; J; r
3 u4 b( b6 d5 {* \) s/ Y
依次从好到差:/ P3 B$ A& ^; f) n$ m2 _  J: a
system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,
5 X7 b: ]1 {2 p8 J) K3 jindex_subquery,range,index_merge,index,ALL: t) }1 A* n6 n) l

! b( _: X5 [# {% U7 \: Q, r% m除了all之外,其他的type都可以使⽤到索引,除了index_merge之外,其他的type只可以用到一个索引, Q/ F) P( F8 w: {

% K* \: f7 j4 o2 ~0 {3 j; X% p0 y. ?4、1 system
9 u& O9 E" ?' G) P. P表中只有一行数据或者是空表。
7 X0 d+ j9 l% k- h( z. [0 e
9 t: ~8 f- Y/ K4、2const
7 y) j1 V" e/ Q7 [* `1 B, S8 |3 K( }9 U使用唯一索引或者主键,返回记录一定是1行记录的等值where条件时,通常type是const。其他数据库也叫做唯一索引扫描。  P) @8 m: v" ?0 K- U6 u
! `7 H' u+ i* }
4、3 eq_ref1 F. f; D: X# P9 R/ w& i& u
关键字:连接字段主键或者唯一性索引。
2 N# _0 m3 ^$ O4 I  M0 p此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较较操作通常是 ‘=’, 查询效率较高.8 q( W6 U1 z0 g1 f) z( u
0 i  R1 T! A8 R4 ?9 H" j
EXPLAIN select u.id,u.addr_id,a.* from user u inner join taddr a on u.addr_id=a.id
6 F% t" M( L2 q4 E* r+ [
; P! H) X$ P% }
7 o1 u" H- _1 D, }+ e 13.png 0 i9 o5 n; Q4 D
5 k% A6 h! F7 X8 y  r

6 F- Z% }& N2 [. N3 U( P

4、4 ref6 b; Z2 p8 |6 U5 ~) ^: {* H6 f$ i
针对非唯一性索引,使用等值(=)查询非主键。或者是使用了最左前缀规则索引的查询。

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

14.png 1 [7 t" i5 ?: y, u
9 Q, e1 z! k* v* ]* R/ u4 e
4.5 fulltext
0 Q6 W) s& t+ w全文索引检索,要注意,全文索引的优先级很高,若全高索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引
' n' h1 N2 E1 j" o; M
$ x4 `" L% ?) z2 y4 K4、6 unique_subquery
& R; n2 z+ j7 [. l- R用于where中的in形式子查询,子查询返回不重复值唯一值
0 s0 P' r- e4 L" a0 @  Z; [( W( Q! Z0 g# K9 j& f
4、7 index_subquery
" n6 u7 W0 A7 T) N) T& K用于in形式子查询使用到了辅助索引或者in常数列表,子查询可能返回重复值,可以使用索引将子查询去重。& B( _. I* e, R1 K3 k! U

! ]* p1 }* R, N3 r: R* k4、8 range
! _/ a; v7 n+ l, C( k. b: [索引范围扫描,常用于使用>,<,is null,between ,in ,like等运算符的查询中。0 S3 V* f: c" O* z
2 Y% Y3 ?. a& {4 f
explain select * from type_time a inner join (
+ d1 q0 F1 v+ B6 m7 m6 dselect id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) ) b on a.id=b.id
4 l( G2 d+ q$ @0 ^# }6 R4 o5 k# q9 Q; [

7 \. d+ ~% {/ B1 m3 N: s6 [ 15.png - N. e1 @: v( u. C7 A7 e1 ~" _" M

9 l! k/ O$ k8 {( F2 o4、9 index
+ _" V# {; s% F& F+ y- v键字:条件是出现在索引树中的节点的。可能没有完全匹配索引。
' d8 \/ S$ F: w6 o索引全表扫描,把索引从头到尾扫一遍,常用于使用索引列就可以处理不需要读取数据文件的查询、可以使使用索引排序或者分组的查询。+ w! \: j. N* C% f- h8 u9 x3 [

8 S7 J, H$ o1 v/ N; W) e1 _explain select * from user group by addr_id2 ?: ^3 M" I, o' S( P
" e) Y2 |* j" ?) Y

* T5 z$ D2 q$ H  U& @6 ]7 i9 s1 `6 t  u
16.png
4 _8 G* J. T! F1 U2 e0 t3 ^6 z) U6 h7 {( k- F9 r
explain select addr_id from user
7 L) K8 _0 C# J2 a  C2 p. H0 B2 P/ F4 C
17.png ; q% z: i* ]) v5 F. N
5 p, t% n- S2 U
5 B' f6 ]/ Y  Z8 T- m
4、10 all
7 m; I( L8 r( e3 B& {" W- _这个就是全表扫描数据文件,然后再在server层进行过滤返回符合要求的记录。4 Q4 u- Y; c4 ]! ~0 k

" n0 c. d3 [3 H' ]: o7 m7 _' L五、possible_keys  n& p7 C6 A0 `. R
! K/ K8 w4 o& _: s( U- o* }
此次查询中可能选用的索引,一个或多个
3 R3 e. S$ ]( [: Z9 E. [7 h
8 c! z* H: s: X. `+ F/ [" [7 z: Z六、key
3 ?- W% V0 P( E  X4 k/ Z查询真正使使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。
$ O& H4 y2 r; A- @
7 J% \6 g5 b& T4 M( b, P9 |七、key_len
' W- I4 N: ~6 S9 f. r: W" N5 _
( ^* ?7 R7 G6 H用于处理查询的索引长度度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查# m/ d! z) m% T& V& }
询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的,这里不会计算进去。留意下这个列的值,算下你的多列索引总长度就知道有没有使用到所有的列了。
' C* u% }6 {+ r: w) w8 M另外,key_len只计算where条件用到的索引长度,而排序和分组就算使用到了索引,也不会计算到key_len中。# W( z' @# J( m6 Q! c7 d% k3 j& ?
explain select id from type_time where name =‘2’ 用到长度303$ z3 B1 s# C, m$ @) J5 W

" n0 r3 d# A7 l6 k' U' O1 |( s7 y- r5 ^ 18.png
! r/ q" x% l* e9 bexplain select id from type_time where name =‘2’ and time in (‘2’,‘3’,‘4’) 用到长度 1071
7 Z8 |) \1 o# b8 G2 {3 G2 u2 m# w/ C( x0 C3 y: v$ L1 ?8 {
19.png 9 J- Q: u( F% F: p6 @8 N
8 c5 \  c) Y7 k" T7 r$ `
八、ref
4 J, v; V" s, _( P0 E$ O如果是使用的常数等值查询,这里会显示const
2 ]8 S1 [$ Q- c0 I, K如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段
6 w. y8 ^8 X& `0 M如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func8 C8 W: d, e+ \. G+ @3 p
: A6 |7 `5 V, r5 _2 i
九、rows0 H1 g' m- Z. L% m
这里是执行计划中估算的扫描行数,不是精确值(InnoDB不是精确的值,MyISAM是精确的值,主要原因是InnoDB使用了MVCC并发机制)' Q2 \( p8 {, v7 @
5 @6 ?4 v" y# A( S6 S+ D  r% V
十、extra# k: c; e3 E& U" L( M
这个列包含不适合在其他列中显示但十分重要的额外的信息,其中比较常见有一些:
% Y4 Y$ @; s: m& w8 v
( x# J9 c3 @$ o/ ]% P/ _10、1 using temporary2 w& J$ u- m" L2 n! B
表示使用了临时表存储中间结果。8 q4 ]+ m7 y9 d
MySQL在对查询结果order by和group by时使用临时表
( _- }: F/ k5 p  H1 A" a% v临时表可以是内存临时表和磁盘临时表,执行计划中看不出来,需要查看status变量,. D7 {+ e- t* H, X& U* O# |  ]" b
used_tmp_table,used_tmp_disk_table才能看出来。
1 F0 ]/ P' s3 D5 r. M0 u5 u- B) y/ _& ?0 F6 g2 T
explain select * from user u inner join taddr t on u.addr_id=t.id GROUP BY t.id, C  V, Z" W/ l% @
- N- D9 Y" x" h" w2 f2 g9 M: M
20.png
/ K" J) a, |- }$ b
2 r- R8 a! s3 e/ X* B10、2 using filesort  p0 Z8 z# T7 ^$ X7 ]
排序时无法使用到索引时,就会出现这个。常用于order by和group by语句中
0 r& Y, X6 d$ o; K* G5 ]
) e& G3 \$ z. g说明MySQL会使用个外部的索引排序,而不是按照索引顺序进行读取。
5 A& @  i# A1 O1 Q2 LMySQL中无法利索引索引完成的排序操作称为“文件排序“
$ k5 O2 w0 \* y! Z1 [0 n/ F7 O$ F. s6 |6 u' t; g: ^- U
10、3 using index( E0 b, I# L& r0 N: d+ U4 J
查询时不需要回表查询,直接通过索引就可以获取查询的数据。
$ A( `5 n; T  b% j, |7 e表示相应的SELECT查询中使用到了覆盖索引(Covering Index),避免回表访问数据行,效率不2 G2 Q6 d: p3 g1 `# [
错。
/ w! L5 H; E: u如果同时出现Using Where ,说明索引被用来执行查找索引键值
& V" S- q3 {# i  }: b* [如果没有同时出现Using Where ,表明索引用来读取数据来执行查找动作。: g- A2 R1 V/ f* O$ D

+ a  v- U; k$ `+ o7 L/ \" f这里对索引的原理和explain做了一些介绍,需要索引需要建立之后对其改变查询方式可能会更能深刻理解 InnoDB 使用覆盖索引和非覆盖索引造成区别。这也是建立索引和使用sql需要特别考虑的问题。5 ^7 U. x9 K' o7 P0 l' g
————————————————4 K3 ]; ?6 Y" ?5 B, g
版权声明:本文为CSDN博主「筏镜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
! f) e, c7 K* Z( l1 k原文链接:https://blog.csdn.net/fajing_feiyue/article/details/1056166291 z% Z, @% Y! d3 M2 f
1 K5 T5 n$ X: ?* I' M
1 |* {6 l' M# ^

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

20.png






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5