Mysql应用sql语句优化的一般步骤详解
《Mysql应用sql语句优化的一般步骤详解》要点: MYSQL实例前言 MYSQL实例本文主要给大家分享了关于sql语句优化的一般步骤,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. MYSQL实例一、通过 show status 命令了解各种 sql 的执行频率 MYSQL实例mysql 客户端连接成功后,通过 MYSQL实例
MYSQL实例
# Com_xxx 表示每个 xxx 语句执行的次数.
mysql> show status like 'Com_%';
MYSQL实例我们通常比较关心的是以下几个统计参数:
MYSQL实例上面这些参数对于所有存储引擎的表操作都会进行累计.下面这几个参数只是针对 innodb 的,累加的算法也略有不同:
MYSQL实例通过以上几个参数,可以很容易地了解当前数据库的应用是以插入更新为主还是以查询操作为主,以及各种类型的 sql 大致的执行比例是多少.对于更新操作的计数,是对执行次数的计数,不论提交还是回滚都会进行累加. MYSQL实例对于事务型的应用,通过 MYSQL实例此外,以下几个参数便于用户了解数据库的基本情况:
MYSQL实例二、定义执行效率较低的 sql 语句 MYSQL实例1. 通过慢查询日志定位那些执行效率较低的 sql 语句,用 MYSQL实例2. 慢查询日志在查询结束以后才记录,所以在应用反映执行效率出现问题的时候慢查询日志并不能定位问题,可以使用 show processlist 命令查看当前 mysql 在进行的线程,包括线程的状态、是否锁表等,可以实时的查看 sql 的执行情况,同时对一些锁表操作进行优化. MYSQL实例三、通过 explain 分析低效 sql 的执行计划 MYSQL实例测试数据库地址:https://downloads.mysql.com/docs/sakila-db.zip(本地下载) MYSQL实例统计某个 email 为租赁电影拷贝所支付的总金额,需要关联客户表 customer 和 付款表 payment,并且对付款金额 amount 字段做求和(sum) 操作,相应的执行计划如下: MYSQL实例
mysql> explain select sum(amount) from customer a,payment b where a.customer_id= b.customer_id and a.email='JANE.BENNETT@sakilacustomer.org'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 599
filtered: 10.00
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: sakila.a.customer_id
rows: 26
filtered: 100.00
Extra: NULL
2 rows in set,1 warning (0.00 sec)
MYSQL实例1. MYSQL实例
mysql> explain select * from film where rating > 9 G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: film
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
filtered: 33.33
Extra: Using where
1 row in set,1 warning (0.01 sec)
MYSQL实例2. MYSQL实例
mysql> explain select title form filmG
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: film
partitions: NULL
type: index
possible_keys: NULL
key: idx_title
key_len: 767
ref: NULL
rows: 1000
filtered: 100.00
Extra: Using index
1 row in set,1 warning (0.00 sec)
MYSQL实例3. MYSQL实例
mysql> explain select * from payment where customer_id >= 300 and customer_id <= 350 G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: payment
partitions: NULL
type: range
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: NULL
rows: 1350
filtered: 100.00
Extra: Using index condition
1 row in set,1 warning (0.07 sec)
MYSQL实例4. MYSQL实例
mysql> explain select * from payment where customer_id = 350 G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: payment
partitions: NULL
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: const
rows: 23
filtered: 100.00
Extra: NULL
1 row in set,1 warning (0.01 sec)
MYSQL实例索引 MYSQL实例
mysql> explain select b.*,a.* from payment a,customer b where a.customer_id = b.customer_id G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 599
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: sakila.b.customer_id
rows: 26
filtered: 100.00
Extra: NULL
2 rows in set,1 warning (0.00 sec)
MYSQL实例5. MYSQL实例
mysql> explain select * from film a,film_text b where a.film_id = b.film_id G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 1000
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 2
ref: sakila.b.film_id
rows: 1
filtered: 100.00
Extra: Using where
2 rows in set,1 warning (0.03 sec)
MYSQL实例6. MYSQL实例
mysql> create table test_const (
-> test_id int,-> test_context varchar(10),-> primary key (`test_id`),-> );
insert into test_const values(1,'hello');
explain select * from ( select * from test_const where test_id=1 ) a G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: test_const
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set,1 warning (0.00 sec)
MYSQL实例7. MYSQL实例
mysql> explain select 1 from dual where 1 G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: NULL
partitions: NULL
type: NULL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
filtered: NULL
Extra: No tables used
1 row in set,1 warning (0.00 sec)
MYSQL实例 类型 type 还有其他值,如
MYSQL实例show warnings 命令 MYSQL实例执行explain 后再执行 MYSQL实例
MySQL [sakila]> explain select sum(amount) from customer a,payment b where 1=1 and a.customer_id = b.customer_id and email = 'JANE.BENNETT@sakilacustomer.org'G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: a
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 599
filtered: 10.00
Extra: Using where
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: b
partitions: NULL
type: ref
possible_keys: idx_fk_customer_id
key: idx_fk_customer_id
key_len: 2
ref: sakila.a.customer_id
rows: 26
filtered: 100.00
Extra: NULL
2 rows in set,1 warning (0.00 sec)
MySQL [sakila]> show warnings;
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select sum(`sakila`.`b`.`amount`) AS `sum(amount)` from `sakila`.`customer` `a` join `sakila`.`payment` `b` where ((`sakila`.`b`.`customer_id` = `sakila`.`a`.`customer_id`) and (`sakila`.`a`.`email` = 'JANE.BENNETT@sakilacustomer.org')) |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
MYSQL实例从 warning 的 message 字段中能够看到优化器自动去除了 1=1 恒成立的条件,也就是说优化器在改写 sql 时会自动去掉恒成立的条件. MYSQL实例explain 命令也有对分区的支持. MYSQL实例
MySQL [sakila]> CREATE TABLE `customer_part` (
-> `customer_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,-> `store_id` tinyint(3) unsigned NOT NULL,-> `first_name` varchar(45) NOT NULL,-> `last_name` varchar(45) NOT NULL,-> `email` varchar(50) DEFAULT NULL,-> `address_id` smallint(5) unsigned NOT NULL,-> `active` tinyint(1) NOT NULL DEFAULT '1',-> `create_date` datetime NOT NULL,-> `last_update` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,-> PRIMARY KEY (`customer_id`)
->
-> ) partition by hash (customer_id) partitions 8;
Query OK,0 rows affected (0.06 sec)
MySQL [sakila]> insert into customer_part select * from customer;
Query OK,599 rows affected (0.06 sec)
Records: 599 Duplicates: 0 Warnings: 0
MySQL [sakila]> explain select * from customer_part where customer_id=130G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: customer_part
partitions: p2
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 2
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set,1 warnings (0.00 sec)
MYSQL实例可以看到 sql 访问的分区是 p2. MYSQL实例四、通过 performance_schema 分析 sql 性能 MYSQL实例旧版本的 mysql 可以使用 profiles 分析 sql 性能,我用的是5.7.18的版本,已经不允许使用 profiles 了,推荐用 MYSQL实例五、通过 trace 分析优化器如何选择执行计划. MYSQL实例mysql5.6 提供了对 sql 的跟踪 trace,可以进一步了解为什么优化器选择 A 执行计划而不是 B 执行计划,帮助我们更好的理解优化器的行为. MYSQL实例使用方式:首先打开 trace,设置格式为 json,设置 trace 最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整显示. MYSQL实例
MySQL [sakila]> set optimizer_trace="enabled=on",end_markers_in_json=on;
Query OK,0 rows affected (0.00 sec)
MySQL [sakila]> set optimizer_trace_max_mem_size=1000000;
Query OK,0 rows affected (0.00 sec)
MYSQL实例接下来执行想做 trace 的 sql 语句,例如像了解租赁表 rental 中库存编号 inventory_id 为 4466 的电影拷贝在出租日期 rental_date 为 2005-05-25 4:00:00 ~ 5:00:00 之间出租的记录: MYSQL实例
mysql> select rental_id from rental where 1=1 and rental_date >= '2005-05-25 04:00:00' and rental_date <= '2005-05-25 05:00:00' and inventory_id=4466;
+-----------+
| rental_id |
+-----------+
| 39 |
+-----------+
1 row in set (0.06 sec)
MySQL [sakila]> select * from information_schema.optimizer_traceG
*************************** 1. row ***************************
QUERY: select * from infomation_schema.optimizer_trace
TRACE: {
"steps": [
] /* steps */
}
MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
INSUFFICIENT_PRIVILEGES: 0
1 row in set (0.00 sec)
MYSQL实例六、 确定问题并采取相应的优化措施 MYSQL实例经过以上步骤,基本就可以确认问题出现的原因.此时可以根据情况采取相应的措施,进行优化以提高执行的效率. MYSQL实例总结 MYSQL实例以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程之家PHP的支持. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |