(mysql優化-1) 索引優化

1.慢查詢日誌mysql

MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中
#查看慢查詢是否開啓
>show variables like '%slow_query_log%';
#開啓慢查詢(默認是關閉)
>set global slow_query_log=1;
#設置時間閥值(默認是10s)
>set global long_query_time=1;
#未使用索引的查詢也被記錄到慢查詢日誌中(默認關閉)
>set global log_queries_not_using_indexes=1;
分析日誌
mysqldumpslow  /var/lib/mysql/ArchLinux-slow.log

Count: 1    #訪問計數    
Time=0.00s (0s)    #平均查詢時間(總查詢時間)
Lock=0.00s (0s)    #平均鎖定時間(總鎖定時間)
Rows_sent=1000.0 (1000)    #平均返回記錄數(總返回記錄數)
Rows_examined=1000.0 (1000)    #平均掃描過的行數(總掃描過的行數)
Rows_affected=0.0 (0)    #平均更新行數(總更新行數)
分析日誌(percona-toolkit)
pt-query-digest /var/lib/mysql/ArchLinux-slow.log

開始總的摘要信息
# 170ms user time, 10ms system time, 26.00M rss, 213.39M vsz
--此工具執行日誌分析時的所用時間、內存資源(rss物理內存佔用大小,vsz虛擬內存佔用大小)
# Current date: Mon Jul 28 09:55:34 2014
--分析時的系統時間
# Hostname: lump.group.com
--進行分析的主機名
# Files: mysql-slow.log
--分析的日誌文件名稱
# Overall: 5 total, 4 unique, 0.02 QPS, 0.04x concurrency 
--文件中總共的語句數量,惟一的語句數量(對語句進行了格式化),QPS(每秒查詢數(queries per second)),併發數
# Time range: 2014-07-28 09:50:30 to 09:54:50
--記錄日誌的時間範圍

# Attribute          total     min     max     avg     95%  stddev  median
--total總計,min最小,max最大,avg平均,95%把全部值從小到大排列,位於95%的那個數
–Exec time:語句執行時間
–Lock time:鎖佔有時間
–Rows sent:發送到客戶端的行數
–Row examine:掃描的行數(SELECT語句)
–Row affecte:發送改變的行數(UPDATE, DELETE, INSERT語句)
–Bytes sent:發送多少bytes的查詢結果集
–Query size:查詢語句的字符

查詢分組統計結果
–Rank:分析的全部查詢語句的排名,默認按查詢時間降序排序
–Query ID:查詢語句的指紋
–Response time:響應時間
–Calls:查詢執行的次數
–R/Call:每次執行的平均響應時間
–V/M:響應時間Variance-to-mean的比率
–Item:查詢語句

每一個獨立查詢語句的分析
#保存到數據庫中(簡單)
pt-query-digest --user=root --password=123456 
   --review h=127.0.0.1,D=sakila,t=global_query_review --no-report --create-review-table                 
   /var/lib/mysql/ArchLinux-slow.log

#保存到數據庫中(詳細)
pt-query-digest --user=root --password=123456 
   --history h=127.0.0.1,D=sakila,t=global_query_history --no-report --create-history-table                 
   /var/lib/mysql/ArchLinux-slow.log


2.分析數據sql

>explain select customer_id,first_name,last_name from customer;

id:1    #若是id相同,從上往下順序執行;不然id值越大,優先級越高,越先執行
select_type: SIMPLE    #查詢類型(簡單查詢SIMPLE;含子查詢或聯合查詢PRIAMRY;聯合查詢UNION;聯合查詢結果UNION RESULT;非from子查詢SUBQUERY;from子查詢DERIVED)
table: customer    #顯示這條數據是哪一張表(表的別名;derived子查詢;null計算結果)
type: ALL    #顯示鏈接使用何種類型(null不用訪問表或索引>const直接獲取(主索引)>eq_ref主索引引用(經常使用於多表鏈接)>
ref次索引檢索>range只檢索給定範圍索引>index遍歷索引>all遍歷全表)
possible_keys: NULL    #顯示可能應用在這張表的索引
key: NULL    #實際使用的索引
key_len: NULL    #使用索引的長度(越短越好)
ref: NULL    #顯示索引的那一列被使用
rows: 599    #檢索行數
Extra:    #額外信息(Using index:使用索引;Using where:在使用索引的基礎上進行條件判斷;
Using filesort:表示MySQL須要使用臨時表來存儲結果集,常見於排序和分組查詢;
Using temporary:MySQL中沒法利用索引完成的排序操做稱爲「文件排序」)


3.查詢優化數據庫

#優化Max

>explain select  max(payment_date) from payment;    (type爲ALL)
>create index idx_paydate on payment(payment_date);
>explain select  max(payment_date) from payment;    (type爲NULL)
#優化子查詢

>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')
    );    (採用子查詢)
>explain select film.title,film.release_year,film.length from film,film_actor,actor 
    where actor.first_name='sandra'  
        and film_actor.actor_id=actor.actor_id 
          and  film_actor.film_id=film.film_id;    (採用鏈接查詢)
#去除重複索引(重複索引指相同的列以相同的順序創建的同類型的索引)

create table test(
    id int primary key,
    name varchar(10),
    constraint union_key unique(id)
);

pt-duplicate-key-checker -u root -p '123456' -h 127.0.0.1
#去除冗餘索引(冗餘索引指多個索引的前綴列相同,或是在聯合索引中包含主鍵的索引)

create table test(
    id int primary key,
    name varchar(10),
    index union_index(id,name(4))
)

pt-duplicate-key-checker -u root -p '123456' -h 127.0.0.1
#刪除不用的索引

pt-index-usage -u root -p '123456' -h 127.0.0.1
#索引左前綴原則【假若有聯合索引index(c1,c2,c3,c4)】

(a).where c1=x and c2=x and c4>x and c3=x : index(c1,c2,c3,c4),where添加能夠交換位置
(b).where c1=x and c2=x and c4=x order(group) by c3 : index(c1,c2,c3),
(c).where c1=x and c2=x and c3=x order(group) by c4 : index(c1,c2,c3,c4)
(d).where c1=x and c4=x order(group) by c2,c3 : index(c1,c2,c3),order(group) by不能夠交換位置
(e).where c1=x and c4=x order(group) by c3,c2 : index(c1)
#索引覆蓋【假如主鍵key(c1),聯合索引index(c1,c2)】

(a).select * from t1 order by c1 : key(c1),
(b).select * from t1 order by c1,c2 : index(1,2)


4.如何創建索引併發

a.在where從句,group by從句,order by從句,on從句中出現的列
b.索引字段越小越好
c.離散度大的列放到聯合索引的前面(count(distinct 字段名)越大的離散度越大)
相關文章
相關標籤/搜索