您的位置:首页 > 数据库 > MySQL

MySQL 优化系列 --3.SQL语句优化

2016-12-26 15:57 141 查看
3.1 SQL语句的一般优化步骤

session :(默认的)表示当前连接
global:     表示自数据库启动至今.
-1. show    status ;                             //用于了解SQL语句的执行频率,重点跟踪以com开头的命令.
-2. show    status   like  "com_insert %"        //显示执行插入语句的次数.(批量操作只算 1 条执行语句).
-3. show    status   like   "com_select%"        //显示执行查询语句的次数.
-4  show    status   like   "com_update%"        //显示执行更新语句的次数
-5  show    status   like   "com_delete%"        //显示执行删除语句的次数.


只针对inndb存储引擎的

-1. show     status   like     "innodb_rows_read";        //显示执行查询语句的次数.
-2. show     status   like     "innodb_rows_inserted";    //显示执行插入语句的次数.
-3. show     status   like     "innodb_rows_updated"      //显示执行更新语句的次数.
-4. show     status   like     "innodb_rows_deleted"      //显示执行删除语句的次数.
-5. show     status   like     "%connections%";           //显示 MySQL的数量;
-6. show     status   like     "%uptime%"                 //显示服务器工作的时间(以秒为单位)
-7. show     status   like     "%slow_queries%"           //显示慢查询的次数.
-8. show     variable   like  "%quer%";                   //显示慢查询是否被开启.
-8:  //显示: log_slow_queries    off                      //慢查询日志没有开启
-9.  show    variable   like    "%connection%"            //显示MySQL服务器的连接数.
-9.  //显示:  max_connections        100                  //最大连接数
10.  show     status   like"%conn%";                      //显示MySQL服务器的连接数.
10. //显示:   Connection               3                  //试图连接到(不管是否成功)MySQL服务器的连接数
10. //显示:   Max_used_connections     3                  //服务器启动后已经同时使用的连接的最大数量
10. //显示:   Threads_connected        3                  //当前的连接数
开启慢查询日志:  (    http://www.cnblogs.com/gzgccsu/archive/2013/01/23/2873598.html     这里有讲开启慢查询日志 )
-1. Linux下
找到mysql的配置文件my.ini, 在mysqld下方加入慢查询的配置语句(注意:一定要在[mysqld]下的下方加入)
log-slow-queries = /var/lib/mysql/mysql-slow.log
long_query_time = 10
-2. Windows下
log-slow-queries = C:/Program Files/MySQL/MySQL Server 5.5/log/mysql-slow.log"    // windows下一定要写绝对路径.
long_query_time = 10                                                              // 最长执行时间,可根据实际情况更改.
慢查询:默认是关闭的. 开启慢查询后,一条语句执行时间超过10秒就会被记录.

3.1.2 定位执行效率低的语句的步骤;

-1. 查慢查询日志.
-2. 查异常语句影响行数.
-3. 检查是否使用索引或者索引是否被执行.
-4. desc ... 语句执行后检查是否优化.(主要是围绕索引优化)
desc   select   *   from   t1   where   id=1   \G   // 注意不加 ; 号
mysql> desc select * from t1 where id=1 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
Extra:
1 row in set (0.00 sec)
-1. rows           1            //  影响行数,扫描行的数量
-2. select_type    SIMPLE       //  simple 表示不使用表连接或子查询,  primary 主查询(外层查询),   union(union中的第二个查询),
subqurty子查询的第一个select.
-3. table          t1           //  输出结果集的表
-4. possible_keys: PRIMARY      //  可能用到的suoyin
-5.  key:          PRIMARY      //  实际使用的索引
-6.  type:         const        //  表的连接类型, system (表仅一行),  const(只一行匹配),    eq_ref(对于前面的每一行使用主键和唯一索引)
ref(没有使用主键和唯一索引),      range(范围查询),      index_merge(索引合并优化),
unique_subquery(主键子查询),      index_subquery(非主键子查询)
index(通过查询索引得到数据),      all(通过全表扫描得到数据.应该避免全表扫描.)
//  注意:  一般问题多在order by .. group by.. Where.. 等条件语句后没有加索引或索引失效引起的查询慢.
-7.  ref:                       //  推荐使用的索引类型
-8.  Extra:Using where; Using index      // 使用过where ,  使用过索引


3.2  索引问题

3.2.1 索引的存储分类

-1. myisam存储引擎的表的数据和索引是自动分来存储的,各自是独立的一个文件.
-2. innodb存储引擎的表的数据和索引是存储在同一个表的空间里面,但是可以有多个文件组成.
-3. MySQL暂时不支持函数索引.
// 注意: 索引一般加在条件语句后如where...  having...  group by...  order  by... 或者频繁使用的语句.


3.2.2 使用索引

-1 如何使用索引

-1.1. 对于创建的多列索引,只要查询的条件中用到最左边的列,索引一般就会被使用.
show index  from t1                               //查询t1表的索引
drop  index  inx_name  on t1;                     //删除t1表的名为inx_name的索引.
select   * from  t1  where  name="user0";         //查询name是user0的列
create index  inx_sum  on t1(name,salary);        //给name列和salary列添加联合索引
desc  select  *  from   t1 where  name="user0")  \G   //显示 索引被使用, rows只查了1行. 所以只要查询的条件中用到最左边的列,索引一般就会被使用.
desc  select  *  from   t1 where  salary=101 \G       //显示没有使用索引.rows查询了10行. 查询联合索引的右侧的列,索引没有被使用.


