Mysql数据库(十)MySQL性能优化
一、优化概述
为了提高MySQL数据库的性能,不要进行一系列的优化措施。如果MySQL数据库需要进行大量的查询操作,那么就需要对查询语句进行优化。对于耗费时间的查询语句进行优化,可以提高整体地查询速度。如果连接MySQL数据库的用户很多,那么就需要对MySQL服务器进行优化,否则,大量的用户同时连接MySQL数据库,可能会造成数据库系统崩溃。
1.分析MySQL数据库的性能
mysql> show status like 'Connections'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Connections | 13 | +---------------+-------+ 1 row in set (0.81 sec)
还可以查询的几个参数:Uptime(上线时间)、Slow_queries(慢查询)、Com_select(查询操作)、Com_insert(插入操作)、Com_delete(删除操作)。
2.通过profile工具分析语句消耗性能
(1)首先查看profile工具是否开启
mysql> show variables like '%pro%'; +------------------------------------------+-------+ | Variable_name | Value | +------------------------------------------+-------+ | check_proxy_users | OFF | | have_profiling | YES | | mysql_native_password_proxy_users | OFF | | performance_schema_max_program_instances | -1 | | profiling | OFF | | profiling_history_size | 15 | | protocol_version | 10 | | proxy_user | | | sha256_password_proxy_users | OFF | | slave_compressed_protocol | OFF | | stored_program_cache | 256 | +------------------------------------------+-------+ 11 rows in set, 1 warning (0.00 sec)
mysql> set profiling=1; Query OK, 0 rows affected, 1 warning (0.00 sec)
(2)然后使用profile工具
mysql> use db_library; Database changed mysql> select * from tb_bookinfo; +----------+-----------+--------+-----------+------+-------+------+----------+------------+------+----+ | barcode | bookname | typeid | author | ISBN | price | page | bookcase | inTime | del | id | +----------+-----------+--------+-----------+------+-------+------+----------+------------+------+----+ | 17120108 | Lian | 1 | QiaoJiang | 116 | 50.00 | 351 | 2 | 2018-04-18 | 0 | 2 | | 17120109 | Tian King | 2 | TianJiang | 117 | 51.10 | 352 | 3 | 2018-04-19 | 0 | 3 | | 17120110 | ShenOba | 4 | ShenJiang | 118 | 52.15 | 300 | 4 | 2018-04-20 | 0 | 4 | +----------+-----------+--------+-----------+------+-------+------+----------+------------+------+----+ 3 rows in set (0.01 sec) mysql> show profiles; +----------+------------+---------------------------+ | Query_ID | Duration | Query | +----------+------------+---------------------------+ | 1 | 0.00019475 | SELECT DATABASE() | | 2 | 0.01017075 | select * from tb_bookinfo | +----------+------------+---------------------------+ 2 rows in set, 1 warning (0.00 sec)
二、优化查询
1.分析查询语句
(1)使用EXPLAIN SELECT语句
mysql> EXPLAIN SELECT * FROM tb_bookinfo; +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ | 1 | SIMPLE | tb_bookinfo | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
(2)使用DESCRIBE SELECT语句
mysql> DESCRIBE SELECT * FROM tb_bookinfo; +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ | 1 | SIMPLE | tb_bookinfo | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
2.索引对查询速度的影响
(1)首先分析未使用索引时的查询情况(从rows字段下的3可以看出,数据库存在的3条数据都被查询了一遍)
mysql> DESCRIBE SELECT * FROM tb_bookinfo WHERE author='ShenJiang'; +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tb_bookinfo | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec)
(2)使用索引后的查询情况(只查询了1行数据)
mysql> CREATE INDEX index_name ON tb_bookinfo(author); Query OK, 0 rows affected (0.10 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> DESCRIBE SELECT * FROM tb_bookinfo WHERE author='ShenJiang'; +----+-------------+-------------+------------+------+---------------+------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | tb_bookinfo | NULL | ref | index_name | index_name | 33 | const | 1 | 100.00 | NULL | +----+-------------+-------------+------------+------+---------------+------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec)
3.使用索引查询
(1)应用LIKE关键字优化索引查询(%放在第一个字符,索引不会被使用)
mysql> DESCRIBE SELECT * FROM tb_bookinfo WHERE author LIKE '%enJiang'; +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tb_bookinfo | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> DESCRIBE SELECT * FROM tb_bookinfo WHERE author LIKE 'She%'; +----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | tb_bookinfo | NULL | range | index_name | index_name | 33 | NULL | 1 | 100.00 | Using index condition | +----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------+ 1 row in set, 1 warning (0.00 sec)
(2)查询语句中使用多列索引(多列索引是指在表的多个字段上创建一个索引。只有查询条件中使用了这些字段中的第一个字段时,索引才会被正常使用)
mysql> CREATE INDEX index_book_info ON tb_bookinfo(bookname,price); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0
必须使用第一字段bookname时,索引才可以被正常使用。
(3)查询语句中使用OR关键字
mysql> DESCRIBE SELECT * FROM tb_bookinfo WHERE author='ShenJiang' OR price=51.10; +----+-------------+-------------+------------+------+------------------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+------------------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | tb_bookinfo | NULL | ALL | index_name,index_price | NULL | NULL | NULL | 3 | 55.56 | Using where | +----+-------------+-------------+------------+------+------------------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.01 sec)
三、优化数据库结构
1.将字段很多的表分解成多个表(将字段特别多且有些字段的使用频率很低的表,分解成多个表。在查询时可以联表查询)
SELECT * FROM tb_student,tb_student_extra WHERE tb_student.id=tb_student_extra.id
2.增加中间表
mysql> desc tb_bookinfo; +----------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+-------+ | barcode | varchar(30) | YES | | NULL | | | bookname | varchar(70) | YES | MUL | NULL | | | typeid | int(10) unsigned | YES | | NULL | | | author | varchar(30) | YES | MUL | NULL | | | ISBN | varchar(20) | YES | | NULL | | | price | float(8,2) | YES | MUL | NULL | | | page | int(10) unsigned | YES | | NULL | | | bookcase | int(10) unsigned | YES | | NULL | | | inTime | date | YES | | NULL | | | del | tinyint(1) | YES | | 0 | | | id | int(11) | NO | PRI | NULL | | +----------+------------------+------+-----+---------+-------+ 11 rows in set (0.00 sec) mysql> desc tb_borrow; +------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | readerid | int(10) unsigned | YES | | NULL | | | bookid | int(10) | YES | | NULL | | | borrowTime | date | YES | | NULL | | | backTime | date | YES | | NULL | | | operator | varchar(30) | YES | | NULL | | | ifback | tinyint(1) | YES | | 0 | | +------------+------------------+------+-----+---------+----------------+ 7 rows in set (0.01 sec) mysql> CREATE TABLE temp_bookinfo(id INT NOT NULL, -> name varchar(45) NOT NULL, -> borrowTime date); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO temp_bookinfo SELECT a.id,a.bookname,b.borrowTime -> FROM tb_bookinfo a,tb_borrow b WHERE a.typeid=b.id; Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql> select * from temp_bookinfo; +----+-----------+------------+ | id | name | borrowTime | +----+-----------+------------+ | 2 | Lian | 2018-04-19 | | 3 | Tian King | 2018-04-16 | +----+-----------+------------+ 2 rows in set (0.00 sec)
3.优化插入记录的速度
插入记录时,索引、唯一性校验都会影响到插入记录的速度。而且,一次插入多条记录和多次插入记录所耗费的时间是不一样的。
(1)禁用索引
ALTER TABLE tablename DISABLE KEYS; ALTER TABLE tablename ENABLE KEYS;
(2)禁用唯一性检查
SET UNIQUE_CHECK=0; SET UNIQUE_CHECK=1;
(3)优化INSERT语句
一个INSERT语句插入多条记录比一个INSERT语句只插入一个记录,多个INSERT语句插入多条记录减少了与数据库之间的连接等操作,其速度比第二种方式要快。
4.分析表、检查表和优化表
(1)分析表(表名称、执行的操作、信息类型(状态、警告、错误或信息中的一个)、显示信息)
mysql> ANALYZE TABLE tb_bookinfo; +------------------------+---------+----------+----------+ | Table | Op | Msg_type | Msg_text | +------------------------+---------+----------+----------+ | db_library.tb_bookinfo | analyze | status | OK | +------------------------+---------+----------+----------+ 1 row in set (0.01 sec)
(2)检查表(检查表是否存在错误)
mysql> CHECK TABLE tb_bookinfo; +------------------------+-------+----------+----------+ | Table | Op | Msg_type | Msg_text | +------------------------+-------+----------+----------+ | db_library.tb_bookinfo | check | status | OK | +------------------------+-------+----------+----------+ 1 row in set (0.00 sec)
(3)优化表(只能优化表中的varchar、blog或text类型的字段。可以消除删除和更新造成的磁盘碎片)
mysql> OPTIMIZE TABLE tb_bookinfo; +------------------------+----------+----------+-------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +------------------------+----------+----------+-------------------------------------------------------------------+ | db_library.tb_bookinfo | optimize | note | Table does not support optimize, doing recreate + analyze instead | | db_library.tb_bookinfo | optimize | status | OK | +------------------------+----------+----------+-------------------------------------------------------------------+ 2 rows in set (0.08 sec)
四、优化多表查询(子查询的查询时间比连接查询的时间要少很多)
SELECT s.name FROM tb_student2 s,tb_classes c WHERE s.classid=c,id AND c.name='一年三班'; SELECT name FROM tb_student2 WHERE classid=(SELECT id FROM tb_classes WHERE name='一年三班');
五、优化表设计
(1)在设计数据表是应优先考虑使用特定字段长度,后考虑使用变长字段。同时将字段长度设置成其可能应用的最大范围可以充分地优化查询效率
(2)使用OPTIMIZE TABLE命令处理用户经常操作的表,用来减少磁盘碎片的增加。
(3)检查用户已经建立的数据表,确认这些表是否有可能整合成一个表,如果没有必要整合,可以使用连接查询。