MySql数据库优化

目录

一、 优化思路

二、查询MySql服务运行状态值

三、获取需要优化的sql

方式一:查看运行的线程

方式二:开启慢查询日志

四 、分析 SQL 语句

方式一:explain

方式二:profiling

五、优化方式

1、查询优化

2、 索引使用

5.2.1 适合使用索引的情况

5.2.2 不适合使用索引的情况

5.2.3 索引创建和使用原则


一、 优化思路

二、查询MySql服务运行状态值

show status

  主要关注 “Queries”、“Threadsconnected” 和 “Threadsrunning” 的值,即查询次数、线程连接数和线程运行数。

  使用以下脚本监控 MySQL 服务器运行的状态值

#!/bin/bash
while true
do
mysqladmin -uroot -p"密码" ext | awk '/Queries/{q=$4}/Threads_connected/{c=$4}/Threads_running/{r=$4}END{printf("%d %d %d\n",q,c,r)}' >> status.txt
sleep 1
done

三、获取需要优化的sql

方式一:查看运行的线程

  查询出线程执行的命令/sql以及所执行的时间返回的 State 的值是我们判断性能好坏的关键。

show processlist

  下面列表指所需要优化的sql

Converting HEAP to MyISAM # 查询结果太大时,把结果放到磁盘,严重
Create tmp table #创建临时表,严重
Copying to tmp table on disk  #把内存临时表复制到磁盘,严重
locked #被其他查询锁住,严重
loggin slow query #记录慢查询
Sorting result #排序
方式二:开启慢查询日志

  在配置文件 my.cnf 中的 [mysqld] 一行下边添加两个参数:

  slowquerylog = 1 表示开启慢查询;slowquerylogfile 表示慢查询日志存放的位置;longquerytime = 2 表示查询 >=2 秒才记录日志;logqueriesnotusing_indexes = 1 记录没有使用索引的 SQL 语句。

slow_query_log = 1
slow_query_log_file=/var/lib/mysql/slow-query.log
long_query_time = 2

log_queries_not_using_indexes = 1

  MySQL 提供 mysqldumpslow 工具对日志进行分析。我们可以使用 mysqldumpslow --help 查看命令相关用法。

  常用参数:

    -s:排序方式,后边接着如下参数
        c:访问次数
        l:锁定时间
        r:返回记录
        t:查询时间
    al:平均锁定时间
    ar:平均返回记录书
    at:平均查询时间
    -t:返回前面多少条的数据
    -g:翻遍搭配一个正则表达式,大小写不敏感

示例:

获取返回记录集最多的10个sql
mysqldumpslow -s r -t 10 /var/lib/mysql/slow-query.log

获取访问次数最多的10个sql
mysqldumpslow -s c -t 10 /var/lib/mysql/slow-query.log

获取按照时间排序的前10条里面含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/slow-query.log

四 、分析 SQL 语句

方式一:explain

  查看 SQL 执行计划情况(关联表,表查询顺序、索引使用情况等)。

explain select * from category;
mysql> explain select * from category;
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | category | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

1) id:select 查询序列号。id相同,执行顺序由上至下;id不同,id值越大优先级越高,越先被执行

2) select_type:查询数据的操作类型,其值如下:

  • simple:简单查询,不包含子查询或 union

  • primary:包含复杂的子查询,最外层查询标记为该值

  • subquery:在 select 或 where 包含子查询,被标记为该值

  • derived:在 from 列表中包含的子查询被标记为该值,MySQL 会递归执行这些子查询,把结果放在临时表

  • union:若第二个 select 出现在 union 之后,则被标记为该值。若 union 包含在 from 的子查询中,外层 select 被标记为 derived

  • union result:从 union 表获取结果的 select

3) table:显示该行数据是关于哪张表

4) partitions:匹配的分区

