1. 表碎片
    原因:delete操作时,MySQL并不会把数据文件真实删除,而只是将数据文件的标识位删除,也没有整理数据文件,不会彻底释放表空间。
    计算:show table status like ‘%table_name%’;
mysql> show table status like '%overtime_allowance%';
+---------------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+----------------+
| Name                      | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation          | Checksum | Create_options     | Comment        |
+---------------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+----------------+
| overtime_allowance        | InnoDB |      10 | Compact    |    2 |           8192 |       16384 |               0 |            0 |         0 |            118 | 2019-02-28 13:15:44 | NULL        | NULL       | utf8mb4_general_ci | NULL     | row_format=COMPACT | 加班补贴表     |
| overtime_allowance_detail | InnoDB |      10 | Compact    |    2 |           8192 |       16384 |               0 |            0 |         0 |            101 | 2019-02-28 13:15:44 | NULL        | NULL       | utf8mb4_general_ci | NULL     | row_format=COMPACT | 加班补贴明细表 |
+---------------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+----------------+
2 rows in set (0.34 sec)



mysql> show table status where name='overtime_allowance';
+--------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+------------+
| Name               | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation          | Checksum | Create_options     | Comment    |
+--------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+------------+
| overtime_allowance | InnoDB |      10 | Compact    |    2 |           8192 |       16384 |               0 |            0 |         0 |            118 | 2019-02-28 13:15:44 | NULL        | NULL       | utf8mb4_general_ci | NULL     | row_format=COMPACT | 加班补贴表 |
+--------------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+--------------------+------------+
1 row in set (0.28 sec)

解决:第一种:alter table table_name engine=innodb;作用就是重新整理一遍全表数据,整理之后数据连续性好,全表扫描变快;
第二种:备份元彪数据,然后删掉,重新导入到新表中(备份恢复时可能会用);

  1. 表的统计信息
    就是统计每个库的大小、表的大小、数据和索引的大小等;
统计数据库
中每个库的大小;

mysql> select table_schema,sum(data_length)/1024/1024/1024 as data_length,sum(index_length)/1024/1024/1024 as index_length,sum(data_length+index_length)/1024/1024/1024 as sum_data_length from information_schema.tables where table_schema != 'infomation_schema' and table_schema != 'mysql' group by table_schema;
+--------------------+----------------+----------------+-----------------+
| table_schema       | data_length    | index_length   | sum_data_length |
+--------------------+----------------+----------------+-----------------+
| account_manager    | 0.000564575195 | 0.000106811523 | 0.000671386719  |
| activiti_001       | 0.000381469727 | 0.000442504883 | 0.000823974609  |
| dbandcache         | 0.000015258789 | 0.000000000000 | 0.000015258789  |
| dbandcache2        | 0.000015258789 | 0.000000000000 | 0.000015258789  |
| hyetec-portal      | 0.003005981445 | 0.000701904297 | 0.003707885742  |
| hyetec-urm         | 2.418289184570 | 0.000183105469 | 2.418472290039  |
| information_schema | 0.000152587891 | 0.000000000000 | 0.000152587891  |
| moa                | 0.529266357422 | 0.001052856445 | 0.530319213867  |
| performance_schema | 0.000000000000 | 0.000000000000 | 0.000000000000  |
| sdyy               | 0.000045776367 | 0.000000000000 | 0.000045776367  |
| substation         | 0.004638671875 | 0.000106811523 | 0.004745483398  |
| sys                | 0.000015258789 | 0.000000000000 | 0.000015258789  |
| zhgl               | 0.002090454102 | 0.000000000000 | 0.002090454102  |
+--------------------+----------------+----------------+-----------------+
13 rows in set (1.02 sec)

## 统计库中每个表的大小:


mysql>  select table_name,data_length,index_length,sum(data_length+index_length) as total_size from information_schema.tables where table_schema='sdyy' group by table_name;
+------------+-------------+--------------+------------+
| table_name | data_length | index_length | total_size |
+------------+-------------+--------------+------------+
| call_log   |       16384 |            0 | 16384      |
| sys_log    |       16384 |            0 | 16384      |
| t_user     |       16384 |            0 | 16384      |
+------------+-------------+--------------+------------+
3 rows in set (0.12 sec)

统计所有数据库大小
mysql> select sum(data_length+index_length)/1024/1024/1024 from information_schema.tables;
+----------------------------------------------+
| sum(data_length+index_length)/1024/1024/1024 |
+----------------------------------------------+
| 2.963734141551                               |
+----------------------------------------------+
1 row in set (1.26 sec)
  1. 统计信息的收集方法:
  2. 常用命令:
--查看表结构
desc table_name;
--查看执行计划:
explain select * from table_name ;

--分析下:先看第五列type,如果为ALL,代表全表扫描,后边的其他数据就可以不用看了;非ALLL下,再看key列的数据;如果是NNULL表示没有使用索引;再看rows,查看需要查询的行数;再看extra;观察是否使用了using filesort或者Using temporary;
mysql> explain select * from year_vocation ;
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table         | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | year_vocation | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL  |
+----+-------------+---------------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set (0.15 sec)
--

延申下sql如何优化

  1. 先看表的数据类型是否设计的合理,是否遵循选取数据类型越简单越小原则;
  2. 表中的碎片是否整理;
  3. 表的统计信息是否收集,只有统计信息收集准确,执行计划才能帮助我们优化sql;
  4. 查看执行计划:检查索引的使用情况;如果没有使用索引,考虑创建索引;如果有索引,考虑索引是否正确;
  5. 在创建索引之前,还要查看索引的选择性,判断该字段是否适合创建索引。这里的索引选择性指的是不重复的索引值(也成为基数)和数据表的记录总数的比例;这个比例值越高,则查询效率越高;主键索引和唯一索引的选择性为1
    效率最高;
  6. 创建索引后,再次查看执行计划,对比两次结果,看索引是否起到作用。