-1.2. 使用 like 查询 如果%不是第一个字符,可以使用索引,否则索引失效.

drop     index   inx_sum    on   t1 ;                              //删除t1表的名字是inx_sum的索引
create   index   inx_name   on   t1(name) ;                        //给t1表name列创建名为inx_name的索引.
desc     select  *   from   t1   where  name  like  "%ser%"  \G    //显示 rows查询了所有列.  索引失效.
desc     select  *   from   t1   where  name  like  "user5%" \G    //显示 rows查询了2行,索引可以用.


-1.3. 列名是索引,使用column_name   is   null 将使用索引.

-2 存在索引,但不使用索引的情况

-2.1.  如果SQL计算使用索引比全表扫描时间长,将放弃使用索引.
-2.2.  用or分割开的语句,如果or左侧使用索引,右侧没有使用索引,那么将都不使用索引.
-2.3.  如果表使用了联合索引(2个列一起被创建为索引) 只有 create index  inx_sum  on t1(name,salary); 的name列可以使用索引.salary列将不使用索引.
-2.4   like 是以%开头的,将不使用索引. 如 select * from t1  where  name like" user5%" \G  //将使用索引.
-2.5   如果列类型是字符串,查询时候使用了 int型.也将不会使用索引
desc   select  * from  t2    where   name = 1  \G        //将不会使用索引


show  atatus   like  "handler_read%";
// 显示:   handler_read_key值很高,说明索引实用正常.
// 显示:   handler_read_rnd_next 值涵高, 就说明需要检查索引是否存在或者有效.


3.3 实用的表优化

3.3.1  定期分析表和检查表

analyze table  sales;        //用于分析和存储表的关键字分布,
check   table  table_name    // 用于检查表是否正常可用.


3.3.3 定期表优化

如果有频繁删除表或者修改表字段长度.需要定期做优化.合并空间碎片.
optimize  table  table_name  //优化表空间,提取碎片和空洞.  注意只针对myisam, bdb, innodb表引擎有效.


3.4 常用SQL优化

3.4.1 大批量导入导出数据

myisam引擎使用load命令时候可以配合使用:
alter  table  t1  disable  keys;  //关闭使用t1表的索引. 在myisam引擎下会提高导出速度.
alter  table  t1  enable   keys;  //恢复使用t1表的索引.
注意: 唯一索引不建议关闭.
-1. innodb引擎表的主键是顺序保存的,将导出数据的主键,顺序排列用可以提高导入数据的效率. (linux下的命令语句)
load    data   infile"/test.txt"  into  t1(name);    //给t1表的name列快速导入数据.
select  name   from  t1  into  outfile"/test.txt";   //导出t1表的name列数据快速导出到test.txt文件中.(适合新手,大神,请收下膝盖)
-2. 关闭唯一性校检可以提高效率.
在导入数据前先执行 set unique_checks=0;   //关闭唯一性校检.   导入数据结束后在恢复唯一性校检. set  unique_checks=1;
--- 如果确定关闭唯一索引不会引起问题, 关闭唯一索引在导入数据也会提高效率.
-3. 关闭自动提交可以提高导入速度.
在导入数据前先关闭自动提交,也可以提高导入速度. set autcommit=0; //关闭自动提交事务.    set  autocomit=1; //打开自动提交.


3.4.2 优化insert 语句

insert  into  t1(name) values ("user1"), ("user2"), ("user3");    //一次插入多值,减少表连接次数.也可以提高效率.


3.4.3 优化group by 语句

分组语句默认带升序排序.可以使用  order by null  来禁止其排序来提高效率.
select * from  t1 where group by name  order by null;


3.4.5 优化嵌套排序

嵌套查询效率没有表连接效率高.  建议使用表连接来代替嵌套查询.
当使用嵌套查询时:  如果内外侧查询都使用了索引, 就只有内侧查询索引有效. 外层查询索引没用.
select  *     from  t1      where  id  in(select  id  from  t2);  //外层select查询索引没有用.只有内层查询索引有效.
等价于
select  t1.*  from  t1, t2  where  t1.id = t2.id;                 // 表连接不会有索引失效问题 (如果索引创建正确的话)


 

     

     
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: