一、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性能