[未完成待續….]
使用Mysql官方網站提供的數據庫進行練習
參考地址:
https://dev.mysql.com/doc/index-other.html
https://dev.mysql.com/doc/sakila/en/sakila-usage.html
. MySql開啓慢查詢日誌分析
- 查找慢查詢日誌變量。
show variables like 'slow_query_log';
- 設置慢查詢分析文件的位置。
set global show_query_log_file ='/home/mysql/sql_log/mysql-slow.log';
- 設置是否記錄未開啓索引的查詢。
set global log_queries_not_using_indexes=on;
- 設置記錄超過制定時長的語句。
set global long_query_time = 1;
. 實際例子
1. Count()和Max()的優化方法。
.優化前
explain select max(payment_date) from payment;
id: 1 select_type: SIMPLE
table: payment
type: ALL possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 16086
Extra: NULL
.優化後
創建一個索引
create index idx_paydate on payment(payment_date);
id: 1
select_type: SIMPLE
table: NULL
type: NULL possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
Extra: Select tables optimized away
2. 子查詢優化
通常情況下,需要將子查詢轉換成join查詢,但在優化的時候要注意關聯鍵是否爲一對多關係,需要注意重複數據。
(查詢sandra出演的所有影片)
explain select title,release_year,LENGTH
from film
where film_id in(
select film_id from film_actor where actor_id in(
select actor_id from actor where first_name='sandra'));
可以將上面的例子換成join
方式連接即可。
3.Group By語句優化
查詢每一個演員演出的電影數量
優化前
explain SELECT actor.first_name,actor.last_name,count(*)
FROM sakila.film_actor
INNER JOIN sakila.actor USING(actor_id)
GROUP BY film_actor.actor_id;
explain結果,可以看到第一條記錄Extra信息,用到了臨時表跟文件排序,意味着需要優化。
***************** 1. row *****************
id: 1 select_type: SIMPLE
table: actor
type: ALL possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 200
Extra: Using temporary; Using filesort
***************** 2. row *****************
id: 1 select_type: SIMPLE
table: film_actor
type: ref possible_keys: PRIMARY,idx_fk_film_id
key: PRIMARY
key_len: 2
ref: sakila.actor.actor_id
rows: 1
Extra: Using index 2 rows in set (0.00 sec)
優化後(將group by語句放到子查詢裏面)
explain SELECT actor.first_name,actor.last_name,c.cnt
FROM sakila.actor INNER JOIN(
SELECT actor_id,COUNT(*) AS cnt from sakila.film_actor
GROUP BY actor_id
)AS c USING(actor_id);
explain結果
***************** 1. row *****************
id: 1 select_type: PRIMARY
table: actor
type: ALL possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 200
Extra: NULL
***************** 2. row *****************
id: 1 select_type: PRIMARY
table:
type: ref possible_keys:
key:
key_len: 2
ref: sakila.actor.actor_id
rows: 27
Extra: NULL
***************** 3. row *****************
id: 2 select_type: DERIVED
table: fiLm_actor
type: index possible_keys: PRIMARY,idx_fk_film_id
key: PRIMARY
key_len: 4
ref: NULL
rows: 5462
Extra: Using index 3 rows in set (0.00 sec)
4. 優化Limit查詢
SELECT film_id,description FROM sakila.film ORDER BY title LIMIT 50,5;
出現Using filesort 意味着sql需要優化。
***************** 1. row *****************
id: 1 select_type: SIMPLE
table: film
type: ALL possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using filesort 1 row in set (0.00 sec)
優化步驟
1.使用有索引的列或者主鍵進行Order by 操作
SELECT film_id,description FROM sakila.film ORDER BY film_id LIMIT 50,5;
***************** 1. row *****************
id: 1 select_type: SIMPLE
table: film
type: index possible_keys: NULL
key: PRIMARY
key_len: 2
ref: NULL
rows: 55
Extra: NULL 1 row in set (0.00 sec)
2.記錄上一次返回的主鍵,在下一次查詢時使用主鍵過濾(如果主鍵不連續,可以新建一個自增長的id)
SELECT film_id,description FROM sakila.film WHERE film_id>55 and film_id<=60 ORDER BY film_id LIMIT 1,5;
***************** 1. row *****************
id: 1 select_type: SIMPLE
table: film
type: range possible_keys: PRIMARY
key: PRIMARY
key_len: 2
ref: NULL
rows: 5
Extra: Using where 1 row in set (0.00 sec)