mysql优化器 屏蔽索引_MySQL性能优化 SQL语句优化、索引优化、数据库结构优化、系统配置优化、服务器硬件优化...

1473338143408088149.jpg

MySQL慢日志

1).慢日志开启方式和存储格式

如何发现有问题的SQL? 使用MySQL慢日志对有效率问题的SQL进行监控。

前期准备mysql> show variables like '%log_queri%';

+-------------------------------+-------+

| Variable_name                 | Value |

+-------------------------------+-------+

| log_queries_not_using_indexes | OFF   |

+-------------------------------+-------+

# 记录未使用索引的查询

mysql> set global log_queries_not_using_indexes=on;

Query OK, 0 rows affected (0.03 sec)mysql> show variables like 'slow_query_log';

+----------------+-------+

| Variable_name  | Value |

+----------------+-------+

| slow_query_log | OFF   |

+----------------+-------+

# 开启慢查询日志

mysql> set global slow_query_log=on;

Query OK, 0 rows affected (0.32 sec)# 把大于10毫秒的查询记录到日志里

mysql> show variables like 'long_query_time';

+-----------------+-----------+

| Variable_name   | Value     |

+-----------------+-----------+

| long_query_time | 10.000000 |

+-----------------+-----------+mysql> use sakila;

Database changed

mysql> show tables;

23 rows in set (0.00 sec)

# 查看慢查日志在什么地文

mysql> show variables like 'slow_query_log_file%';

+---------------------+--------------------------------+

| Variable_name       | Value                          |

+---------------------+--------------------------------+

| slow_query_log_file | /var/lib/mysql/ubuntu-slow.log |

+---------------------+--------------------------------+

mysql> select * from store limit 10;

+----------+------------------+------------+---------------------+

| store_id | manager_staff_id | address_id | last_update         |

+----------+------------------+------------+---------------------+

|        1 |                1 |          1 | 2006-02-15 04:57:12 |

|        2 |                2 |          2 | 2006-02-15 04:57:12 |

+----------+------------------+------------+---------------------+

changwen@ubuntu:~$ sudo tail -50 /var/lib/mysql/ubuntu-slow.log

/usr/sbin/mysqld, Version: 5.6.30-0ubuntu0.15.10.1 ((Ubuntu)). started with:

Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock

Time                 Id Command    Argument

/usr/sbin/mysqld, Version: 5.6.30-0ubuntu0.15.10.1 ((Ubuntu)). started with:

Tcp port: 3306  Unix socket: /var/run/mysqld/mysqld.sock

Time                 Id Command    Argument

# Time: 160908  0:47:01

# User@Host: root[root] @ localhost []  Id:     2

# Query_time: 0.019114  Lock_time: 0.000065 Rows_sent: 2  Rows_examined: 2

use sakila;

SET timestamp=1473320821;

select * from store limit 10;

2).慢查日志分析工具之mysqldumpslow

changwen@ubuntu:~$ mysqldumpslow --help

changwen@ubuntu:~$ sudo mysqldumpslow -t 3 /var/lib/mysql/ubuntu-slow.log | more

3).慢查日志分析工具之pt-query-digest

1473337783571023925.png

1473337789337035139.png

4).通过explain查询和分析SQL的执行计划mysql> explain select customer_id,first_name,last_name from customer;

+----+-------------+----------+------+---------------+------+---------+------+------+-------+

| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra |

+----+-------------+----------+------+---------------+------+---------+------+------+-------+

|  1 | SIMPLE      | customer | ALL  | NULL          | NULL | NULL    | NULL |  599 | NULL  |

+----+-------------+----------+------+---------------+------+---------+------+------+-------+

1 row in set (0.94 sec)

1473337838602088756.png

5).Count()和Max()的优化

查询最后支付时间 -- 优化max()函数。

1473337867872003549.png

可以看到返回请求数据的行数有一万多条,不是很好,优化如下mysql> create index idx_paydate on payment(payment_date);

mysql> explain select max(payment_date) from payment \G

*************************** 1. row ***************************

id: 1

select_type: SIMPLE

table: NULL

type: NULL

possible_keys: NULL

key: NULL

key_len: NULL

ref: NULL

rows: NULL

Extra: Select tables optimized away

1 row in set (0.03 sec)

1473337908991087574.pngmysql> create table t(id int);  

Query OK, 0 rows affected (0.62 sec)

