mysql優化相關

一 SQL 語句優化相關

1 許可的重要性

影響所有語句的一個因素是:你的許可設置的越複雜,所需要的開銷也會越多,執行grant 語句時使用簡單的許可,當客戶端執行語句時,可以是mysql降低許可檢查開銷,未授權的表或列級資源,服務器不需要檢查tables_priv和columns_priv 表的內容。
同樣,如果不對任何賬號進行限制,服務器不需要對資源進行統計,如果查詢量很高,可以花費一些時間使用簡化的授權結構來降低許可檢查開銷。
如果你的問題是與具體mysql表達式或函數有關,可以使用mysql客戶端程序所帶的benchmark()函數執行定時測試。
其語法問benchnark(loop_count,expression),如
mysql優化相關
上面的結果顯示mysql在該系統上再0.13秒內可以執行1000,000個簡單的+表達式運算
所有mysql函數應該被高度優化,但總是有可能有一些例外,benchmark()是一個找出是否查詢有問題的工具

2 explain 工具

1 作用

如果在select語句前面放上相關詞explain,mysql將解釋他如何處理select,提供有關如何連接和連接次序,藉助於explain,可以知道什麼時候必須爲表加入索引已得到一個使用索引來尋找記錄的更快的select。

2 語法格式

explain tabl_name 或 explain [extended] select selectoption\
explain 語句可以用作describe 的一個同義詞,或者獲取關於mysql如何執行select語句的信息

3 explain 和 describe ,columnsfrom 的區別和聯繫

explain table_name 是 describe table_name 或 show columnsfrom tab_name 的一個同義詞
mysql優化相關
mysql優化相關
如果由於使用了不正確的索引出現了問題,應運行analyze table 更新表的統計,這樣會影響優化器的選擇
還可以知道優化器是否以一個最佳次序連接表,爲了強制優化器讓一個select 語句按照表命名順序被列出,
mysql用一遍掃描多次連接的方式來解決所有的鏈接,這意味着mysql從第一個表中讀取一行,然後找到第二個表中的一個匹配行,然後在第3個表中等,當所有的表都處理完成之後,他輸出選中的列並且返回表清單知道找到一個有更多匹配的行的表,從該表讀入下一行並繼續處理下一個表。
當使用extended關鍵字時,explain 產生附加信息,可以用show warnings 瀏覽,該信息顯示優化器限定select語句中的表和列名,重寫並且執行優化規則後select語句是什麼樣子,並且還可能包括優化過程的其他註解。

4 explain 各列的含義

explain 的每個輸出行提供一個表的相關信息,並且每個行包括下面的列
mysql優化相關

1. id

select 識別符,這是select的查詢序號
select_type select 類型,可以是一下的任何一種

1 simple 簡單的(不使用union或子查詢)
2 primary 最外面的select
3 union 中的第二個或後面的select
4 dependent union union 中的第二個或後面的select 語句,取決於外面的查詢
5 union result union 的結果
6 subquery 子查詢中的第一個select
7 dependent subquery 子查詢中的第一個select,取決於外面的查詢
8 derived 導出表的select(from 子句的子查詢)

2. table

輸出的行所引用的表

3. type

連接類型,下面給出各種連接類型,按照從最佳類型到最壞類型的排序,掃描的方式

