一、SQL执行效率分析

  1.通过 show status和应用特点了解各种 SQL的执行频率(次要了解)

  通过 SHOW STATUS 可以提供服务器状态信息,也可以使用 mysqladmin extende d-status 命令获得。 SHOW STATUS 可以根据需要显示 session 级别的统计结果和 global级别的统计结果。

       如显示当前session: SHOW STATUS like "Com_%"; 全局级别:show global status;
       以下几个参数对 Myisam 和 Innodb 存储引擎都计数:

1. Com_select 执行 select 操作的次数,一次查询只累加 1 ;

2. Com_insert 执行 insert 操作的次数,对于批量插入的 insert 操作,只累加一次 ;

3. Com_update 执行 update 操作的次数;

4. Com_delete 执行 delete 操作的次数;

        以下几个参数是针对 Innodb 存储引擎计数的,累加的算法也略有不同:

1. Innodb_rows_read select 查询返回的行数;

2. Innodb_rows_inserted 执行 Insert 操作插入的行数;

3. Innodb_rows_updated 执行 update 操作更新的行数;

4. Innodb_rows_deleted 执行 delete 操作删除的行数;

       通过以上几个参数,可以很容易的了解当前数据库的应用是以插入更新为主还 是以查询操作为主,以及各种类型的 SQL大致的执行比例是多少。对于更新操作的计 数,是对执行次数的计数,不论提交还是回滚都会累加。
      对于事务型的应用,通过 Com_commit 和 Com_rollback 可以了解事务提交和回 滚的情况,对于回滚操作非常频繁的数据库,可能意味着应用编写存在问题。此外,以下几个参数便于我们了解数据库的基本情况:

1. Connections 试图连接 Mysql 服务器的次数
2. Uptime 服务器工作时间
3. Slow_queries 慢查询的次数

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

可以通过以下两种方式定位执行效率较低的 SQL 语句:
     1. 可以通过慢查询日志定位那些执行效率较低的 sql 语句,用 --log-slow-queries[=file_name] 选项启动时, mysqld 写一个包含所有执行时间超过long_query_time 秒的 SQL 语句的日志文件。可以链接到管理维护中的相关章节。
     2. 使用 show processlist查看当前MYSQL的线程, 命令慢查询日志在查询结束以后才纪录,所以在应用反映执行效率出现问题的时候查 询慢查询日志并不能定位问题,可以使用 show processlist 命令查看当前 MySQL 在进行的线程,包括线程的状态,是否锁表等等,可以实时的查看 SQL 执行情况, 同时对一些锁表操作进行优化。

3. 通过EXPLAIN 分析低效 SQL的执行计划:

       通过以上步骤查询到效率低的 SQL 后,我们可以通过 explain 或者 desc 获取MySQL 如何执行 SELECT 语句的信息,包括 select 语句执行过程表如何连接和连接 的次序。

二、mysql索引

1.索引

    索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(), MIN()和ORDERBY这些命令的时候,性能提高更为明显.

    那该对哪些字段建立索引呢?一般说来,索引应建立在那些将用于JOIN, WHERE判断和ORDER BY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说,出现大量重复值是很有可能的情况,例如customerinfo中的“province”..字段,在这样的字段上建立索引将不会有什么帮助;相反,还有可能降低数据库的性能。我们在创建表的时候可以同时创建合适的索引,也可以使用ALTER TABLE或CREATE INDEX在以后创建索引

1). 普通索引

        普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column = …)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能,就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。

2). 唯一索引

        普通索引允许被索引的数据列包含重复的值。比如说,因为人有可能同名,所以同一个姓名在同一个”员工个人资料”数据表里可能出现两次或更多次。

如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好处:一是简化了MySQL对这个索引的管理工作,这个索引也因此而变得更有效率;二是MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。

3). 主索引

        在前面已经反复多次强调过:必须为主键字段创建一个索引,这个索引就是所谓的”主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。

 4). 外键索引

         如果为某个外键字段定义了一个外键约束条件,MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。

复合索引

        索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引。这种索引的特点是MySQL可以有选择地使用一个这样的索引。如果查询操作只需要用到columnA数据列上的一个索引,就可以使用复合索引INDEX(columnA, columnB)。不过,这种用法仅适用于在复合索引中排列在前的数据列组合。比如说,INDEX(A, B, C)可以当做A或(A, B)的索引来使用,但不能当做B、C或(B, C)的索引来使用。

2.索引的创建与删除

①使用CREATE INDEX 语句

语法格式:

CREATE <索引名> ON <表名> (<列名> [<长度>] [ ASC | DESC])

示例:

CREATE INDEX可对表增加普通索引或UNIQUE索引。

(1)CREATE INDEX index_name ON table_name (column_list)
 (2)CREATE UNIQUE INDEX index_name ON table_name (column_list)

table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名不可选。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引。

②使用ALTER TABLE 语句

ALTER TABLE用来创建普通索引、UNIQUE索引或PRIMARY KEY索引。

