MySQL 優化,索引

一、MyISAM 和 InnoDB

Mysql邏輯架構:

1.連接層 2.服務層(sql優化)3.引擎層(存儲和提取)4.存儲層(數據存儲再文件系統,完成與存儲引擎的交互)

1. 對比:

2. MyISAM

適用於讀操作多於寫操作,寫鎖後其他線程不能做任何操作,會造成阻塞。不支持事務。適合小併發,小數據。

支持Btree索引

MyISAM 使用表鎖:執行select語句前,會自動給涉及的表加讀鎖,執行增刪改前給涉及的表自動加寫鎖。

3. InnoDB

Mysql 默認InnoDB 存儲引擎,支持事務,適合插入和更新操作較多的場景,支持Btree和自適應Hash索引,使用行鎖。適合高併發,大數據。

行鎖變表鎖:varchar 類型字段沒寫引號,發生類型轉換,索引失效導致行鎖變表鎖。

間隙鎖:當我們用範圍條件檢索數據,並請求共享或排他鎖時,InnoDB會給已有的數據記錄的索引項加鎖;
對於鍵值在範圍內但不存在的記錄,就叫間隙。

間隙鎖的危害:InnoDB會對這個間隙加鎖。導致這個間隙無法進行操作,產生阻塞。

鎖定一行的方式:

begin;
select * from A where a=8 for update; 鎖定一行後對該行的其他操作將被阻塞,直到鎖定行commit。
commit;

InnoDB 行鎖分析:

通過檢查InnoDB_row_lock_xxx 分析行鎖的爭奪情況
show status like 'innodb_row_lock%';
InnoDB_row_lock_time_avg 等待平均時長
InnoDB_row_lock_waits 等待總次數
InnoDB_row_lock_time 等待總時長

4. 讀寫鎖

讀鎖(read)共享鎖
當前線程只能讀當前被鎖的表,不能修改任何表。 其他線程對被鎖表只能讀,寫操作阻塞。其他表可以讀寫。
寫鎖 (write)排他鎖
當前線程只能對當前表讀寫。其他線程對當前表讀寫阻塞。
總結來說:讀鎖會阻塞寫,不會阻塞讀,而寫鎖則把讀和寫都阻塞。

二、索引優化

1. sql 性能下降原因

查詢語句寫的不好(子查詢,關聯查詢太多)。

沒建索引,或建了索引但索引失效。

服務器調優以及各個參數設置不合理(緩衝,線程數)。

2. mysql 操作命令

rpm -ivh MySQL-client-5.6.22-1.el6.i686.rpm
rpm -ivh MySQL-server-5.6.22-1.el6.i686.rpm
cat /etc/passwd|grep mysql 查看mysql安裝是否成功
cat /etc/group|grep mysql 查看有沒有mysql組
rpm -qa|grep -i mysql 查詢已安裝
ps -ef|grep mysql

單值索引:create index idx_user_name on user(name)
複合索引:create index idx_user_nameEmail on user(name,email)
創建索引:alter table `book` add index z(`card`);
刪除索引:drop index idx_class_card on book;

3. 索引簡介

3.1 是什麼?

MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高校獲取數據的數據結構。可以得到索引的本質:索引是數據結構

索引是排好序的快速查找數據結構,可以提高MySQL查詢效率,索引通常以索引文件的形式存儲在磁盤上。

索引分類:單值索引 唯一索引(索引列的值必須唯一) 複合索引

3.2 優劣勢

優勢:提高數據檢索效率,降低數據庫的IO成本;索引列對數據進行排序,降低數據排序的成本,降低cpu的消耗。

劣勢:佔用空間,表的更新速度減慢,每次更新都要保存新添數據的索引列字段,需要進行索引信息調整。需要不停優化。

3.3 mysql 索引結構

BTree索引

真實數據存儲在葉子節點(磁盤中),非葉子節點存儲的是搜索方向(範圍區間)。

Hash索引

全文索引

R-Tree索引

3.4 哪些情況需要建立索引

1.主鍵自動創建唯一索引

2.頻繁查詢的字段

3.查詢中與其他表關聯的字段,外鍵關係建立索引

4. 頻繁更新不適合建索引。

5.where條件用不到的字段不建索引

6.高併發組合索引

7.查詢中統計或者分組字段

4. Explain 查看執行計劃

使用EXPLAIN關鍵字可以模擬優化器執行SQL語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是結構的性能瓶頸。

4.1 關鍵字介紹

1. id select查詢的序列號,表示查詢中執行select子句或者表的執行順序
1)id相同,按順序執行
2)id不同,遞增,數字大優先級高
3)id相同也不同 數字大優先級高,相同按順序執行

2.select_type :查詢類型(普通,聯合,子查詢)

simple 簡單查詢  primary 最外層查詢  subquery 子查詢 derived 衍生(from列表中的子查詢) union select出現在UNION之後

3.table 表

4.type 訪問類型,以何種方式去訪問數據

好-->差 儘可能達到rang級別,最好達到ref
system > const > eq_ref > ref > range > index > All

1)all 全表掃描,數據量較大時需要優化
2)index 全索引掃描
3)rang 範圍掃描
4)ref 使用了非唯一索引進行數據查找 例如部門號
5)eq_ref 使用唯一性索引進行數據查找 例如員工號
6)const 至多一個匹配行
7)system 系統只有一行記錄

5.possible_keys 可能用到的索引

6.key 實際用到的索引

7.key_len 索引中使用的字節數,保證結果前提下,越短越好

8.ref 顯示索引的那一列被使用了

9.rows 查找結果讀取的行數

10.Extra 包含不適合在其他列中顯示但十分重要的信息

