Mysql性能優化實踐

[未完成待續….]
使用Mysql官方網站提供的數據庫進行練習
參考地址:
https://dev.mysql.com/doc/index-other.html
https://dev.mysql.com/doc/sakila/en/sakila-usage.html

. MySql開啓慢查詢日誌分析

  1. 查找慢查詢日誌變量。
    show variables like 'slow_query_log';
  2. 設置慢查詢分析文件的位置。
    set global show_query_log_file ='/home/mysql/sql_log/mysql-slow.log';
  3. 設置是否記錄未開啓索引的查詢。
    set global log_queries_not_using_indexes=on;
  4. 設置記錄超過制定時長的語句。
    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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章