5) type:表的连接类型,其值,性能由高到底排列如下:

  • system:表只有一行记录,相当于系统表

  • const:通过索引一次就找到,只匹配一行数据

  • eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常用于主键或唯一索引扫描

  • ref:非唯一性索引扫描,返回匹配某个单独值的所有行。用于=、< 或 > 操作符带索引的列

  • range:只检索给定范围的行,使用一个索引来选择行。一般使用between、>、<情况

  • index:只遍历索引树

  • ALL:全表扫描,性能最差

注:前5种情况都是理想情况的索引使用情况。通常优化至少到range级别,最好能优化到 ref

6) possible_keys:指出 MySQL 使用哪个索引在该表找到行记录。如果该值为 NULL,说明没有使用索引,可以建立索引提高性能

7) key:显示 MySQL 实际使用的索引。如果为 NULL,则没有使用索引查询

8) key_len:表示索引中使用的字节数,通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好 显示的是索引字段的最大长度,并非实际使用长度

9) ref:显示该表的索引字段关联了哪张表的哪个字段

10) rows:根据表统计信息及选用情况,大致估算出找到所需的记录或所需读取的行数,数值越小越好

11) filtered:返回结果的行数占读取行数的百分比,值越大越好

12) extra:包含不合适在其他列中显示但十分重要的额外信息,常见的值如下:

  • using filesort:说明 MySQL 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。出现该值,应该优化 SQL

  • using temporary:使用了临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。出现该值,应该优化 SQL

  • using index:表示相应的 select 操作使用了覆盖索引,避免了访问表的数据行,效率不错

  • using where:where 子句用于限制哪一行

  • using join buffer:使用连接缓存

  • distinct:发现第一个匹配后,停止为当前的行组合搜索更多的行

方式二:profiling

  使用 profiling 命令可以了解 SQL 语句消耗资源的详细信息(每个执行步骤的开销)

show profiles;

  查询指定 ID 的执行详细信息

show profile for query Query_ID;

  获取 CPU、 Block IO 等信息

show profile block io,cpu for query Query_ID;

show profile cpu,block io,memory,swaps,context switches,source for query Query_ID;

show profile all for query Query_ID;

五、优化方式

1、查询优化

1) 避免 SELECT *,需要什么数据,就查询对应的字段。

2) 小表驱动大表,即小的数据集驱动大的数据集。如:以 A,B 两表为例,两表通过 id 字段进行关联。

当 B 表的数据集小于 A 表时,用 in 优化 exist;使用 in ,两表执行顺序是先查 B 表,再查 A 表

select * from A where id in (select id from B)

当 A 表的数据集小于 B 表时,用 exist 优化 in;使用 exists,两表执行顺序是先查 A 表,再查 B 表

select * from A where exists (select 1 from B where B.id = A.id)

3) 一些情况下,可以使用连接代替子查询,因为使用 join,MySQL 不会在内存中创建临时表。

4) 适当添加冗余字段,减少表关联。

5) 合理使用索引(下文介绍)。如:为排序、分组字段建立索引,避免 filesort 的出现。

2、 索引使用
5.2.1 适合使用索引的情况

1) 主键自动创建唯一索引

2) 频繁作为查询条件的字段

3) 查询中与其他表关联的字段

4) 查询中排序的字段

5) 查询中统计或分组字段

5.2.2 不适合使用索引的情况

1) 频繁更新的字段

2) where 条件中用不到的字段

3) 表记录太少

4) 经常增删改的表

5) 字段的值的差异性不大或重复性高

5.2.3 索引创建和使用原则

1) 单表查询:哪个列作查询条件,就在该列创建索引

2) 多表查询:left join 时,索引添加到右表关联字段;right join 时,索引添加到左表关联字段

3) 不要对索引列进行任何操作(计算、函数、类型转换)

4) 索引列中不要使用 !=,<> 非等于

5) 索引列不要为空,且不要使用 is null 或 is not null 判断

6) 索引字段是字符串类型,查询条件的值要加''单引号,避免底层类型自动转换

违背上述原则可能会导致索引失效,具体情况需要使用 explain 命令进行查看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值