(1.)ALTER TABLE table_name ADD INDEX index_name (column_list)
 (2.)ALTER TABLE table_name ADD UNIQUE (column_list)
 (3.)ALTER TABLE table_name ADD PRIMARY KEY (column_list)

其中table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。另外,ALTER TABLE允许在单个语句中更改多个表,因此可以在同时创建多个索引。

③ 使用 CREATE TABLE 语句

mysql> CREATE TABLE tb_stu_info
    -> (
    -> id INT NOT NULL,
    -> name CHAR(45) DEFAULT NULL,
    -> dept_id INT DEFAULT NULL,
    -> age INT DEFAULT NULL,
    -> height INT DEFAULT NULL,
    -> KEY `height` (`height`)
    -> );

④删除索引

可利用ALTER TABLE或DROP INDEX语句来删除索引。类似于CREATE INDEX语句,DROP INDEX可以在ALTER TABLE内部作为一条语句处理,语法如下。

DROP INDEX index_name ON talbe_name
ALTER TABLE table_name DROP INDEX index_name
ALTER TABLE table_name DROP PRIMARY KEY

其中,前两条语句是等价的,删除掉table_name中的索引index_name。

第3条语句只在删除PRIMARY KEY索引时使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。

如果从表中删除了某列,则索引会受到影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索引中删除。如果删除组成索引的所有列,则整个索引将被删除。

3.索引建立原则

1、字段值的重复程度,如图:

MYSQL表数据日增行数 mysql增长率_mysql

身份证号码由于基本上不可能重复,因此选择性非常好,而人的名字重复性较低,选择性也不错, 性别选择性较差,重复度非常高

2、选择性很差的字段通常不适合创建索引,但也有例外

如:男女比例相仿的表中,性别不适合创建单列索引,如果走索引不如走全表扫描,因为走索引的I/O开销更大

但如果男女比例极度不平衡,要查询的又是少数方,如:理工学校、IT公司等可以考虑使用索引。

3、联合索引中选择性好的字段应该排在前面

select * from tab_a where gender=? and name=? idx_name_gender(name,gender) ->正确

4、联合索引可以为单列、复列查询提供帮助

idx_smp(a,b,c) where a=?; ->正确 where a=? and b=?; ->正确 where a=? and c=?; ->正确 (注:需要MySQL5.6版本以上;在5.5及以前版本,可以对a字段进行索引扫描,但c字段不行 ) where a=? and b=? and c=? ->正确

5、合理创建联合索引,避免冗余

(a),(a,b),(a,b,c) ->不可取 (a,b,c) ->正确,可以覆盖前两个

4.索引失效的情况

下列情况下, Mysql 不会使用已有的索引:

1、索引列进行数据运算或者函数运算

eg: where id+1=10;        ->错误,无法利用到索引
       where id=(10-1)        ->正确
       where year(id) < 2016        ->错误,无法利用到索引
       where col < '2016-01-01'    ->正确.

2、如果 like 是以%开始;

      like '%ttt%'   ->错误,无法利用到索引

      like "ttt%"     ->正确

3、where条件使用NOT,<>,!= 通常也无法使用到索引

4、如果创建复合索引,如果条件中使用的列不是索引列的第一部分;(不是前缀索引)

5、使用or分割的条件,如果or前的条件中的列有索引,后面的列中没有索引,那么涉及到的索引都不会使用。

6、where条件使用in , not in 

7、对 where 后边条件为字符串的一定要加引号,字符串如果为数字 mysql 会自动转 为字符串,但是不使用索引。

5.查看索引使用情况

MySQL中自带命令行工具 explain 来查看一个sql语句是否了索引

使用方式:

explain select * from tb_test;

关注的项:

1、type : 查询access的方式,表的连接类型

index | 索引

full | 全表扫描

ref | 参照查询,也就是等值查询

range | 范围查询

2、key : 本次查询最终选择使用哪个索引,NULL为未使用索引

3、key_len : 选择的索引使用的前缀长度或者整个长度

4、rows : 查询逻辑扫描过的记录行数

5、extra : 额外信息,主要是指fetch data的具体方式

6.常见索引原则

1. 选择唯一性索引
    唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 
2. 为经常需要排序、分组和联合操作的字段建立索引 :

3 .为常作为查询条件的字段建立 索引 。 

4 .限制索引的数目:
    越多的索引,会使更新表变得很浪费时间。 
    尽量使用数据量少的索引

5. 如果索引的值很长,那么查询的速度会受到影响。 
    尽量使用前缀来索引

6. 如果索引字段的值很长,最好使用值的前缀来索引。  

7. 删除不再使用或者很少使用的索引

8. 最左前缀匹配原则,非常重要的原则。

9. 尽量选择区分度高的列作为索引
    区分度的公式是表示字段不重复的比例 

10.索引列不能参与计算,保持列“干净”:带函数的查询不参与索引。

11.尽量的扩展索引,不要新建索引。 

三、其他一些注意优化