1)Using filesort 無法利用索引完成的排序操作稱爲文件排序
2)Using temporary 建立臨時表來保存中間結果,查詢完成之後把臨時表刪除,常見order by group by
3)Using index  表示當前查詢是覆蓋索引的
4)Using where 使用了where 過濾

4.2 覆蓋索引和最左前綴

覆蓋索引:select的數據列只用從索引中就能取得,不必讀取數據行,查詢列要被所建的索引覆蓋。

最左前綴法則:多列索引要遵循最左前綴法則,查詢從索引的最左列開始並且不跳過索引中的列。

5. 索引優化

5.1 索引失效

1)不要在索引上做操作(計算,函數,自動或手動類型轉換)
2)存儲引擎不能使用索引中範圍條件右邊的列。
3)儘量使用覆蓋索引(索引列和查詢列一致),減少select *
4)使用 != 或<>無法使用索引會導致全表掃描。
5)is null is not null無法使用索引
6)like以通配符開頭(%abc)索引失效會變成全表掃描的操作。 想使用 %abc% 就建立覆蓋索引,like KK%相當於=常量     %KK和%KK% 相當於範圍。
7)儘量少用or,使用or連接索引會失效
8)字符串不加單引號索引失效

5.2 優化口訣

【優化口訣】
全值匹配我最愛,最左前綴要遵循;
帶頭大哥不能死,中間兄弟不能斷;
索引列上少計算,範圍之後全失效;
like百分寫最右,覆蓋索引不寫 * ;
不等空值還有or,索引失效要少用;
VARCHAR引號不可丟,SQL高級so easy;

三、查詢優化

1. 慢sql分析

讓系統跑一段時間,查看生產的慢sql情況。

開啓慢查詢日誌,設置闕值,將慢sql語句抓取出來。 show variables like '%slow_query_log%';

使用explain 進行分析。

show profile 查詢sql在服務器裏的執行細節和生命週期情況。

sql 數據庫服務器參數調優。

2. 小表驅動大表

select * from A where id in (select id from B)
當B表數據集小於A表,使用 in
select * from A where exists (select 1 from B where B.id = A.id)
當A的數據集小於B表,使用 exists
exists 將主查詢的數據,放到子查詢中做條件驗證,根據驗證結果決定主查詢結果是否保留。

3. Order By 優化

3.1 Mysql 兩種排序方式

文件排序 FileSort效率低,掃描有序索引排序 Index效率高

index 方式排序:OrderBy語句使用索引最左前列,使用Where子句與OrderBy子句條件列組合滿足索引最左前列

儘可能在索引上完成排序操作,遵循最左前綴,如果不在索引列上mysql 就會啓動單路排序。

3.2 單路排序

從磁盤讀取查詢需要的所有列,按照orderby列在buffer對它們進行排序,將排序好的列表進行輸出。避免了二次讀取數據,把隨機IO變成順序IO,但是會使用很大空間。

單路排序的問題:數據列超過buffer容量,導致大量IO操作。

單路排序優化:
1. 忌select *
2. 嘗試提高sort_buffer_size
3.max_length_for_sort_data

常見面試題彙總

如何設計一個高併發的系統

① 數據庫的優化,包括合理的事務隔離級別、SQL語句優化、索引的優化

② 使用緩存,儘量減少數據庫 IO

③ 分佈式數據庫、分佈式緩存

④ 服務器的負載均衡

鎖的優化策略

① 讀寫分離

② 分段加鎖

③ 減少鎖持有的時間

④ 多個線程儘量以相同的順序去獲取資源

實踐中如何優化MySQL

①sql語句及索引的優化

②數據庫表結構的優化

③系統配置的優化

④硬件的優化

優化數據庫的方法

①選取最適用的字段屬性,儘可能減少定義字段寬度,儘量把字段設置NOTNULL,例如’省份’、’性別’最好適用ENUM

②使用連接(JOIN)來代替子查詢

③適用聯合(UNION)來代替手動創建的臨時表

④事務處理

⑤鎖定表、優化事務處理

⑥適用外鍵,優化鎖定表

⑦建立索引

⑧優化查詢語句

SQL注入漏洞產生的原因?如何防止?

SQL注入產生的原因:程序開發過程中不注意規範書寫sql語句和對特殊字符進行過濾,導致客戶端可以通過全局變量POST和GET提交一些sql語句正常執行。

防止SQL注入的方式:
開啓配置文件中的magic_quotes_gpc 和 magic_quotes_runtime設置

執行sql語句時使用addslashes進行sql語句轉換

Sql語句書寫儘量不要省略雙引號和單引號。

過濾掉sql語句中的一些關鍵詞:update、insert、delete、select、 * 。

提高數據庫表和字段的命名技巧,對一些重要的字段根據程序的特點命名,取不易被猜到的。

Php配置文件中設置register_globals爲off,關閉全局變量註冊

控制錯誤信息,不要在瀏覽器上輸出錯誤信息,將錯誤信息寫到日誌文件中。

char和varchar的區別?

char是一種固定長度的類型,varchar則是一種可變長度的類型,它們的區別是:  

char(M)類型的數據列裏,每個值都佔用M個字節,如果某個長度小於M,MySQL就會在它的右邊用空格字符補足.(在檢索操作中那些填補出來的空格字符將被去掉)在varchar(M)類型的數據列裏,每個值只佔用剛好夠用的字節再加上一個用來記錄其長度的字節(即總長度爲L+1字節).  

varchar使用場景:

1.字符串列得最大長度比平均長度大很多

2.字符串很少被更新,容易產生存儲碎片

3.使用多字節字符集存儲字符串

Char使用場景:

1.存儲固定長度(身份證,手機號)

2.長度比較短小得字符串

3.適合經常更新的字符串,更新時不會出現頁分裂得情況,避免出現存儲碎片,獲得更好的io性能

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

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