1 system
表僅有一行(=系統表),這是const連接類型的一個特例
2 const
最多有一個匹配行,他講在查詢開始時被讀取,因爲僅有一行,在這行的列值可被優化器剩餘部分認爲是常數,const表很快,因爲他們只讀取一次
const 用於常數值比較primary key 或 unique 索引的所有部分時
3 eq_ref
對於每個來自於前面的表的行組合,從該表中讀取一行,這可能是最好的鏈接類型,除了const類型,他用在一個索引的所有部分被關聯使用並且索引是unique或primary key
eq_ref 可以用於使用= 操作符比較的帶索引的列,比較值可以爲常量或一個使用該表前面所讀取的表的列的表達式。
select * from ref_table,other_table where ref_tablekey_column=other_table colm;
select * from ref_table,other_table where ref_tablekey_column_part1=other_tablecolumn and ref_tablekey_column_part2=1;
對於每個來自於前面的表的行組合,所有匹配索引值的行將從這張表中讀取,如果連接只使用鍵的最左邊的前綴,或如果鍵不是unique或primary key ,則使用ref,如果使用的鍵僅僅匹配少量行,該連接類型是不錯的。
ref 可以用於使用=或<=>操作符的帶索引的列
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
4 ref_or_null
該連接類型如同ref,但是添加了mysql可以專門搜索包括null值的行,在解決子查詢中經常使用該連接類型的優化
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
5 index_merge
該聯合類型表示使用了索引合併優化方法,在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素
6 unique_subquery
該類型替換了下面形式的IN子查詢的ref
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高
7 index_subquery
該連接類型類似於unique_subquery,可以替換IN子查詢,但只適合下列形式的子查詢中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
8 range
值檢索給定範圍的行,使用一個索引來選擇行,key 列顯示了使用哪個索引,key_lan 包含了所使用的索引的最長關鍵元素,在該類型中的ref列爲NULL
當使用=、 <>、 >、 >=、 <、 <=、 IS NULL、 <=>、 BETWEEN或者IN操作符,用常量比較關鍵字列時,可以
使用range:
SELECT * FROM tbl_name
WHERE key_column = 10;
SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20;
SELECT * FROM tbl_name
WHERE key_column IN (10,20,30);
SELECT * FROM tbl_name
WHERE key_part1= 10 AND key_part2 IN (10,20,30);
9 index
該連接類型與ALL相同,除了只有索引數被掃描。這通常被ALL快,因爲索引文件通常比數據文件小,當查詢只使用作爲單一索引部分的列時,mysql可以使用該連接類型
10 all
對於每個來自於先前的表的行組合,進行完成的表掃描,如果表是第一個沒標記的const的表,這通常不好,並且通常在他的情況下很差,通常可以增加更多的索引而不是要使用all,使得行能基於前面的表中的常數值或列值被檢索

4. possible_keys

列指出mysql能使用哪個索引在該表中找到行,該列完全獨立於explain輸出所示的表的次序,這意味着在possibe_keys中的某些鍵實際上不能按生成的表次序使用,如果該列是NULL,則沒有相關的索引,這種情況下,可以通過檢查where字句查看那是否引用某些列或者適合索引的列來提高性能。
掃描時可能使用的索引
看錶的索引 show index from X;
mysql優化相關

5. key

實際使用的索引
key 列顯示了mysql實際決定使用的鍵(索引),如果沒有選擇索引,則是null,要想前置mysql是使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX, USER INDEX 或者 IGNORE INDEX
對於myisam和BDB表,運行analyze table 可以幫助優化器選擇更好的索引,對於myisam表,可以使用myisamchk-analyze

6. key_len

顯示了mysql決定使用的鍵的長度,如果鍵是NULL,則長度爲NULL,通過此列可以確定mysql將實際使用一個多部分關鍵字的幾個部分

7. ref

顯示使用了那個列或常數與key一起從表中選擇行

8. rows

顯示了mysql認爲他執行查詢時必須檢查的行數

9. extra

