MySQL之SQL语句优化

一 SQL语句优化的一般步骤:

1 通过show status命令了解各种SQL语句的执行频率

mysql> show status;                #show status:显示服务器状态信息

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

| Variable_name                                 | Value       |

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

| Aborted_clients                               | 0           |

| Aborted_connects                              | 0           |

| Binlog_cache_disk_use                         | 0           |

| Binlog_cache_use                              | 8           |

| Binlog_stmt_cache_disk_use                    | 0           |

| Binlog_stmt_cache_use                         | 25          |

| Bytes_received                                | 2919        |

| Bytes_sent                                    | 51750       |

......

mysql> show status like "com%";    #显示当前session中,统计参数的值

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

| Variable_name             | Value |

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

| Com_admin_commands        | 0     |

| Com_assign_to_keycache    | 0     |

| Com_alter_db              | 0     |

| Com_alter_db_upgrade      | 0     |

| Com_alter_event           | 0     |

| Com_alter_function        | 0     |

| Com_alter_procedure       | 0     |

| Com_alter_server          | 0     |

| Com_alter_table           | 2     |

| Com_alter_tablespace      | 0     |

| Com_alter_user            | 0     |

| Com_analyze               | 0     |

| Com_begin                 | 0     |

......

Com_xxx:表示每个xxx语句执行的次数,以下几个统计参数非常重要:

  • Com_select:执行select的次数,一次查询累计加1
  • Com_insert:执行insert操作的次数,批量插入只累加1
  • Com_delete:执行delete操作的次数,
  • Com_update:执行update操作的次数,

以上参数针对所有存储引擎的表操作。

下面的参数是针对InnoDB存储引擎的,算法也稍有不同:

Innodb_rows_read:select查询返回的行数

Innodb_rows_inserted:执行insert操作插入的行数

Innodb_rows_updated:执行update操作更新的行数

Innodb_rows_deleted:执行delete操作删除的行数

通过以上参数的了解,可以判断出当前数据库是以插入更新为主还是以查询操作为主,以及各种类型SQL大致的执行比例是多少。

此外,以下几个参数可以帮助用户了解数据库的基本情况:

Uptime:数据库服务器的工作时间

Connections:试图连接服务器的次数

Slow_queries:慢查询的次数

2 定位执行效率低的SQL语句

方式1:通过慢查询日志定位

方式2:查看当前正在进行的线程

mysql> show processlist;

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

| Id | User        | Host      | db   | Command | Time  | State                                                                       | Info             |

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

|  1 | system user |           | NULL | Connect | 34400 | Waiting for master to send event                                            | NULL             |

|  2 | system user |           | NULL | Connect |  7738 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL             |

|  4 | root        | localhost | NULL | Query   |     0 | init                                                                        | show processlist |

3 通过explain分析低效的SQL语句的执行

通过之前的步骤查询到效率低的SQL语句之后,可以通过explain命令获取MySQL是如何执行select语句的信息。如:

mysql> explain select * from emp1;

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

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

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

|  1 | SIMPLE      | emp1  | ALL  | NULL          | NULL | NULL    | NULL |    4 | NULL  |

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

1 row in set (0.00 sec)

  • select_type——select类型
  • table——输出结果的表
  • type——表示MySQL在表中找到所需行的方式,或者叫访问类型,常见有以下几种:性能由最差到最好。

type=all,即通过全表扫描找到匹配的行。

type=index,索引全扫描,mysql遍历索引才找到匹配的行。

type=range,索引范围扫描,

type=ref,使用非唯一索引扫描,或唯一索引的前缀扫描,返回匹配某个单独值的记录行

type=eq_ref,类似ref,区别在于使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配。

type=const/system,表单中最多有一个匹配行,查询起来非常迅速。如根据主键和唯一索引进行的查询。

type=null,不需要访问表或索引,直接就可以得到结果。

  • possible_keys——表示查询时可能使用的索引
  • key——表示实际使用的索引
  • key_len——使用到索引字段的长度
  • rows——扫描行的数量
  • Extra——执行情况的说明和描述

4 通过show profile分析SQL

mysql> select @@have_profiling;        #查看是否支持

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

| @@have_profiling |

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

| YES              |

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

mysql> set profiling=1;                #开启profiling,默认是关闭

Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from emp1;             #执行一个语句

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

| age1 | deptno | ename | birth      |

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

|  111 |      4 | ccc   | 2011-11-30 |

|  666 |     11 | ddd   | 2014-12-22 |

|  888 |     22 | eee   | 2015-11-30 |

|  333 |      8 | fff   | 2011-04-30 |

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

4 rows in set (0.02 sec)

mysql> show profiles;                  #查看当前SQL语句的查询ID

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

| Query_ID | Duration   | Query                     |

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

|        1 | 0.01696625 | select count(*) from emp1 |

