@@ -70,7 +70,7 @@ MySQL支持做数据分区,通过分区可以存储更多的数据、优化查
70
70
| slow_query_log | OFF |
71
71
| slow_query_log_file | / mysql/ data/ localhost- slow .log |
72
72
+ -- -------------------------+----------------------------------+
73
-
73
+
74
74
mysql> show variables like ' long_query_time' ;
75
75
+ -- ---------------+-----------+
76
76
| Variable_name | Value |
@@ -124,24 +124,99 @@ MySQL支持做数据分区,通过分区可以存储更多的数据、优化查
124
124
125
125
3 . 通过` show profiles` 和` show profile for query` 分析SQL。
126
126
127
+ MySQL从5 .0 .37 开始支持剖面系统来帮助用户了解SQL执行性能的细节,可以通过下面的方式来查看MySQL是否支持和开启了剖面系统。
128
+
129
+ ` ` ` SQL
130
+ select @@have_profiling;
131
+ select @@profiling;
132
+ ` ` `
133
+
134
+ 如果没有开启剖面系统,可以通过下面的SQL来打开它。
135
+
136
+ ` ` ` SQL
137
+ set profiling=1;
138
+ ` ` `
139
+
140
+ 接下来就可以通过剖面系统来了解SQL的执行性能,例如:
141
+
142
+ ` ` ` SQL
143
+ mysql> select count(*) from tb_emp;
144
+ +----------+
145
+ | count(*) |
146
+ +----------+
147
+ | 14 |
148
+ +----------+
149
+ 1 row in set (0.00 sec)
150
+
151
+ mysql> show profiles;
152
+ +----------+------------+-----------------------------+
153
+ | Query_ID | Duration | Query |
154
+ +----------+------------+-----------------------------+
155
+ | 1 | 0.00029600 | select count(*) from tb_emp |
156
+ +----------+------------+-----------------------------+
157
+ 1 row in set, 1 warning (0.00 sec)
158
+
159
+ mysql> show profile for query 1;
160
+ +----------------------+----------+
161
+ | Status | Duration |
162
+ +----------------------+----------+
163
+ | starting | 0.000076 |
164
+ | checking permissions | 0.000007 |
165
+ | Opening tables | 0.000016 |
166
+ | init | 0.000013 |
167
+ | System lock | 0.000007 |
168
+ | optimizing | 0.000005 |
169
+ | statistics | 0.000012 |
170
+ | preparing | 0.000010 |
171
+ | executing | 0.000003 |
172
+ | Sending data | 0.000070 |
173
+ | end | 0.000012 |
174
+ | query end | 0.000008 |
175
+ | closing tables | 0.000012 |
176
+ | freeing items | 0.000032 |
177
+ | cleaning up | 0.000013 |
178
+ +----------------------+----------+
179
+ 15 rows in set, 1 warning (0.00 sec)
180
+ ` ` `
181
+
127
182
4 . 优化CRUD操作。
128
183
129
184
- 优化` insert` 语句
130
185
- 在` insert` 语句后面跟上多组值进行插入在性能上优于分开` insert` 。
131
186
- 如果有多个连接向同一个表插入数据,使用` insert delayed` 可以获得更好的性能。
132
187
- 如果要从一个文本文件装载数据到表时,使用` load data infile` 比` insert` 性能好得多。
188
+
133
189
- 优化` order by` 语句
190
+
134
191
- 如果` where` 子句的条件和` order by` 子句的条件相同,而且排序的顺序与索引的顺序相同,如果还同时满足排序字段都是升序或者降序,那么只靠索引就能完成排序。
192
+
135
193
- 优化` group by` 语句
194
+
136
195
- 在使用` group by` 子句分组时,如果希望避免排序带来的开销,可以用` order by null` 禁用排序。
196
+
137
197
- 优化嵌套查询
198
+
199
+ - MySQL从4 .1 开始支持嵌套查询(子查询),这使得可以将一个查询的结果当做另一个查询的一部分来使用。在某些情况下,子查询可以被更有效率的连接查询取代,因为在连接查询时MySQL不需要在内存中创建临时表来完成这个逻辑上需要多个步骤才能完成的查询。
200
+
138
201
- 优化or 条件
202
+
139
203
- 如果条件之间是` or` 关系,则只有在所有条件都用到索引的情况下索引才会生效。
204
+
140
205
- 优化分页查询
206
+
207
+ - 分页查询时,一个比较头疼的事情是如同` limit 1000, 20` ,此时MySQL已经排序出前1020 条记录但是仅仅返回第1001 到1020 条记录,前1000 条实际都用不上,查询和排序的代价非常高。一种常见的优化思路是在索引上完成排序和分页的操作,然后根据返回的结果做表连接操作来得到最终的结果,这样可以避免出现全表查询,也避免了外部排序。
208
+
209
+ ` ` ` SQL
210
+ select * from tb_emp order by ename limit 1000, 20;
211
+ select * from tb_emp t1 inner join (select eno from tb_emp order by ename limit 1000, 20) t2 on t1.eno=t2.eno;
212
+ ` ` `
213
+
214
+ 上面的代码中,第2 行SQL是优于第1 行SQL的,当然我们的前提是已经在` ename` 字段上创建了索引。
215
+
141
216
- 使用SQL提示
142
- - USE INDEX
143
- - IGNORE INDEX
144
- - FORCE INDEX
217
+ - USE INDEX:建议MySQL使用指定的索引。
218
+ - IGNORE INDEX:建议MySQL忽略掉指定的索引。
219
+ - FORCE INDEX:强制MySQL使用指定的索引。
145
220
146
221
# ## 配置优化
147
222
@@ -164,24 +239,32 @@ show status like 'connections';
164
239
show status like 'slow_queries';
165
240
` ` `
166
241
167
- 1 . 调整max_connections
168
- 2 . 调整back_log
169
- 3 . 调整table_open_cache
170
- 4 . 调整thread_cache_size
171
- 5 . 调整innodb_lock_wait_timeout
172
- 6 . 调整` innodb_buffer_pool_size` :InnoDB数据和索引的内存缓冲区大小,以字节为单位,这个值设置得越高,访问表数据需要进行的磁盘I/ O操作就越少,如果可能甚至可以将该值设置为物理内存大小的80 %。
242
+ 1 . 调整` max_connections` :MySQL最大连接数量,默认151 。在Linux系统上,如果内存足够且不考虑用户等待响应时间这些问题,MySQL理论上可以支持到万级连接,但是通常情况下,这个值建议控制在1000 以内。
243
+ 2 . 调整` back_log` :TCP连接的积压请求队列大小,通常是max_connections的五分之一,最大不能超过900 。
244
+ 3 . 调整` table_open_cache` :这个值应该设置为max_connections的N倍,其中N代表每个连接在查询时打开的表的最大个数。
245
+ 4 . 调整` innodb_lock_wait_timeout` :该参数可以控制InnoDB事务等待行锁的时间,默认值是50ms,对于反馈响应要求较高的应用,可以将这个值调小避免事务长时间挂起;对于后台任务,可以将这个值调大来避免发生大的回滚操作。
246
+ 5 . 调整` innodb_buffer_pool_size` :InnoDB数据和索引的内存缓冲区大小,以字节为单位,这个值设置得越高,访问表数据需要进行的磁盘I/ O操作就越少,如果可能甚至可以将该值设置为物理内存大小的80 %。
173
247
174
248
# ## 架构优化
175
249
176
250
1 . 通过拆分提高表的访问效率。
177
251
- 垂直拆分
178
252
- 水平拆分
253
+
179
254
2 . 逆范式理论。数据表设计的规范程度称之为范式(Normal Form),要提升表的规范程度通常需要将大表拆分为更小的表,范式级别越高数据冗余越小,而且在插入、删除、更新数据时出问题的可能性会大幅度降低,但是节省了空间就意味着查询数据时可能花费更多的时间,原来的单表查询可能会变成连表查询。为此,项目实践中我们通常会进行逆范式操作,故意降低范式级别增加冗余来减少查询的时间开销。
180
255
- 1NF:列不能再拆分
181
256
- 2NF:所有的属性都依赖于主键
182
257
- 3NF:所有的属性都直接依赖于主键(消除传递依赖)
183
258
- BCNF:消除非平凡多值依赖
259
+
184
260
3 . 使用中间表提高统计查询速度。
261
+
262
+ 使用` insert into 中间表 select ... where ...` 这样的语句先将需要的数据筛选出来放到中间表中,然后再对中间表进行统计,避免不必要的运算和处理。
263
+
185
264
4 . 主从复制和读写分离,具体内容请参考[《项目部署上线和性能调优》](./ 98 .项目部署上线和性能调优.md)。
265
+
186
266
5 . 配置MySQL集群。
187
267
268
+
269
+
270
+ > ** 说明** :本章内容参考了网易出品的《深入浅出MySQL》一书,该书和《高性能MySQL》一样,都对MySQL进行了深入细致的讲解,虽然总体感觉后者更加高屋建瓴,但是前者也算得上是提升MySQL技能的佳作(作者的文字功底稍显粗糙,深度也不及后者),建议有兴趣的读者可以阅读这两本书。
0 commit comments