索引的定義
MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構.能夠得出索引的本質就是數據結構
你能夠簡單理解爲"排序好的快速查找數據結構"
在數據以外,數據庫還維護着知足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構的基礎上實現高級查找算法,這種數據結構就是索引
通常來講索引自己很大,不適合所有存儲在內存中,所以索引每每以索引文件的形式存儲在磁盤上
咱們日常所說的索引,若是沒有特別指明,都是指B樹(多路搜索樹,並不必定是二叉的)結構組織的索引,其中彙集索引,次要索引,覆蓋索引
複合索引,前綴索引,惟一索引默認都是使用B+樹索引,統稱索引.固然,除了B+樹這種類型的索引以外,還有哈稀索引(hash index)等
優點
相似大學圖書館建書目錄索引,提升數據檢索的效率,下降數據庫的IO成本
經過索引列對數據進行排序,下降數據排序成本,下降了CPU的消耗
能夠加速表和表之間的鏈接
劣勢
實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引也是要佔內存空間的
雖然索引大大提升了查詢速度,同時都會下降更新表的速度,如對錶進行insert,update和delete
由於更新表時,MySQL不只要保存數據,還要保存一下索引文件每次更新添加了索引的字段,都會調整由於更新所帶來的鍵值變化後的索引信息
索引只是高效的一個因素,若是你的MySQL有大數據量的表,就須要花時間研究創建最優秀的索引,或優化查詢方法
索引的分類
單值索引:即一個索引只包含單個列,一個表不\能夠有多個單列索引
惟一索引:索引列的值必須惟一,但容許有控制,例如手機號,銀行卡號等值必須是惟一
複合索引:即一個索引包含多個列,例如手機號和銀行卡號一塊兒,若是一個表中的數據在查詢時有多個字段老是同時出現則這些字段就能夠做爲複合索引
基本語法
建立:create [unique] index indexName on tbname(columnname(lenght))
更改:alter table tbname add [unique] index [indexName] on (columnname(lenght))
更改:alter table tbname add [unique] fulltext [indexName] on (columnname(lenght))#指定索引爲fulltext,用於全文索引
刪除:drop index [indexName] on tbname;
查看:show index from tbname\G;
索引結構
BTree索引
Hash索引
full-text全文索引
R-Tree索引mysql
哪一種狀況須要建立索引
1.主鍵自動創建惟一索引
2.頻繁做爲查詢條件的字段應該建立索引
3.查詢中與其餘表關聯的字段,外鍵關係創建索引
4.頻繁更新的字段不適合建立索引,由於每次更新不僅僅是更新數據還會更新索引
5.Where條件裏用獲得的字段適合建立索引
6.單鍵/組合索引的選擇問題,在高併發下傾向建立組合索引
7.查詢中排序的字段,排序字段若經過索引去訪問將大大提升排序速度
8.查詢中統計或者分組字段
哪一種狀況不須要建索引
1.表記錄太少(通常生產環境下,三百萬條記錄性能就可能開始降低,官方說的是五百萬到八百萬)
2.常常增刪改的表
3.某個數據列的值包含許多重複的內容ios
性能分析算法
1.MySQL Query Optimizer(查詢優化器)
1.1MySQL中有專門負責優化select語句的優化器模塊,主要功能:經過計算分析系統中收集到的統計信息,爲客戶端請求的query提供它認爲最有的執行計劃(它認爲最優的數據檢索方式,但不見得是DBA認爲是最優的,這部分是最耗時間的)
1.2當客戶端向MySQL請求一條query,命令解析其模塊完成請求分類,區別是select並轉發給MySQL Query Optimizer時,MySQL Query Optimizer首先會對整條Query進行優化,處理掉一些常量表達式的預算,直接轉換成常量值,並對query中的查詢條件進行簡化和轉換,如去掉一些無用或顯而易見的條件,結構調整等,而後分析query中的Hint信息(若是有),看顯示Hint信息是否能夠徹底肯定該query的執行計劃,若是沒有Hint或Hint信息不足以徹底肯定執行計劃,則會讀取所涉及對象的統計信息,根據query進行寫相應的計算分析,而後再得出最後的執行計劃。sql
2.MySQL常見瓶頸
CPU:CPU在飽和的時候通常發生在數據裝入內存或從磁盤讀取數據時候
IO:磁盤IO瓶頸發生在裝入數據遠大於內存容量的時候
服務器硬件的性能瓶頸,top,free,iostat和vmstat來查看系統的性能狀態數據庫
3.Explain
3.1explain+SQL語句順序解釋
表的讀取順序(數字大的先讀,相同的則由上而下讀取)
數據讀取操做的操做類型
哪些索引可使用
哪些索引被實際使用
索引總長度
表之間的引用
每張表有多少行被優化器查詢
額外的信息(出現using index較好,出現using filesort較差)
3.2怎麼用
explain+SQL語句
執行計劃包含如下的信息緩存
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
致使索引失效的案例
1.建什麼索引用什麼索引,順序也最好保持一致
2.最佳左前綴索引名稱命名(如字段name,age,city,則索引命名應該是nameAgeCity或者xxx_nameAgeCity,順序很重要)
3.不在索引列上作任何操做(計算,函數,or,類型轉換),會致使索引失效而轉向全表掃描
4.存儲引擎不能使用索引中範圍條件右邊的列(如name='lin' and age>25 and city='qingdao',則age後面的索引會實效)
5.儘可能使用覆蓋索引(只訪問索引的查詢(索引列和要查詢的列一致)),減小select *
6.MySQL在使用不等於(!=或者<>)的時候沒法使用索引會致使全表掃描
7.is null,is not null 也沒法使用索引
8.like以通配符在這('%abc','%abc%')兩種狀況會索引實效變成全表掃描,'abc%'則不會,若要'%abc','%abc%'不失效,建議使用覆蓋索引,且查詢的字段要少於索引或者與索引一致,不使用select *。如爲name,age,city建了索引,請這麼使用:select name或者select age,或者select city或者select name,age,city。若是select name,age,city,email則會全表掃描
9.字符串不加引號索引失效,
10.少用or,用他來鏈接時索引會失效
11.select * from A where exists (select 1 from where b.id=A.id)#當A表的數據系小於B表時,用exists優於in
12.使用join代替子查詢服務器
數據類型選擇
1.數字類型
Float和double選擇(儘可能選擇float)
區分開TINYINT / INT / BIGINT,能肯定不會使用負數的字段,建議添加 unsigned定義
可以用數字類型的字段儘可能選擇數字類型而不用字符串類型的
2.字符類型
char,varchar,TEXT的選擇:非萬不得已不要使用 TEXT 數據類型,定長字段,建議使用 CHAR 類型(填空格),不定長字段儘可能使用 VARCHAR(自動適應長度,超過階段),且僅僅設定適當的最大長度
3.時間類型
按選擇優先級排序DATE(精確到天)、TIMESTAMP、DATETIME(精確到時間)
4.ENUM
對於狀態字段,能夠嘗試使用 ENUM 來存放
5.避免使用NULL字段
很難查詢優化且佔用額外索引空間數據結構
字符編碼
一樣的內容使用不一樣字符集表示所佔用的空間大小會有較大的差別,因此經過使用合適的字符集,能夠幫助咱們儘量減小數據量,進而減小IO操做次數。
1.純拉丁字符能表示的內容,選擇 latin1 字符編碼
2.中文可選用utf-8
3.MySQL的數據類型能夠精確到字段,因此當咱們須要大型數據庫中存放多字節數據的時候,能夠經過對不一樣表不一樣字段使用不一樣的數據類型來較大程度減少數據存儲量,進而下降 IO 操做次數並提升緩存命中率併發
order by優化
重點:使用order by就須要看會不會產生filesort
mysql支持兩種方式排序,index和filesort,index效率高
儘可能使用Index方式排序,避免使用FileSort方式排序
儘量在索引列上完成排序操做,遵守索引列的最佳左前綴
若是不在索引列上,filesort有兩種算法:雙路排序和單路排序
雙路排序:取一堆數據,要對磁盤進行兩次掃描(mysql4.1以前,後來的版本增長了單路排序)
單路排序:從磁盤讀取查詢須要的全部列,按照order by列在buffer對他們進行排序,而後掃描排序後的列表進行輸出,效率快,但會使用更多的內存空間,所以注意調整sort_buffer_size和max_lenght_for_sort_data參數值(增大值),避免建立tmp文件從而進行屢次I/O
group by優化
和order by差很少
先排序後分組,遵守索引列的最佳左前綴
當沒法使用索引列時,增大max_lenght_for_sort_data和sort_buffer_size的值
where高於having,能在where限定的條件就不要去having限定了
優化總結
1.開啓慢查詢日誌
2.expain+慢SQL分析
3.show profile查詢sql在mysql服務器裏面的執行細節和生命週期狀況
4.sql數據庫服務器的參數調優
函數