|        2 | 0.02623125 | select * from emp1        |

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

mysql> show profile for query 2;       #查看执行过程中线程的每个状态和消耗时间

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

| Status               | Duration |

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

| starting             | 0.000111 |

| checking permissions | 0.000019 |

| Opening tables       | 0.000046 |

| init                 | 0.000043 |

| System lock          | 0.000031 |

| optimizing           | 0.000016 |

| statistics           | 0.000039 |

| preparing            | 0.000023 |

| executing            | 0.000008 |

| Sending data         | 0.025442 |

| end                  | 0.000020 |

| query end            | 0.000014 |

| closing tables       | 0.000016 |

| freeing items        | 0.000326 |

| cleaning up          | 0.000079 |

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

Sending data表示MySQL线程开始访问数据行并把结果返回给客户端。通常是整个查询中耗时最长的状态

mysql> show profile cpu for query 2;    #查看耗费CPU的时间,Sending data主要耗费在CPU上

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

| Status               | Duration | CPU_user | CPU_system |

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

| starting             | 0.000111 | 0.000000 |   0.000000 |

| checking permissions | 0.000019 | 0.000000 |   0.000000 |

| Opening tables       | 0.000046 | 0.000000 |   0.000000 |

| init                 | 0.000043 | 0.000000 |   0.000000 |

| System lock          | 0.000031 | 0.000000 |   0.000000 |

| optimizing           | 0.000016 | 0.000000 |   0.000000 |

| statistics           | 0.000039 | 0.000000 |   0.000000 |

| preparing            | 0.000023 | 0.000000 |   0.000000 |

| executing            | 0.000008 | 0.000000 |   0.000000 |

| Sending data         | 0.025442 | 0.000000 |   0.001999 |

| end                  | 0.000020 | 0.000000 |   0.000000 |

| query end            | 0.000014 | 0.000000 |   0.000000 |

| closing tables       | 0.000016 | 0.000000 |   0.000000 |

| freeing items        | 0.000326 | 0.000000 |   0.000000 |

| cleaning up          | 0.000079 | 0.000000 |   0.000000 |

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

5 通过trace分析优化器如何选择执行计划

6 确定问题之后,采取相应的措施优化

由前面的步骤确认对表进行全表扫描,导致查询效果不理想,那么对表的某个字段建立索引。具体如下 :

mysql> create index index_ename on emp1(ename);

Query OK, 0 rows affected (0.25 sec)

Records: 0  Duplicates: 0  Warnings: 0

建立索引后,再看下这条语句的执行状态:

mysql> explain select ename from emp1;

建立索引后,可以发现对表扫描的行数大大减少,提高了对表的访问速度。

二 索引问题

索引是数据库优化中最重要也是最常用的手段之一,通过索引可以帮助用户解决大多数SQL性能问题。

1 索引的存储分类:索引是在存储引擎层中实现的

  • B-Tree索引:最常见的索引,大部分引擎支持B树索引。
  • HASH索引:只有Memory引擎支持,使用场景简单
  • Full-text(全文索引):一种特殊索引类型

创建索引方式 1:

mysql> create index index_age1 on emp1(age1);

Query OK, 0 rows affected (0.15 sec)

Records: 0  Duplicates: 0  Warnings: 0

创建索引方式 2:

mysql> alter table zwj.emp1 add index index_ename (ename);

Query OK, 0 rows affected (0.05 sec)

Records: 0  Duplicates: 0  Warnings: 0

查看索引:

mysql> show index from zwj.emp1;

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

| Table | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

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

| emp1  |          1 | index_ename |            1 | ename       | A         |           4 |     NULL | NULL   | YES  | BTREE      |         |               |

| emp1  |          1 | index_age1  |            1 | age1        | A         |           4 |     NULL | NULL   | YES  | BTREE      |         |               |

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

删除索引:

mysql> drop index index_age1 on zwj.emp1;

Query OK, 0 rows affected (0.06 sec)

Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table zwj.emp1 drop index index_ename;

Query OK, 0 rows affected (0.04 sec)

Records: 0  Duplicates: 0  Warnings: 0

另有复合索引:需要咨询开发人员

创建复合索引(将最常用作限制条件的列放在最左边,依次递减):

mysql> create index name_passwd on abc.student(name,passwd);(需要咨询研发部门)

2 查看索引的使用情况:

mysql> show status like ‘handler_read%‘;

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

| Variable_name         | Value |

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

| Handler_read_first    | 4     |

| Handler_read_key      | 5     |

| Handler_read_last     | 0     |

| Handler_read_next     | 0     |

| Handler_read_prev     | 0     |

| Handler_read_rnd      | 0     |

| Handler_read_rnd_next | 56    |

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

7 rows in set (0.00 sec)

Handler_read_key:如果索引正在工作,此值应该很高,这个值代表了一个行被索引值读的次数。如果值过低,表明增加索引得到的性能改善不高,因为索引并不常被使用。

