-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy path37讲什么时候会使用内部临时表.html
446 lines (372 loc) · 57.5 KB
/
37讲什么时候会使用内部临时表.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<style type="text/css">
#watermark {
position: relative;
overflow: hidden;
}
#watermark .x {
position: absolute;
top: 800;
left: 400;
color: #3300ff;
font-size: 50px;
pointer-events: none;
opacity:0.3;
filter:Alpha(opacity=50);
}
</style>
<style type="text/css">
html{color:#333;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;text-rendering:optimizelegibility;font-family:Helvetica Neue,PingFang SC,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif}html.borderbox *,html.borderbox :after,html.borderbox :before{box-sizing:border-box}article,aside,blockquote,body,button,code,dd,details,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hr,input,legend,li,menu,nav,ol,p,pre,section,td,textarea,th,ul{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,menu,nav,section{display:block}audio,canvas,video{display:inline-block}body,button,input,select,textarea{font:300 1em/1.8 PingFang SC,Lantinghei SC,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,Helvetica,sans-serif}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}blockquote{position:relative;color:#999;font-weight:400;border-left:1px solid #1abc9c;padding-left:1em;margin:1em 3em 1em 2em}@media only screen and (max-width:640px){blockquote{margin:1em 0}}abbr,acronym{border-bottom:1px dotted;font-variant:normal}abbr{cursor:help}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}ol,ul{list-style:none}caption,th{text-align:left}q:after,q:before{content:""}sub,sup{font-size:75%;line-height:0;position:relative}:root sub,:root sup{vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a{color:#1abc9c}a:hover{text-decoration:underline}.typo a{border-bottom:1px solid #1abc9c}.typo a:hover{border-bottom-color:#555;color:#555}.typo a:hover,a,ins{text-decoration:none}.typo-u,u{text-decoration:underline}mark{background:#fffdd1;border-bottom:1px solid #ffedce;padding:2px;margin:0 5px}code,pre,pre tt{font-family:Courier,Courier New,monospace}pre{background:hsla(0,0%,97%,.7);border:1px solid #ddd;padding:1em 1.5em;display:block;-webkit-overflow-scrolling:touch}hr{border:none;border-bottom:1px solid #cfcfcf;margin-bottom:.8em;height:10px}.typo-small,figcaption,small{font-size:.9em;color:#888}b,strong{font-weight:700;color:#000}[draggable]{cursor:move}.clearfix:after,.clearfix:before{content:"";display:table}.clearfix:after{clear:both}.clearfix{zoom:1}.textwrap,.textwrap td,.textwrap th{word-wrap:break-word;word-break:break-all}.textwrap-table{table-layout:fixed}.serif{font-family:Palatino,Optima,Georgia,serif}.typo-dl,.typo-form,.typo-hr,.typo-ol,.typo-p,.typo-pre,.typo-table,.typo-ul,.typo dl,.typo form,.typo hr,.typo ol,.typo p,.typo pre,.typo table,.typo ul,blockquote{margin-bottom:1rem}h1,h2,h3,h4,h5,h6{font-family:PingFang SC,Helvetica Neue,Verdana,Microsoft Yahei,Hiragino Sans GB,Microsoft Sans Serif,WenQuanYi Micro Hei,sans-serif;color:#000;line-height:1.35}.typo-h1,.typo-h2,.typo-h3,.typo-h4,.typo-h5,.typo-h6,.typo h1,.typo h2,.typo h3,.typo h4,.typo h5,.typo h6{margin-top:1.2em;margin-bottom:.6em;line-height:1.35}.typo-h1,.typo h1{font-size:2em}.typo-h2,.typo h2{font-size:1.8em}.typo-h3,.typo h3{font-size:1.6em}.typo-h4,.typo h4{font-size:1.4em}.typo-h5,.typo-h6,.typo h5,.typo h6{font-size:1.2em}.typo-ul,.typo ul{margin-left:1.3em;list-style:disc}.typo-ol,.typo ol{list-style:decimal;margin-left:1.9em}.typo-ol ol,.typo-ol ul,.typo-ul ol,.typo-ul ul,.typo li ol,.typo li ul{margin-bottom:.8em;margin-left:2em}.typo-ol ul,.typo-ul ul,.typo li ul{list-style:circle}.typo-table td,.typo-table th,.typo table caption,.typo table td,.typo table th{border:1px solid #ddd;padding:.5em 1em;color:#666}.typo-table th,.typo table th{background:#fbfbfb}.typo-table thead th,.typo table thead th{background:hsla(0,0%,95%,.7)}.typo table caption{border-bottom:none}.typo-input,.typo-textarea{-webkit-appearance:none;border-radius:0}.typo-em,.typo em,caption,legend{color:#000;font-weight:inherit}.typo-em{position:relative}.typo-em:after{position:absolute;top:.65em;left:0;width:100%;overflow:hidden;white-space:nowrap;content:"\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB\30FB"}.typo img{max-width:100%}.common-content{font-weight:400;color:#353535;line-height:1.75rem;white-space:normal;word-break:normal;font-size:1rem}.common-content img{display:block;max-width:100%;background-color:#eee}.common-content audio,.common-content video{width:100%;background-color:#eee}.common-content center,.common-content font{margin-top:1rem;display:inline-block}.common-content center{width:100%}.common-content pre{margin-top:1rem;padding-left:0;padding-right:0;position:relative;overflow:hidden}.common-content pre code{font-size:.8rem;font-family:Consolas,Liberation Mono,Menlo,monospace,Courier;display:block;width:100%;box-sizing:border-box;padding-left:1rem;padding-right:1rem;overflow-x:auto}.common-content hr{border:none;margin-top:1.5rem;margin-bottom:1.5rem;border-top:1px solid #f5f5f5;height:1px;background:none}.common-content b,.common-content h1,.common-content h2,.common-content h3,.common-content h4,.common-content h5,.common-content strong{font-weight:700}.common-content h1,.common-content h2{font-size:1.125rem;margin-bottom:.45rem}.common-content h3,.common-content h4,.common-content h5{font-size:1rem;margin-bottom:.45rem}.common-content p{font-weight:400;color:#353535;margin-top:.15rem}.common-content .orange{color:#ff5a05}.common-content .reference{font-size:1rem;color:#888}.custom-rich-content h1{margin-top:0;font-weight:400;font-size:15.25px;border-bottom:1px solid #eee;line-height:2.8}.custom-rich-content li,.custom-rich-content p{font-size:14px;color:#888;line-height:1.6}table.hljs-ln{margin-bottom:0;border-spacing:0;border-collapse:collapse}table.hljs-ln,table.hljs-ln tbody,table.hljs-ln td,table.hljs-ln tr{box-sizing:border-box}table.hljs-ln td{padding:0;border:0}table.hljs-ln td.hljs-ln-numbers{min-width:15px;color:rgba(27,31,35,.3);text-align:right;white-space:nowrap;cursor:pointer;user-select:none}table.hljs-ln td.hljs-ln-code,table.hljs-ln td.hljs-ln-numbers{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px;line-height:20px;vertical-align:top}table.hljs-ln td.hljs-ln-code{position:relative;padding-right:10px;padding-left:10px;overflow:visible;color:#24292e;word-wrap:normal;white-space:pre}video::-webkit-media-controls{overflow:hidden!important}video::-webkit-media-controls-enclosure{width:calc(100% + 32px);margin-left:auto}.button-cancel{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel,.button-primary{-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary{color:#fff;background-color:#ff5a05;border-radius:3px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot);src:url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.woff) format("woff"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.ttf) format("truetype"),url(//at.alicdn.com/t/font_372689_bwwwtosxtzp.svg#iconfont) format("svg")}@font-face{font-family:player-font;src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot);src:url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.woff) format("woff"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.ttf) format("truetype"),url(//at.alicdn.com/t/font_509397_1cyjv4o90qiod2t9.svg#player-font) format("svg")}.iconfont{font-family:iconfont!important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}html{background:#fff;min-height:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{width:100%}body.fixed{overflow:hidden;position:fixed;width:100vw;height:100vh}i{font-style:normal}a{word-wrap:break-word;-webkit-tap-highlight-color:rgba(0,0,0,0)}a:hover{text-decoration:none}.fade-enter-active,.fade-leave-active{transition:opacity .3s}.fade-enter,.fade-leave-to{opacity:0}.MathJax,.MathJax_CHTML,.MathJax_MathContainer,.MathJax_MathML,.MathJax_PHTML,.MathJax_PlainSource,.MathJax_SVG{outline:0}.ios-app-switch .js-audit{display:none}._loading_wrap_{position:fixed;width:100vw;height:100vh;top:50%;left:50%;transform:translate(-50%,-50%);z-index:999}._loading_div_class_,._loading_wrap_{display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}._loading_div_class_{word-wrap:break-word;padding:.5rem .75rem;text-align:center;z-index:9999;font-size:.6rem;max-width:60%;color:#fff;border-radius:.25rem;-ms-flex-direction:column;flex-direction:column}._loading_div_class_ .message{color:#353535;font-size:16px;line-height:3}.spinner{animation:circle-rotator 1.4s linear infinite}.spinner *{line-height:0;box-sizing:border-box}@keyframes circle-rotator{0%{transform:rotate(0deg)}to{transform:rotate(270deg)}}.path{stroke-dasharray:187;stroke-dashoffset:0;transform-origin:center;animation:circle-dash 1.4s ease-in-out infinite,circle-colors 5.6s ease-in-out infinite}@keyframes circle-colors{0%{stroke:#ff5a05}to{stroke:#ff5a05}}@keyframes circle-dash{0%{stroke-dashoffset:187}50%{stroke-dashoffset:46.75;transform:rotate(135deg)}to{stroke-dashoffset:187;transform:rotate(450deg)}}.confirm-box-wrapper,.confirm-box-wrapper .mask{position:absolute;top:0;left:0;right:0;bottom:0}.confirm-box-wrapper .mask{background:rgba(0,0,0,.6)}.confirm-box-wrapper .confirm-box{position:fixed;top:50%;left:50%;width:267px;background:#fff;transform:translate(-50%,-50%);border-radius:7px}.confirm-box-wrapper .confirm-box .head{margin:0 18px;font-size:18px;text-align:center;line-height:65px;border-bottom:1px solid #d9d9d9}.confirm-box-wrapper .confirm-box .body{padding:18px;padding-bottom:0;color:#353535;font-size:12.5px;max-height:150px;overflow:auto}.confirm-box-wrapper .confirm-box .foot{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;padding:18px}.confirm-box-wrapper .confirm-box .foot .button-cancel{border:1px solid #d9d9d9}.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
</style>
<style type="text/css">
.button-cancel[data-v-87ffcada]{color:#888;border:1px solid #888;border-radius:3px;margin-right:12px}.button-cancel[data-v-87ffcada],.button-primary[data-v-87ffcada]{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:35px;display:inline-block;font-size:15px;text-align:center;line-height:36px}.button-primary[data-v-87ffcada]{color:#fff;background-color:#ff5a05;border-radius:3px}.pd[data-v-87ffcada]{padding-left:1.375rem;padding-right:1.375rem}.article[data-v-87ffcada]{max-width:70rem;margin:0 auto}.article .article-unavailable[data-v-87ffcada]{color:#fa8919;font-size:15px;font-weight:600;line-height:24px;border-radius:5px;padding:12px;background-color:#f6f7fb;margin-top:20px}.article .article-unavailable .iconfont[data-v-87ffcada]{font-size:12px}.article .main[data-v-87ffcada]{padding:1.25rem 0;margin-bottom:52px}.article-title[data-v-87ffcada]{color:#353535;font-weight:400;line-height:1.65rem;font-size:1.34375rem}.article-info[data-v-87ffcada]{color:#888;font-size:.9375rem;margin-top:1.0625rem}.article-content[data-v-87ffcada]{margin-top:1.0625rem}.article-content.android video[data-v-87ffcada]::-webkit-media-controls-fullscreen-button{display:none}.copyright[data-v-87ffcada]{color:#b2b2b2;padding-bottom:20px;margin-top:20px;font-size:13px}.audio-player[data-v-87ffcada]{width:100%;margin:20px 0}.to-comment[data-v-87ffcada]{overflow:hidden;padding-top:10px;margin-bottom:-30px}.to-comment a.button-primary[data-v-87ffcada]{float:right;height:20px;font-size:12px;line-height:20px;padding:4px 8px;cursor:pointer}.article-comments[data-v-87ffcada]{margin-top:2rem}.article-comments h2[data-v-87ffcada]{text-align:center;color:#888;position:relative;z-index:1;margin-bottom:1rem}.article-comments h2[data-v-87ffcada]:before{border-top:1px dotted #888;content:"";position:absolute;top:56%;left:0;width:100%;z-index:-1}.article-comments h2 span[data-v-87ffcada]{font-size:15.25px;font-weight:400;padding:0 1rem;background:#fff;display:inline-block}.article-sub-bottom[data-v-87ffcada]{z-index:10;cursor:pointer}.switch-btns[data-v-87ffcada]{height:76px;cursor:pointer;padding-top:24px;padding-bottom:24px;border-bottom:10px solid #f6f7fb;position:relative}.switch-btns[data-v-87ffcada]:before{content:" ";height:1px;background:#e8e8e8;position:absolute;top:0;left:0;-webkit-box-sizing:border-box;box-sizing:border-box;left:1.375rem;right:1.375rem}.switch-btns .btn[data-v-87ffcada]{height:38px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.switch-btns .btn .tag[data-v-87ffcada]{-webkit-box-flex:0;-ms-flex:0 0 62px;flex:0 0 62px;text-align:center;color:#888;font-size:14px;border-radius:10px;height:22px;line-height:22px;background:#f6f7fb;font-weight:400}.switch-btns .btn .txt[data-v-87ffcada]{margin-left:10px;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;color:#888;font-size:15px;height:22px;line-height:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400}@media (max-width:769px){.article .breadcrumb[data-v-87ffcada]{padding-top:10px;padding-bottom:10px}}
</style>
<style type="text/css">
.comment-item{list-style-position:inside;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin-bottom:1rem}.comment-item a{border-bottom:none}.comment-item .avatar{width:2.625rem;height:2.625rem;-ms-flex-negative:0;flex-shrink:0;border-radius:50%}.comment-item .info{margin-left:.5rem;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.comment-item .info .hd{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .username{color:#888;font-size:15.25px;font-weight:400;line-height:1.2}.comment-item .info .hd .control{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.comment-item .info .hd .control .btn-share{color:#888;font-size:.75rem;margin-right:1rem}.comment-item .info .hd .control .btn-praise{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:15.25px;text-decoration:none}.comment-item .info .hd .control .btn-praise i{color:#888;display:inline-block;font-size:.75rem;margin-right:.3rem;margin-top:-.01rem}.comment-item .info .hd .control .btn-praise i.on,.comment-item .info .hd .control .btn-praise span{color:#ff5a05}.comment-item .info .bd{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all;line-height:1.6}.comment-item .info .time{color:#888;font-size:9px;line-height:1}.comment-item .info .reply .reply-hd{font-size:15.25px}.comment-item .info .reply .reply-hd span{margin-left:-12px;color:#888;font-weight:400}.comment-item .info .reply .reply-hd i{color:#ff5a05;font-size:15.25px}.comment-item .info .reply .reply-content{color:#353535;font-size:15.25px;font-weight:400;white-space:normal;word-break:break-all}.comment-item .info .reply .reply-time{color:#888;font-size:9px}
</style>
</head>
<body>
<div id="app">
<div data-v-87ffcada="" class="article" id="watermark">
<div data-v-87ffcada="" class="main main-app">
<h1 data-v-87ffcada="" class="article-title pd">
37讲什么时候会使用内部临时表
</h1>
<div data-v-87ffcada="" class="article-content typo common-content pd"><img data-v-87ffcada=""
src="https://static001.geekbang.org/resource/image/04/2d/041a7e2f4ba932d3cb6cbeac6264412d.jpg">
<div>
<audio controls="controls" height="100" width="100">
<source src="37讲什么时候会使用内部临时表.mp3" type="audio/mp3" />
<embed height="100" width="100" src="37讲什么时候会使用内部临时表.mp3" />
</audio>
</div>
<div data-v-87ffcada="" id="article-content" class="">
<div class="text">
<p><span class="orange">今天是大年初二,在开始我们今天的学习之前,我要先和你道一声春节快乐!</span></p><p>在<a href="https://time.geekbang.org/column/article/73479">第16</a>和<a href="https://time.geekbang.org/column/article/79700">第34</a>篇文章中,我分别和你介绍了sort buffer、内存临时表和join buffer。这三个数据结构都是用来存放语句执行过程中的中间数据,以辅助SQL语句的执行的。其中,我们在排序的时候用到了sort buffer,在使用join语句的时候用到了join buffer。</p><p>然后,你可能会有这样的疑问,MySQL什么时候会使用内部临时表呢?</p><p>今天这篇文章,我就先给你举两个需要用到内部临时表的例子,来看看内部临时表是怎么工作的。然后,我们再来分析,什么情况下会使用内部临时表。</p><h1>union 执行流程</h1><p>为了便于量化分析,我用下面的表t1来举例。</p><pre><code>create table t1(id int primary key, a int, b int, index(a));
delimiter ;;
create procedure idata()
begin
declare i int;
set i=1;
while(i<=1000)do
insert into t1 values(i, i, i);
set i=i+1;
end while;
end;;
delimiter ;
call idata();
</code></pre><p>然后,我们执行下面这条语句:</p><pre><code>(select 1000 as f) union (select id from t1 order by id desc limit 2);
</code></pre><p>这条语句用到了union,它的语义是,取这两个子查询结果的并集。并集的意思就是这两个集合加起来,重复的行只保留一行。</p><p>下图是这个语句的explain结果。</p><p><img src="https://static001.geekbang.org/resource/image/40/4e/402cbdef84eef8f1b42201c6ec4bad4e.png" alt=""></p><center><span class="reference">图1 union语句explain 结果</span></center><p>可以看到:</p><ul>
<li>第二行的key=PRIMARY,说明第二个子句用到了索引id。</li>
<li>第三行的Extra字段,表示在对子查询的结果集做union的时候,使用了临时表(Using temporary)。</li>
</ul><!-- [[[read_end]]] --><p>这个语句的执行流程是这样的:</p><ol>
<li>
<p>创建一个内存临时表,这个临时表只有一个整型字段f,并且f是主键字段。</p>
</li>
<li>
<p>执行第一个子查询,得到1000这个值,并存入临时表中。</p>
</li>
<li>
<p>执行第二个子查询:</p>
<ul>
<li>拿到第一行id=1000,试图插入临时表中。但由于1000这个值已经存在于临时表了,违反了唯一性约束,所以插入失败,然后继续执行;</li>
<li>取到第二行id=999,插入临时表成功。</li>
</ul>
</li>
<li>
<p>从临时表中按行取出数据,返回结果,并删除临时表,结果中包含两行数据分别是1000和999。</p>
</li>
</ol><p>这个过程的流程图如下所示:</p><p><img src="https://static001.geekbang.org/resource/image/5d/0e/5d038c1366d375cc997005a5d65c600e.jpg" alt=""></p><center><span class="reference">图 2 union 执行流程</span></center><p>可以看到,这里的内存临时表起到了暂存数据的作用,而且计算过程还用上了临时表主键id的唯一性约束,实现了union的语义。</p><p>顺便提一下,如果把上面这个语句中的union改成union all的话,就没有了“去重”的语义。这样执行的时候,就依次执行子查询,得到的结果直接作为结果集的一部分,发给客户端。因此也就不需要临时表了。</p><p><img src="https://static001.geekbang.org/resource/image/c1/6d/c1e90d1d7417b484d566b95720fe3f6d.png" alt=""></p><center><span class="reference">图3 union all的explain结果</span></center><p>可以看到,第二行的Extra字段显示的是Using index,表示只使用了覆盖索引,没有用临时表了。</p><h1>group by 执行流程</h1><p>另外一个常见的使用临时表的例子是group by,我们来看一下这个语句:</p><pre><code>select id%10 as m, count(*) as c from t1 group by m;
</code></pre><p>这个语句的逻辑是把表t1里的数据,按照 id%10 进行分组统计,并按照m的结果排序后输出。它的explain结果如下:</p><p><img src="https://static001.geekbang.org/resource/image/3d/98/3d1cb94589b6b3c4bb57b0bdfa385d98.png" alt=""></p><center><span class="reference">图4 group by 的explain结果</span></center><p>在Extra字段里面,我们可以看到三个信息:</p><ul>
<li>Using index,表示这个语句使用了覆盖索引,选择了索引a,不需要回表;</li>
<li>Using temporary,表示使用了临时表;</li>
<li>Using filesort,表示需要排序。</li>
</ul><p>这个语句的执行流程是这样的:</p><ol>
<li>
<p>创建内存临时表,表里有两个字段m和c,主键是m;</p>
</li>
<li>
<p>扫描表t1的索引a,依次取出叶子节点上的id值,计算id%10的结果,记为x;</p>
<ul>
<li>如果临时表中没有主键为x的行,就插入一个记录(x,1);</li>
<li>如果表中有主键为x的行,就将x这一行的c值加1;</li>
</ul>
</li>
<li>
<p>遍历完成后,再根据字段m做排序,得到结果集返回给客户端。</p>
</li>
</ol><p>这个流程的执行图如下:</p><p><img src="https://static001.geekbang.org/resource/image/03/54/0399382169faf50fc1b354099af71954.jpg" alt=""></p><center><span class="reference">图5 group by执行流程</span></center><p>图中最后一步,对内存临时表的排序,在<a href="https://time.geekbang.org/column/article/73795">第17篇文章</a>中已经有过介绍,我把图贴过来,方便你回顾。</p><p><img src="https://static001.geekbang.org/resource/image/b5/68/b5168d201f5a89de3b424ede2ebf3d68.jpg" alt=""></p><center><span class="reference">图6 内存临时表排序流程</span></center><p>其中,临时表的排序过程就是图6中虚线框内的过程。</p><p>接下来,我们再看一下这条语句的执行结果:</p><p><img src="https://static001.geekbang.org/resource/image/ae/55/ae6a28d890efc35ee4d07f694068f455.png" alt=""></p><center><span class="reference">图 7 group by执行结果</span></center><p>如果你的需求并不需要对结果进行排序,那你可以在SQL语句末尾增加order by null,也就是改成:</p><pre><code>select id%10 as m, count(*) as c from t1 group by m order by null;
</code></pre><p>这样就跳过了最后排序的阶段,直接从临时表中取数据返回。返回的结果如图8所示。</p><p><img src="https://static001.geekbang.org/resource/image/03/eb/036634e53276eaf8535c3442805dfaeb.png" alt=""></p><center><span class="reference">图8 group + order by null 的结果(内存临时表)</span></center><p>由于表t1中的id值是从1开始的,因此返回的结果集中第一行是id=1;扫描到id=10的时候才插入m=0这一行,因此结果集里最后一行才是m=0。</p><p>这个例子里由于临时表只有10行,内存可以放得下,因此全程只使用了内存临时表。但是,内存临时表的大小是有限制的,参数tmp_table_size就是控制这个内存大小的,默认是16M。</p><p>如果我执行下面这个语句序列:</p><pre><code>set tmp_table_size=1024;
select id%100 as m, count(*) as c from t1 group by m order by null limit 10;
</code></pre><p>把内存临时表的大小限制为最大1024字节,并把语句改成id % 100,这样返回结果里有100行数据。但是,这时的内存临时表大小不够存下这100行数据,也就是说,执行过程中会发现内存临时表大小到达了上限(1024字节)。</p><p>那么,这时候就会把内存临时表转成磁盘临时表,磁盘临时表默认使用的引擎是InnoDB。 这时,返回的结果如图9所示。</p><p><img src="https://static001.geekbang.org/resource/image/a7/6e/a76381d0f3c947292cc28198901f9e6e.png" alt=""></p><center><span class="reference">图9 group + order by null 的结果(磁盘临时表)</span></center><p>如果这个表t1的数据量很大,很可能这个查询需要的磁盘临时表就会占用大量的磁盘空间。</p><h1>group by 优化方法 --索引</h1><p>可以看到,不论是使用内存临时表还是磁盘临时表,group by逻辑都需要构造一个带唯一索引的表,执行代价都是比较高的。如果表的数据量比较大,上面这个group by语句执行起来就会很慢,我们有什么优化的方法呢?</p><p>要解决group by语句的优化问题,你可以先想一下这个问题:执行group by语句为什么需要临时表?</p><p>group by的语义逻辑,是统计不同的值出现的个数。但是,由于每一行的id%100的结果是无序的,所以我们就需要有一个临时表,来记录并统计结果。</p><p>那么,如果扫描过程中可以保证出现的数据是有序的,是不是就简单了呢?</p><p>假设,现在有一个类似图10的这么一个数据结构,我们来看看group by可以怎么做。</p><p><img src="https://static001.geekbang.org/resource/image/5c/19/5c4a581c324c1f6702f9a2c70acddd19.jpg" alt=""></p><center><span class="reference">图10 group by算法优化-有序输入</span></center><p>可以看到,如果可以确保输入的数据是有序的,那么计算group by的时候,就只需要从左到右,顺序扫描,依次累加。也就是下面这个过程:</p><ul>
<li>当碰到第一个1的时候,已经知道累积了X个0,结果集里的第一行就是(0,X);</li>
<li>当碰到第一个2的时候,已经知道累积了Y个1,结果集里的第二行就是(1,Y);</li>
</ul><p>按照这个逻辑执行的话,扫描到整个输入的数据结束,就可以拿到group by的结果,不需要临时表,也不需要再额外排序。</p><p>你一定想到了,InnoDB的索引,就可以满足这个输入有序的条件。</p><p>在MySQL 5.7版本支持了generated column机制,用来实现列数据的关联更新。你可以用下面的方法创建一个列z,然后在z列上创建一个索引(如果是MySQL 5.6及之前的版本,你也可以创建普通列和索引,来解决这个问题)。</p><pre><code>alter table t1 add column z int generated always as(id % 100), add index(z);
</code></pre><p>这样,索引z上的数据就是类似图10这样有序的了。上面的group by语句就可以改成:</p><pre><code>select z, count(*) as c from t1 group by z;
</code></pre><p>优化后的group by语句的explain结果,如下图所示:</p><p><img src="https://static001.geekbang.org/resource/image/c9/b9/c9f88fa42d92cf7dde78fca26c4798b9.png" alt=""></p><center><span class="reference">图11 group by 优化的explain结果</span></center><p>从Extra字段可以看到,这个语句的执行不再需要临时表,也不需要排序了。</p><h1>group by优化方法 --直接排序</h1><p>所以,如果可以通过加索引来完成group by逻辑就再好不过了。但是,如果碰上不适合创建索引的场景,我们还是要老老实实做排序的。那么,这时候的group by要怎么优化呢?</p><p>如果我们明明知道,一个group by语句中需要放到临时表上的数据量特别大,却还是要按照“先放到内存临时表,插入一部分数据后,发现内存临时表不够用了再转成磁盘临时表”,看上去就有点儿傻。</p><p>那么,我们就会想了,MySQL有没有让我们直接走磁盘临时表的方法呢?</p><p>答案是,有的。</p><p>在group by语句中加入SQL_BIG_RESULT这个提示(hint),就可以告诉优化器:这个语句涉及的数据量很大,请直接用磁盘临时表。</p><p>MySQL的优化器一看,磁盘临时表是B+树存储,存储效率不如数组来得高。所以,既然你告诉我数据量很大,那从磁盘空间考虑,还是直接用数组来存吧。</p><p>因此,下面这个语句</p><pre><code>select SQL_BIG_RESULT id%100 as m, count(*) as c from t1 group by m;
</code></pre><p>的执行流程就是这样的:</p><ol>
<li>
<p>初始化sort_buffer,确定放入一个整型字段,记为m;</p>
</li>
<li>
<p>扫描表t1的索引a,依次取出里面的id值, 将 id%100的值存入sort_buffer中;</p>
</li>
<li>
<p>扫描完成后,对sort_buffer的字段m做排序(如果sort_buffer内存不够用,就会利用磁盘临时文件辅助排序);</p>
</li>
<li>
<p>排序完成后,就得到了一个有序数组。</p>
</li>
</ol><p>根据有序数组,得到数组里面的不同值,以及每个值的出现次数。这一步的逻辑,你已经从前面的图10中了解过了。</p><p>下面两张图分别是执行流程图和执行explain命令得到的结果。</p><p><img src="https://static001.geekbang.org/resource/image/82/6a/8269dc6206a7ef20cb515c23df0b846a.jpg" alt=""></p><center><span class="reference">图12 使用 SQL_BIG_RESULT的执行流程图</span></center><p><img src="https://static001.geekbang.org/resource/image/83/ec/83b6cd6b3e37dfbf9699cf0ccc0f1bec.png" alt=""></p><center><span class="reference">图13 使用 SQL_BIG_RESULT的explain 结果</span></center><p>从Extra字段可以看到,这个语句的执行没有再使用临时表,而是直接用了排序算法。</p><p>基于上面的union、union all和group by语句的执行过程的分析,我们来回答文章开头的问题:MySQL什么时候会使用内部临时表?</p><ol>
<li>
<p>如果语句执行过程可以一边读数据,一边直接得到结果,是不需要额外内存的,否则就需要额外的内存,来保存中间结果;</p>
</li>
<li>
<p>join_buffer是无序数组,sort_buffer是有序数组,临时表是二维表结构;</p>
</li>
<li>
<p>如果执行逻辑需要用到二维表特性,就会优先考虑使用临时表。比如我们的例子中,union需要用到唯一索引约束, group by还需要用到另外一个字段来存累积计数。</p>
</li>
</ol><h1>小结</h1><p>通过今天这篇文章,我重点和你讲了group by的几种实现算法,从中可以总结一些使用的指导原则:</p><ol>
<li>
<p>如果对group by语句的结果没有排序要求,要在语句后面加 order by null;</p>
</li>
<li>
<p>尽量让group by过程用上表的索引,确认方法是explain结果里没有Using temporary 和 Using filesort;</p>
</li>
<li>
<p>如果group by需要统计的数据量不大,尽量只使用内存临时表;也可以通过适当调大tmp_table_size参数,来避免用到磁盘临时表;</p>
</li>
<li>
<p>如果数据量实在太大,使用SQL_BIG_RESULT这个提示,来告诉优化器直接使用排序算法得到group by的结果。</p>
</li>
</ol><p>最后,我给你留下一个思考题吧。</p><p>文章中图8和图9都是order by null,为什么图8的返回结果里面,0是在结果集的最后一行,而图9的结果里面,0是在结果集的第一行?</p><p>你可以把你的分析写在留言区里,我会在下一篇文章和你讨论这个问题。感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。</p><h1>上期问题时间</h1><p>上期的问题是:为什么不能用rename修改临时表的改名。</p><p>在实现上,执行rename table语句的时候,要求按照“库名/表名.frm”的规则去磁盘找文件,但是临时表在磁盘上的frm文件是放在tmpdir目录下的,并且文件名的规则是“#sql{进程id}_{线程id}_序列号.frm”,因此会报“找不到文件名”的错误。</p><p>评论区留言点赞板:</p><blockquote>
<p>@poppy 同学,通过执行语句的报错现象推测了这个实现过程。</p>
</blockquote><p><img src="https://static001.geekbang.org/resource/image/09/77/09c1073f99cf71d2fb162a716b5fa577.jpg" alt=""></p>
</div>
</div>
</div>
<div data-v-87ffcada="" class="article-comments pd"><h2 data-v-87ffcada=""><span
data-v-87ffcada="">精选留言</span></h2>
<ul data-v-87ffcada="">
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/03/f7/3a493bec.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">老杨同志</span>
</div>
<div class="bd">请教一个问题:如果只需要去重,不需要执行聚合函数,distinct 和group by那种效率高一些呢?<br><br>课后习题:<br>图8,把统计结果存内存临时表,不排序。id是从1到1000,模10的结果顺序就是1、2、3、4、5。。。<br>图9,老师把tmp_table_size改小了,内存临时表装不下,改用磁盘临时表。根据老师讲的流程,id取模的结果,排序后存入临时表,临时的数据应该是0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,......<br>从这个磁盘临时表读取数据汇总的结果的顺序就是0,1,2,3,4,5。。。 <br></div>
<span class="time">2019-02-06 22:03</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">新年好<br><br>好问题,我加到后面文章中。<br>简单说下结论,只需要去重的话,如果没有limit,是一样的;<br>有limit的话,distinct 快些。<br><br>漂亮的回答👍<br><br></p>
<p class="reply-time">2019-02-07 09:25</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/a8/e2/0262d330.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Li Shunduo</span>
</div>
<div class="bd">请问Group By部分的第一个语句 explain select id%10 as m, count(*) as c from t1 group by m;为什么选择的是索引a,而不是primary key?如果字段a上有空值,使用索引a岂不是就不能取到所有的id值了? <br></div>
<span class="time">2019-02-07 12:23</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">因为索引c的信息也足够,而且比主键索引小,使用索引c更会好。<br><br>“如果字段a上有空值,使用索引a岂不是就不能取到所有的id值了?”,不会的</p>
<p class="reply-time">2019-02-07 17:34</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/57/6e/dd0eee5f.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">夜空中最亮的星(华仔)</span>
</div>
<div class="bd">过年好,老师。这周 补补落下的课 <br></div>
<span class="time">2019-02-13 15:30</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/14/20/3a/90db6a24.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Long</span>
</div>
<div class="bd">老师可能没看到,再发下。<br>老师,新年好! :-)<br><br>有几个版本差异的问题:<br>(1)图1中的执行计划应该是5.7版本以后的吧,貌似没找到说在哪个环境,我在5.6和5.7分别测试了,id = 2的那个rows,在5.6版本(5.6.26)是1000,在5.7版本是2行。应该是5.7做的优化吧?<br><br>(2)图 9 group + order by null 的结果(此盘临时表),这里面mysql5.6里面执行的结果是(1,10),(2,10)...(10,10),执行计划都是只有一样,没找到差异。<br>跟踪下了下optimizer trace,发现问题应该是在临时表空间满的的时候,mysql5.7用的是:converting_tmp_table_to_ondisk "location": "disk (InnoDB)",,而mysql 5.6用的是converting_tmp_table_to_myisam "location": "disk (MyISAM)"的原因导致的。<br>查了下参数:<br>default_tmp_storage_engine。(5.6,5.7当前值都是innodb)<br>internal_tmp_disk_storage_engine(只有5.7有这个参数,当前值是innodb),5.6应该是默认磁盘临时表就是MyISAM引擎的了,由于本地测试环境那个临时表的目录下找不到临时文件,也没法继续分析了。。。<br><br>至于为什么MySQL 5.6中结果展示m字段不是0-9而是1-10,还得请老师帮忙解答下了。<br><br><br>还有几个小问题,为了方便解答,序号统一了:<br>(3)在阅读mysql执行计划的时候,看了网上有很多说法,也参考了mysql官网对id(select_id)的解释:<br>id (JSON name: select_id)<br>The SELECT identifier. This is the sequential number of the SELECT within the query.(感觉这个读起来也有点歧义,这个sequential字面解释感觉只有顺序的号码,并咩有说执行顺序)<br>比如图1,文中解释就是从ID小的往大的执行的,网上有很多其他说法,有的是说ID从大到小执行,遇到ID一样的,就从上往下执行。有的说是从小往大顺序执行。不知道老师是否可以官方讲解下。<br><br>(4)我发现想搞懂一个原理,并且讲清楚让别人明白,真的是很有难度,非常感谢老师的分享。这次专栏结束,还会推出的新的专栏吗? 非常期待。 <br></div>
<span class="time">2019-02-13 14:28</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eop9WylZJicLQxlvXukXUgPp39zJHyyReK5s1C9VhA6rric7GiarbfQMuWhdCCDdxdfL610Hc4cNkn9Q/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">还一棵树</span>
</div>
<div class="bd">group by 执行流程里面,为什么有最后排序操作,感觉这一步是多余的,扫描完最后一行数据后 ,完全可以直接从temporary表返回数据 <br></div>
<span class="time">2019-02-12 14:28</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">嗯 语义就是这么定义的,如果不需要排序,要手动加上 order by null 哈</p>
<p class="reply-time">2019-02-12 21:28</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/51/c8/83852d5a.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">梦康</span>
</div>
<div class="bd">实践发现文中描述的 group by 执行过程中解释不通。案例如下<br><br>select `aid`,sum(`pv`) as num from article_rank force index(idx_day_aid_pv) where `day`>20190115 group by aid order by num desc LIMIT 10;<br><br>内存临时表不够,需要写入磁盘<br><br>select `aid`,sum(`pv`) as num from article_rank force index(idx_aid_day_pv) where `day`>20190115 group by aid order by num desc LIMIT 10;<br><br>内存临时表足够。<br><br>选的索引不一样,但是最后筛选出来的总行应该是一样的呀,所以现在更加困惑了。 <br></div>
<span class="time">2019-02-11 17:27</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/51/c8/83852d5a.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">梦康</span>
</div>
<div class="bd">有一张表article_rank 里面有是个字段(id,aid,pv,day),都是 int 类型。现执行如下 sql<br>select `aid`,sum(`pv`) as num from article_rank where `day`>20190115 group by aid order by num desc limit 10;<br><br>optimizer_trace 结果中关于执行阶段数据解读还是有些问题。<br> {<br> "creating_tmp_table": {<br> "tmp_table_info": {<br> "table": "intermediate_tmp_table",<br> "row_length": 20,<br> "key_length": 4,<br> "unique_constraint": false,<br> "location": "memory (heap)",<br> "row_limit_estimate": 838860<br> }<br> }<br> },<br> {<br> "converting_tmp_table_to_ondisk": {<br> "cause": "memory_table_size_exceeded",<br> "tmp_table_info": {<br> "table": "intermediate_tmp_table",<br> "row_length": 20,<br> "key_length": 4,<br> "unique_constraint": false,<br> "location": "disk (InnoDB)",<br> "record_format": "fixed"<br> }<br> }<br> }<br><br>1. row_length 为什么是20呢?我 gdb 调试确认临时表里存放的是 aid,num。 aid 4个字节,num 因为是 sum 的结果是 DECIMAL 类型,所以是15个字节,不知道为什么总长度是20字节了。测试其他 sql 均发现row_length会比临时表种的字段所占长度多1字节,这是为何呢?<br>2. 创建临时表提示内存超出限制,但是根据第一步行数限制是 838860 行,实际总共符合条件的行数为 649091 通过 select count(distinct aid) from article_rank where `day`>20190115 查询得到。为什么会超出内存呢?<br><br>麻烦老师帮忙解答下。谢谢啦。 <br></div>
<span class="time">2019-02-11 15:40</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/31/c8/a64e4aef.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">兔斯基</span>
</div>
<div class="bd">老师,关于排序有几个问题。<br>order by id,主键<br>order by null,<br>不加order by<br>这三种写法哪种执行效率更高一些?后面两者是不是等价的? <br></div>
<span class="time">2019-02-11 07:55</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">这三种写法语义上不一样。。<br><br>如果对返回结果没有顺序要求,那写上order by null肯定是好的。<br><br>“order by null”和“不加order by”不等价,咱们文中有说哈</p>
<p class="reply-time">2019-02-11 16:29</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/0f/94/59/ac2aa72b.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Smile</span>
</div>
<div class="bd">当碰到第一个 2 的时候,已经知道累积了 Y 个 1,结果集里的第一行就是 (1,Y);<br>---- <br>应该是 结果集里的第 二 行 吧<br><br><br><br> <br></div>
<span class="time">2019-02-11 00:30</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">对的,👍🏿细致<br><br>发起勘误了,新年快乐</p>
<p class="reply-time">2019-02-11 11:09</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/14/20/3a/90db6a24.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Long</span>
</div>
<div class="bd">老师,新年好! :-)<br><br>有几个版本差异的问题:<br>(1)图1中的执行计划应该是5.7版本以后的吧,貌似没找到说在哪个环境,我在5.6和5.7分别测试了,id = 2的那个rows,在5.6版本(5.6.26)是1000,在5.7版本是2行。应该是5.7做的优化吧?<br><br>(2)图 9 group + order by null 的结果(此盘临时表),这里面mysql5.6里面执行的结果是(1,10),(2,10)...(10,10),执行计划都是只有一样,没找到差异。<br>跟踪下了下optimizer trace,发现问题应该是在临时表空间满的的时候,mysql5.7用的是:converting_tmp_table_to_ondisk "location": "disk (InnoDB)",,而mysql 5.6用的是converting_tmp_table_to_myisam "location": "disk (MyISAM)"的原因导致的。<br>查了下参数:<br>default_tmp_storage_engine。(5.6,5.7当前值都是innodb)<br>internal_tmp_disk_storage_engine(只有5.7有这个参数,当前值是innodb),5.6应该是默认磁盘临时表就是MyISAM引擎的了,由于本地测试环境那个临时表的目录下找不到临时文件,也没法继续分析了。。。<br><br>至于为什么MySQL 5.6中结果展示m字段不是0-9而是1-10,还得请老师帮忙解答下了。<br><br><br>还有几个小问题,为了方便解答,序号统一了:<br>(3)在阅读mysql执行计划的时候,看了网上有很多说法,也参考了mysql官网对id(select_id)的解释:<br>id (JSON name: select_id)<br>The SELECT identifier. This is the sequential number of the SELECT within the query.(感觉这个读起来也有点歧义,这个sequential字面解释感觉只有顺序的号码,并咩有说执行顺序)<br>比如图1,文中解释就是从ID小的往大的执行的,网上有很多其他说法,有的是说ID从大到小执行,遇到ID一样的,就从上往下执行。有的说是从小往大顺序执行。不知道老师是否可以官方讲解下。<br><br>(4)我发现想搞懂一个原理,并且讲清楚让别人明白,真的是很有难度,非常感谢老师的分享。这次专栏结束,还会推出的新的专栏吗? 非常期待。 <br></div>
<span class="time">2019-02-10 08:24</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/10/78/31/c7f8d1db.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">Laputa</span>
</div>
<div class="bd">老师好,文中说的不需要排序为什么不直接把orderby去掉而是写order by null <br></div>
<span class="time">2019-02-08 17:36</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">MySQL 语义上这么定义的… </p>
<p class="reply-time">2019-02-08 22:53</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/11/11/18/8cee35f9.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">HuaMax</span>
</div>
<div class="bd">课后题解答。图8是用内存临时表,文中已经提到,是按照表t1的索引a顺序取出数据,模10得0的id是最后一行;图9是用硬盘临时表,默认用innodb 的索引,主键是id%10,因此存入硬盘后再按主键树顺序取出,0就排到第一行了。 <br></div>
<span class="time">2019-02-07 21:17</span>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://thirdwx.qlogo.cn/mmopen/vi_32/DkPNQQn7d39cpNa5Ux8l1AomYPDNb1EKPMcY5NlkL6MCxj2bzxAYicBTu6KFhQ4br7fwWPgdc0dxnezp7v8l7JA/132" class="avatar">
<div class="info">
<div class="hd"><span class="username">牛牛</span>
</div>
<div class="bd">新年快乐~、感谢有您~^_^~ <br></div>
<span class="time">2019-02-06 22:30</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">新年快乐~🤝</p>
<p class="reply-time">2019-02-07 09:22</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/12/0c/48/ba59d28d.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">poppy</span>
</div>
<div class="bd">老师,春节快乐,过年还在更新,辛苦辛苦。<br>关于思考题,我的理解是图8中的查询是使用了内存临时表,存储的顺序就是id%10的值的插入顺序,而图9中的查询,由于内存临时表大小无法满足,所以使用了磁盘临时表,对于InnoDB来说,就是对应B+树这种数据结构,这里会按照id%100(即m)的大小顺序来存储的,所以返回的结果当然也是有序的 <br></div>
<span class="time">2019-02-06 20:17</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">新年好~ <br><br>👍</p>
<p class="reply-time">2019-02-07 09:26</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/20/9a/96259fb9.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">张八百</span>
</div>
<div class="bd">春节快乐,老师。谢谢你让我学到不少知识 <br></div>
<span class="time">2019-02-06 13:17</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">新年快乐🤝</p>
<p class="reply-time">2019-02-06 16:28</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/13/f8/70/f3a33a14.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">某、人</span>
</div>
<div class="bd">老师春节快乐,辛苦了 <br></div>
<span class="time">2019-02-06 09:59</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">春节快乐,🤝</p>
<p class="reply-time">2019-02-06 12:33</p>
</div>
</div>
</li>
<li data-v-87ffcada="" class="comment-item"><img
src="https://static001.geekbang.org/account/avatar/00/14/05/d4/e06bf86d.jpg" class="avatar">
<div class="info">
<div class="hd"><span class="username">长杰</span>
</div>
<div class="bd">图九使用的是磁盘临时表,磁盘临时表使用的引擎是innodb,innodb是索引组织表,按主键顺序存储数据,所以是按照m字段有序的。 <br></div>
<span class="time">2019-02-06 08:38</span>
<div class="reply">
<div class="reply-hd"><span>作者回复</span></div>
<p class="reply-content">👍🏿<br>春节快乐</p>
<p class="reply-time">2019-02-06 12:34</p>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</body>
</html>