Mysql性能优化----SQL语句优化、索引优化、数据库结构优化、系统配置优化、服务器硬件优化

一、SQL语句优化

1-1.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 |
+----------+------------------+------------+---------------------+
<pre name="code" class="sql">[email protected]:~$ 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
# [email protected]: 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

[email protected]:~$ mysqldumpslow --help

[email protected]:~$ sudo mysqldumpslow -t 3 /var/lib/mysql/ubuntu-slow.log | more

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

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)

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

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

可以看到返回请求数据的行数有一万多条,不是很好,优化如下

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)

mysql> 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

<pre name="code" class="sql">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).子查询的优化

mysql> 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: <derived2>
         type: ref
possible_keys: <auto_key0>
          key: <auto_key0>
      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查询的优化

mysql> 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 |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+

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

时间: 2024-10-06 00:12:22

Mysql性能优化----SQL语句优化、索引优化、数据库结构优化、系统配置优化、服务器硬件优化的相关文章

mysql优化sql语句

mysql优化sql语句 常见误区 www.2cto.com 误区1: count(1)和count(primary_key) 优于 count(*) 很多人为了统计记录条数,就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他们认为这样性能更好, 其实这是一个误区.对于有些场景,这样做可能性能会更差,应为数据库对 count(*) 计数操作做了一些特别的优化. 误区2: count(column) 和 count(*) 是一样的 这个误区甚至在很多

应用索引技术优化SQL 语句一

一.前言 很多数据库系统性能不理想是因为系统没有经过整体优化,存在大量性能低下的SQL 语句.这类SQL语句性能不好的首要原因是缺乏高效的索引.没有索引除了导致语句本身运行速度慢外,更是导致大量的磁盘读写操作,使得整个系统性能都受之影响而变差.解决这类系统的首要办法是优化这些没有索引或索引不够好的SQL语句. 本文讨论和索引相关的有关内容,以及通过分析语句的执行计划来讲述如何应用索引技术来优化SQL 语句.通过分析执行计划,读者可以检查索引是否有用,以及如何创建高效的索引.本文对数据库管理人员以

应用索引技术优化SQL 语句三

六.有关索引的几个问题 问题1,是否值得在identity字段上建立聚集索引.答案取决于identity 字段如何在语句中使用.如果你经常根据该字段搜索返回很少的行,那么在其上建立索引是值得的.反之如果identity字段根本很少在语句中使用,那么就不应该对其建立任何索引. 问题2,一个表应该建立多少索引合适.如果表的80%以上的语句都是读操作,那么索引可以多些.但是不要太多.特别是不要对那些更新频繁的表其建立很多的索引.很少表有超过5个以上的索引.过多的索引不但增加其占用的磁盘空间,也增加了S

性能优化——SQL语句(续)

上篇博客介绍了一下自己在项目中遇到的一种使用sql语句的优化方式(性能优化--SQL语句),但是说的不够完整.在对比的过程中,没有将max函数考虑在内,经人提醒之后赶紧做了一个测试,测试过程中又学到了不少的东西.现给大家分享一下 上次用的是select count(*) 和select * 的执行效率问题,因为我的需求是获取数据的一个总数来自动给出新的id,然后网友给出可以使用max的方式给出新id.其实这也是一种不错的思路(当时我们也用过该函数,只不过因为系统数据本身问题,不适合用该函数),然

数据库调优教程(十二) 优化sql语句

五.           优化Sql语句 上一章讲了如何设计一张好的表,一张好的表自然需要好的sql语句去操作它.本章就来聊聊如何优化sql语句. 1.      Sql语句优化原则 优化需要优化的Query 定位优化对象性能瓶颈 从Explain入手 尽可能在索引中完成排序 只取自己需要的Column 尽可能避免复杂的join和子查询 2.     优化limit select * from test1 order by id limit 99999,10 原语句虽然使用了id索引,但是相当于

如何优化sql语句

(1)选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写 在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的 情况下,你必须选择记录条数最少的表作为基础表.如果有3个以上的表连接查询 , 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其 他表所引用的表. (2) WHERE子句中的连接顺序.: ORACLE采用自下而上的顺序解析W

【转】 如何优化sql语句

============推荐============ csdn:http://blog.csdn.net/e3002/article/details/1817941 ====如何优化sql语句==== (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写 在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的 情况下,你必须选择记录条数最少的表作为基础表.如果有3个以上的

通过profile优化SQL语句

开启profile优化SQL语句:set profiling=1;执行SQL语句show profiles;show profile for query 2;//根据query_id 查看某个查询的详细时间耗费 SHOW STATUS LIKE 'last_query_cost';//查询上一条语句执行的代价 例: mysql> show profiles;+----------+------------+----------------------------------------+| Qu

Mysql explain分析SQL语句之字段属性说明

在 explain的帮助下,您就知道什么时候该给表添加索引,以使用索引来查找记录从而让select 运行更快.如果由于不恰当使用索引而引起一些问题的话,可以运行 analyze table来更新该表的统计信息,例如键的基数,它能帮您在优化方面做出更好的选择. explain 返回了一行记录,它包括了 select语句中用到的各个表的信息.这些表在结果中按照mysql即将执行的查询中读取的顺序列出来.mysql用一次扫描多次连接(single- sweep,multi-join)的方法来解决连接.

MySQL管理之SQL语句实例

MySQL管理之SQL语句实例 首先,我们来导入world库,这个world库中的表是mysql ocp考试专用表,在网上有下 mysql> source/root/world_innodb.sql 表结构如下: 本文来自http://yijiu.blog.51cto.com 转载请经博主允许 ,盗帖可耻! CREATE TABLE `Country` (  `Code` char(3) NOT NULL DEFAULT '',  `Name` char(52) NOT NULL DEFAULT