Handler_read_rnd_next:值高意味着查询运行低效,并且应该建立索引补救。这个值的含义是在数据文件中读下一行的请求数。如果进行了大量的扫描,它的值会很高,说明索引不正确或查询没有利用到索引。

时间: 2024-08-04 13:24:11

MySQL之SQL语句优化的相关文章

MySQL常用SQL语句优化

SQL语句写得不严谨或者不适当,没有正确的使用上索引,会带来很严重的性能问题,这时DBA们又要来收拾这些烂滩子了,所以SQL语句的优化,在日常工作中,是占很重要的一部份,当然还有比如OS优化,硬件优化,MySQL Server优化,数据类型优化,应用层优化.我们进行MySQL的一些相关优化进行探讨. 1.优化数据插入: DISABLE KEYS和ENABLE KEYS用来关闭或者打开MyISAM表非唯一索引的更新,当用load命令导入数据的时候,适当的设置可以提高导入的速度.只用于MyISAM存

千万级大数据的Mysql数据库SQL语句优化

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=0 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用

mysql的sql语句优化

对于经常使用mysql的兄弟们,对explain一定不会陌生.当你在一条SELECT语句前放上关键词EXPLAIN,MySQL解释它将如何处理SELECT,提供有关表如何联合和以什么次序的信息.借助于EXPLAIN,你可以知道1)你什么时候必须为表加入索引以得到一个使用索引找到记录的更快的SELECT.2)你也能知道优化器是否以一个最佳次序联结表.为了强制优化器对一个SELECT语句使用一个特定联结次序,增加一个STRAIGHT_JOIN子句.官方的关于explain的文档在http://dev

MySQL的SQL语句优化-group by语句的优化

原文:http://bbs.landingbj.com/t-0-243202-1.html 默认情况下,MySQL排序所有GROUP BY col1, col2, ....,查询的方法如同在查询中指定ORDER BY col1, col2, .... 如果显式包括一个包含相同的列的ORDER BY子句,MySQL可以毫不减速地对它进行优化,尽管仍然进行排序. 如果查询包括GROUP BY但你想要避免排序结果的消耗,你可以指定ORDER BY NULL禁止排序. 例如: INSERT INTO f

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

一.SQL语句优化 1-1.MySQL慢日志 1).慢日志开启方式和存储格式 如何发现有问题的SQL? 使用Mysql慢日志对有效率问题的SQL进行监控 前期准备 mysql> show variables like '%log_queri%'; +-------------------------------+-------+ | Variable_name | Value | +-------------------------------+-------+ | log_queries_no

mysql索引优化和sql语句优化

一.mysql索引分为btree索引和hash索引. btree索引是二叉树结构 先到索引树上找,再去根据索引到数据里边找数据. hash索引是memory引擎,精准查询非常快,如果查范围内(where>8),会比较慢.因为是无序的,无法使用前缀索引. 2.btree索引 建立索引,通常是经常用到做查询条件,做分组,做排序. 独立索引,单个建索引只能用一个索引,通常用联合索引. 如建了一个(a,b,c)的复合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,因为每多一个索引,都会

MySQL数据库sql语句的一些简单优化

1.查询条件的先后顺序 有多个查询条件时,要把效率高能更精确筛选记录的条件放在后边.因为MySQL解析sql语句是从后往前的(不知是否准确). 例: select a.*,b.* from UsrInf a,OrgInf b where LogNam='njnydx9' and b.OrgId=a.blnorg SQL语句从后往前解析,把LogNam='njnydx9'换到后边,避免了更多结果集的连接,提高了执行效率 2.in的效率问题 看网上都说in相当于多个条件的or.实际测试后发现in的执

小贝_mysql sql语句优化过程

sql语句优化 一.SQL优化的一般步骤 (1).通过show status命令了解各种SQL的执行频率. (2).定位执行效率较低的SQL语句-(重点select) (3).通过explain分析低效率的SQL语句的执行情况 (4).确定问题并采取相应的优化措施 (1) 通过showstatus命令了解各种SQL的执行频率 MySQL客户端连接成功后,通过使用show[session|global] status 命令可以提供服务器状态信息.其中的session来表示当前的连接的统计结果,gl

Effective MySQL之SQL语句最优化

推荐本SQL优化的书<Effective MySQL之SQL语句最优化>. 主要讲解:如何去分析SQL的性能.索引的原理.如何创建合适的索引.如何去分析线上系统的性能瓶颈. 另外还介绍了几个辅助工具: mysqldumpslow 来分析慢查询日志: Google开源的mysql-slow-query-log-parser 分析慢查询日志: 应用程序中使用MySQL Proxy来收集SQL语句.QEP.查询执行时间: 开源Maatkit检查数据库中的重复索引: Google的MySQL补丁,引入