該列包含了mysql解決查詢的詳細信息,SQL語句的額外信息,如排序方式
1 distinct
mysl發現第一個批判行後,停止了爲當前行組合搜索更多的行
2 not exists
mysql能夠對查詢進行 left join優化,發現一個匹配left join標準的行後,不再爲前面的行組合在該表內檢索更多的行
3 range checked for each record (index map:#)
mysql沒有發現好的可以使用的索引,但發現如果來自前面的表的列已知,可能部分索引可以使用,對前面的表的每行組合,mysql檢查是否可以使用range或index_merge訪問方法來索取行
4 using filesort
mysql需要額外的一次傳遞,以找出如何按排序檢索行,通過根據連接類型瀏覽所有行併爲所有匹配where字句的行保存排序關鍵字和行的指針來完成排序,然後關鍵字被排序,並按排序檢索行
5 Using index
從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息。當查詢只使用作爲
單一索引一部分的列時,可以使用該策略。
6 Using temporary
爲了解決查詢,MySQL需要創建一個臨時表來容納結果。典型情況如查詢包含可以按不同情況列出列
的GROUP BY和ORDER BY子句時。
7 Using where
WHERE子句用於限制哪一個行匹配下一個表或發送到客戶。除非你專門從表中索取或檢查所有行,如果Extra值不爲Using where並且表聯接類型爲ALL或index,查詢可能會有一些錯誤。
如果想要使查詢儘可能快,應找出Using filesort 和Using temporary的Extra值。
8 Using sort_union(...), Using union(...), Using intersect(...)
這些函數說明如何爲index_merge聯接類型合併索引掃描。
9 Using index for group-by
類似於訪問表的Using index方式, Using index for group-by表示MySQL發現了一個索引,可以用來查詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜索硬盤訪問實際的表。並且,按最有效的方式使用索引,以便對於每個組,只讀取少量索引條目。

5 估計查詢性能

在大多數情況下,可以通過計算磁盤搜索來估計性能,對於小的表,通常能在1次磁盤搜索中找到的行(因爲索引可能被緩存),對於更大的表,可以使用B-樹索引進行估計,將需要log(row_count)/log(index_block_length/3*2/(index_length+data_pointer_length))+1次才能搜索找到行。
在mysql中,索引塊通常是1024個字節,數據指針通常是4字節,這對於有一個長度爲3的索引500000行的表,通過公式可以計算出log(500000)/log(1024/3*2/(3+4))+1=4次搜索。
上面的索引需要大約50000073/2=5.2MB,可以將大部分索引保存在內存中,僅需要1-2次調用從OS讀取數據來找到行
然而對於寫,將需要4次收縮請求來找到在哪兒存放新索引,並且通常需要2次搜索來更新這個索引並寫入行。
當表格變得更大時,所有內容緩存到OS或SQL服務
器後,將僅僅或多或少地更慢。在數據變得太大不能緩存後,將逐漸變得更慢,直到應用程序只能進行磁盤搜索(以logN增加)。爲了避免這個問題,隨數據增加而增加 鍵高速緩衝區大小。對於MyISAM表, 由key_buffer_size系統變量控制 鍵高速緩衝區大小。

技巧:
1 通過查看線程任務得到慢查詢語句

show processlist;

2 通過開啓慢查詢進行

3 通過explain 進行對查詢語句質量的定位。(查詢是否使用索引)

4 查看某一列的重複度,越小重複越多,越不適合創建索引
mysql優化相關

mysql優化相關

5 進行創建聯合索引

create table key_name on tabe_name (id,name,pw);

6 通過explain 進行掃描查詢;

3 部分SQL 語句使用小技巧

1 group by 語句注意事項

默認會對文件進行排序,如此會影響其速度

mysql優化相關
mysql優化相關
mysql優化相關
使用order by null 可以將group by 後面的排序去掉,默認只對指定的列進行排序。
mysql優化相關

2 使用join鏈接代替子查詢

mysql優化相關

mysql優化相關

Select * from X left join on Y.b=X.a;(左外連接) 此方式更優化!

二 索引相關

1 索引基本原理

索引的原理:
爲什麼創建索引後查詢的速度就會變快
傳統的順序是按照一個一個的方式進行檢索的,如果找到,則會繼續向後面執行,因爲其不敢保證後面是否還有相同的數據被存儲,因此只有全部檢索才能返回。

加上索引後,在二叉樹的原理下,根據折中的方式進行計算,首先會掃描全表,構建二叉樹並保存其數據存儲的物理位置,進行左右查找,最終鎖定其位置形成索引。
其相同的記錄會在同一節點進行

有索引的情況下檢索1024個條數據,只需要檢索10次,默認是log2(x) =y 2^y=X
其中X 是數據的量,y 是檢索的次數

索引查詢:
mysql優化相關

mysql優化相關

2 主鍵索引

當一張表中把某個字段設置爲主鍵的時候,該列就是主鍵索引。
主鍵字段不但不能爲空,而且不能重複

主鍵添加方式:
1 建表時添加:
mysql優化相關
2 建表後添加
mysql優化相關
3 索引的刪除
mysql優化相關

3 普通索引

mysql優化相關

普通索引可以同時創建多個
mysql優化相關
刪除索引
mysql優化相關
另一種方式添加索引
mysql優化相關

4 全文索引添加(mysql5.6開始支持全文索引)

全文索引,主要是針對文件
創建:
mysql優化相關
查看
mysql優化相關
如何使用全文索引:
錯誤的使用方式:
mysql優化相關

mysql優化相關
正確的使用方式
mysql優化相關
注意事項
1 在mysql中fulltext 索只針對myisam存儲引擎生效
2 針對英文生效 中文使用sphinx
3 使用方法爲match(字段名,字段名) against('關鍵字')
4 全文索引有停止詞
mysql優化相關
65% 表示第一條記錄的匹配度
而針對於a 經常發生的,則沒有創建索引,這就被稱爲停止詞
其索引的建立是通過比較生僻的詞進行創建的,
全文索引的刪除
mysql優化相關

5 唯一索引

mysql優化相關
唯一索引不能重複,但可以爲空
mysql優化相關
建表成功後添加索引:
mysql優化相關
刪除索引
mysql優化相關

6 外鍵

mysql優化相關

mysql優化相關
其原理是student的classid不能添加class表中ID 字段不存在的值進入student表中。

7 分析索引使用率

mysql優化相關
Read_key值越高越好
read_rnd_next 值越高越不好,越低越好

8 使用索引的注意事項

1 索引的代價

1 對磁盤佔用較嚴重
2 對DML語句有影響,修改、添加和刪除的速度會變慢,因爲其需要檢索索引,因此其速度會變慢

2 索引添加的原則

1 在較爲頻繁的查詢字段上創建索引
2 唯一性太差的字段上不適合創建索引
3 更新非常頻繁的字段不能創建索引
4 在where條件中經常出現的適合創建索引
5 該字段的內容有多個

3 使用索引的注意事項

1 對於創建了多列的索引,主要查詢添加使用了最左端的列,則索引一般會被使用,索引做用在多個列上,如果不是使用最左列索引,則用不上。
如我們對title,content 添加了複合索引
select from table_name where title='test'; 會用到索引
select
from tbale_name where content='test' ; 不會用到索引

2 對於使用like的查詢,查詢中如果是%aaa則不會使用索引,'aaa%'則會使用到索引。如果一定要使用%,則索引不能使用。
3 在進行查詢的時候,如果條件中有or,則該語句中的所有字段都必須創建索引,否則索引不能使用,如果是複合索引,則必須是最左邊的索引,如果兩個條件一個是左邊索引,一個是右邊索引,則不能使用索引。
4 如果列類型是字符串,那麼一定要在添加中的數字加上單引號,否則索引不能使用。
5 如果mysql 發現全表掃描更快,則不會使用索引。

三 存儲引擎相關

1 各存儲引擎的特點

如果表對事物回滾要求不高,同時是以查詢和添加爲主的表,對安全要求不高的情況下,我們考慮使用myisam存儲引擎,如BBS中的帖子表等
innodb存儲:對事物的要求高,保存的數據都是重要的數據,建議使用innodb存儲引擎,如支付表,訂單表,餘額賬戶表
myisam 插入的速度高於innodb,myisam不會再添加時進行排序和事物安全的查詢
myisam支持全文索引,innodb不支持
myisam支持表鎖,innodb支持行鎖
myisam和innodb的區別
1 事物安全方面
2 查詢和添加速度
3 鎖粒度
4 外鍵 innodb支持,myisam不支持

2 memory 速度很快

mysql優化相關
重啓則消失,因爲其是存儲在內存中,而不是磁盤中,因此重啓服務則會消失
mysql優化相關
選擇數據類型時,需要選擇最貼近於存儲的數據類型

3 myisam 存儲引擎碎片整理

如果數據庫的表的存儲引擎時myisam,則請一定要注意定時進行碎片整理

1 數據刪除前:

mysql優化相關
mysql優化相關

2 刪除數據但未收集碎片

mysql優化相關
mysql優化相關

3 收集碎片

mysql優化相關

4 查看大小

mysql優化相關

四 水平分割與垂直分割概念

1 水平分割

水平分割是按照某種規則將數據劃分到不同的表或數據庫中,如計費系統,通過按時間來劃分較合適,因爲系統都是處理某一時間段的數據。
分割原則:
表的結構不會發生變化,用戶根據需要分割的表的數量進行計算如
需要將一個表分成3個則
id=1 1%3=1
id=2 2%3=2
id=3 3%3=0
以此類推
表名最好使用X.0 X.1 X.2 通過id與表取模獲取到的結果來存儲

2 垂直分割

垂直分割就是要把表按照模塊劃分到不同的數據庫中,這種拆分在大型網站演變過程中很常見,當網站很小時,只有少量的人進行開發和維護,各模塊和表放在一起,當網站不斷壯大豐富時,需要很多子系統和模塊,此時需要把相同功能的模塊進行統一管理個建表,並進行分類,簡單的說就是把原來強耦合的系統拆分成多個弱耦合的服務,通過對服務鍵的調用來滿足業務需求。

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