mysql> insert into t values(1),(2),(null);

Query OK, 3 rows affected (0.20 sec)

Records: 3  Duplicates: 0  Warnings: 0

mysql> select count(*), count(id) ,count(id='2'),count(id='2' or null)from t;

+----------+-----------+---------------+-----------------------+

| count(*) | count(id) | count(id='2') | count(id='2' or null) |

+----------+-----------+---------------+-----------------------+

|        3 |         2 |             2 |                     1 |

+----------+-----------+---------------+-----------------------+

1 row in set (0.00 sec)

mysql> select count(release_year='2006' or null) as '2006' ,count(release_year='2007' or null) as '2007' from film;+------+------+| 2006 | 2007 |+------+------+| 540 | 160 |+------+------+

6).子查询的优化

1473337953425098527.pngmysql> create table t1(tid int);  

Query OK, 0 rows affected (0.21 sec)

mysql> insert into t1 values(1),(1);

Query OK, 1 row affected (0.11 sec)

-- 加distinct即可

mysql> select t.id from t join t1 on t.id = t1.tid;

+------+

| id   |

+------+

|    1 |

|    1 |

+------+

2 rows in set (0.00 sec)

mysql> select * from t where t.id in (select t1.tid from t1);

+------+

| id   |

+------+

|    1 |

+------+

1 row in set (0.25 sec)

7).group by的优化mysql> explain select actor.first_name, actor.last_name, count(*) from sakila.film_actor

inner join sakila.actor USING(actor_id) group by film_actor.actor_id \G

*************************** 1. row ***************************

id: 1

select_type: SIMPLE

table: actor

type: ALL

possible_keys: PRIMARY

key: NULL

key_len: NULL

ref: NULL

rows: 200

Extra: Using temporary; Using filesort

*************************** 2. row ***************************

id: 1

select_type: SIMPLE

table: film_actor

type: ref

possible_keys: PRIMARY,idx_fk_film_id

key: PRIMARY

key_len: 2

ref: sakila.actor.actor_id

rows: 13

Extra: Using index

2 rows in set (0.01 sec)

上面那个sql查询可以看到,使用了临时表和文件排序,这样不好,优化如下mysql> explain select actor.first_name, actor.last_name, c.cnt  from sakila.actor

inner join (select actor_id, count(*) as cnt from sakila.film_actor  group by actor_id )as c USING(actor_id) \G

*************************** 1. row ***************************

id: 1

select_type: PRIMARY

table: actor

type: ALL

possible_keys: PRIMARY

key: NULL

key_len: NULL

ref: NULL

rows: 200

Extra: NULL

*************************** 2. row ***************************

id: 1

select_type: PRIMARY

table: 

type: ref

possible_keys: 

key: 

key_len: 2

ref: sakila.actor.actor_id

rows: 27

Extra: NULL

*************************** 3. row ***************************

id: 2

select_type: DERIVED

table: film_actor

type: index

possible_keys: PRIMARY,idx_fk_film_id

key: PRIMARY

key_len: 4

ref: NULL

rows: 5462

Extra: Using index

3 rows in set (0.00 sec)

8).Limit查询的优化

1473338025622070874.pngmysql> explain select film_id,description from sakila.film order by title limit 50,5;  

+----+-------------+-------+------+---------------+------+---------+------+------+----------------+

| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |

+----+-------------+-------+------+---------------+------+---------+------+------+----------------+

|  1 | SIMPLE      | film  | ALL  | NULL          | NULL | NULL    | NULL | 1000 | Using filesort |

+----+-------------+-------+------+---------------+------+---------+------+------+----------------+

优化步骤1:使用有索引的列或主键进行order by操作mysql> explain select film_id,description from sakila.film order by film_id limit 50,5;

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+

| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra |

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+

|  1 | SIMPLE      | film  | index | NULL          | PRIMARY | 2       | NULL |   55 | NULL  |

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------+

1 row in set (0.00 sec)

如果上面为500,5则rows是505,如果数太多,也会影响性能,优化如下:

优化步骤2:记录一次返回的主键,在下次查询时使用主键过滤mysql> explain select film_id,description from sakila.film where film_id>55 and film_id<=60 order by film_id limit 1,5;

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

|  1 | SIMPLE      | film  | range | PRIMARY       | PRIMARY | 2       | NULL |    5 | Using where |

+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

上面主键一定要是顺序排序的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值