索引前端
相似於書目,用於快速檢索
mysql
優勢:
sql
提升數據檢索效率;
數據庫
提升表間的join效率;
緩存
利用惟一性索引,保證數據的一致性;
數據結構
提升排序和分組效率;
併發
缺點:
數據庫設計
消耗更多的物理存儲;
ide
數據變動時,索引也須要更新,下降更新效率函數
二叉樹、B數、B+數、hash索引
二叉樹
二叉樹的每一個節點至多隻有兩顆子樹,二叉樹的子樹有左右有序之分,次序不能顛倒
不適合作數據庫索引:
一、當數據量大的時候,樹的高度會比較高,查詢會比較慢;
二、每一個節點只存儲一個記錄,可能致使一次查詢有不少次磁盤io;
B樹

B+樹是B樹的變體, 還是多叉搜索樹,在B樹的基礎上,作了一些改進:
一、非葉子節點再也不存儲數據,數據只存儲在同一層的葉子節點上;
二、葉子之間,增長了鏈表,獲取全部節點,再也不須要中序遍歷;
三、非葉子節點,不存儲實際記錄,而只存儲記錄的KEY的話,那麼在相同內存的狀況下,B+樹可以存儲更多索引;
四、在MySQL中,爲了方便,直接寫成BTREE
哈希索引:
創建在哈希表的基礎上,它只對使用了索引中的每一個值的精確查找有用
對於每一行,存儲引擎計算出了被索引的哈希碼,他是一個較小的值,而且有可能和其餘行的哈希碼相同
把哈希碼保存在索引中,而且保證了一個指向哈希表中的每一行的指針

B+樹索引和哈希索引的比較
大量惟一值的等值查詢,哈希索引效率一般比B+tree高
hash索引不支持模糊查找
hash索引不支持聯合索引中的最左匹配原則
hash索引不支持排序
hash索引不支持範圍查詢
hash索引只能顯示應用於memory、NDB表
索引使用建議
一、常常檢索的列;
二、常常用於錶鏈接的列;
三、常常排序、分組的列;
索引不使用建議
一、基數很低的列;
二、更新頻繁但檢索不頻繁的列;
三、BLOB、TEXT等長內容列;
四、不多用於檢索的列;
數據庫設計索引的緣由
一、用於提高數據庫的查找速度
二、提升聚合函數效率
三、提升排序效率,order by asc、desc
四、有時能夠避免回表
五、減小多表關聯時掃描行數
六、列定義爲default null 時,null值也會有索引,存放在索引數的最前端部分,所以儘可能不要定義容許null
彙集索引
innodb表,只可以有一個,由於數據行在物理磁盤上只能有一份彙集存儲。
innodb中,表即彙集索引,彙集索引即表
mysiam沒有彙集索引的概念
彙集索引優先選擇的列:
一、int/bigint
二、數據連續(單調)遞增或自增
不建議的彙集索引:
一、修改頻繁的列;
二、新增數據太過離散隨機
無論innodb有沒有主鍵,它都會有彙集索引,由於innodb是基於彙集索引的索引組織表
主鍵必定是彙集索引,彙集索引不必定是主鍵
主鍵索引
innodb的主鍵索引與行記錄是存儲在一塊兒的,故叫作彙集索引
由於這個特性,innodb的表必需要有彙集索引:
(1)若是表定義了PK,則PK就是彙集索引;
(2)若是表沒有定義PK,則第一個非空unique列是彙集索引;
(3)不然,InnoDB會建立一個隱藏的row-id做爲彙集索引;
主鍵由表中的一個或多個字段組成,它的值用於惟一的標識表中的某一條記錄
create table row_id(a int not null,b int null,c int not null,d int not null,unique key(b),unique key(d),unique key(c));
insert into row_id select 1,2,3,4;
insert into row_id select 5,6,7,8
insert into row_id select 9,10,11,12;
select a,b,c,d,_rowid from row_id;
另外_rowid只能查看單列爲主鍵的狀況,對於多列組成的主鍵就顯得無能爲力了
做用:
一、保證數據的完整性;
二、加快數據的操做速度;
三、主鍵值不能重複,也不能包含null;
主鍵選擇建議:
對業務無心義,沒必要受限於業務變化的影響;
不多修改和刪除;通常都是自增的
不建議使用較長的列作主鍵,例如char(64),由於全部的普通索引都會存儲主鍵,會致使普通索引過於龐大;
建議使用趨勢遞增的key作主鍵,因爲數據行與索引一體,這樣不至於插入記錄時,有大量索引分裂,行記錄移動;
例如:select * from t where name='lisi';
會先經過name輔助索引定位到B+樹的葉子節點獲得id=5,再經過彙集索引定位到行記錄。因此,其實掃了2遍索引樹。
innodb主鍵特色:
定義索引時,無論有無顯示包含主鍵,實際都會存儲主鍵值;
在MySQL5.6.9版本後,優化器已能自動識別索引末尾的主鍵值,以前版本則須要顯示加上主鍵列才能夠被識別(通過測試,老版本也支持此特徵)
例如:
仍然遵循最左前綴原則:
惟一索引
不容許具備索引值相同的行,從而禁止重複的索引或鍵值(在惟一約束上,和主鍵同樣)
惟一索引容許有空值(NULL);
一個表只能有一個主鍵,但能夠有多個惟一索引;
innodb表中主鍵必須是惟一索引,但惟一索引不必定是主鍵;
聯合索引
多列組成的索引
適合where條件中的多列組合
能夠避免回表(覆蓋索引)
支持多列不一樣的排序規則(8.0開始支持倒序索引)
聯合索引建議:
where條件中,常常同時出現的列放在聯合索引中;
把選擇性大的列放在聯合索引最左邊
覆蓋索引
經過索引數據結構便可完成查詢返回數據,不須要回表
執行計劃中,Extra爲關鍵字 using index;
desc select name from t1 where name like '%zyq%';
前綴索引
使用的緣由:
char、varcahr列太長,所有建立索引的話,效率太差,存在浪費;
或者blob、text類型不能整列做爲索引列,所以須要使用前綴索引
部分索引選擇建議:
一、統計平均值;
二、知足10%-30%的覆蓋度就能夠
缺點:
沒法利用前綴索引完成排序
與所有索引對比:
索引的最大長度767bytes啓用innodb_lagrge_prefix,增長到3072bytes,只針對dynamic,compressed格式管用對於redundant、compact格式,最大索引長度仍是767bytesmysiam表索引最大長度是1000bytes最大排序長度默認是1024(max_sort_length)
Copy Table方式這是InnoDB最先支持的建立索引的方式。建立索引是經過臨時表拷貝的方式實現的。1. 新建一個帶有新索引的臨時表。2. 而後鎖原表,禁止DML操做,容許讀操做。3. 將原表數據所有拷貝到臨時表(無排序,一行行拷貝)。4. 而後Rename,升級字典鎖,禁止讀寫。5. 完成建立索引的操做。這種copy方式的效率沒有inplace好 ,由於copy須要記錄undo和redo log,並且由於臨時佔用buffer pool引發短期內性能受影響。Inplace方式這是原生MySQL 5.5,以及innodb_plugin中提供的建立索引的方式。所謂Inplace,也就是索引建立在原表上直接進行,不會拷貝臨時表。1. 新建一個帶有新索引的臨時表。2. 而後鎖原表,禁止DML操做,容許讀操做。3. 讀取彙集索引,構造新的索引項,排序並插入新索引。4. 而後Rename,升級字典鎖,禁止讀寫。5. 完成建立索引的操做。能夠避免重建錶帶來的IO和CPU消耗,保證DDL期間依然有良好的性能和併發。Inplace方式建立索引,建立過程當中,原表一樣可讀的,可是不可寫。Online方式這是MySQL5.6.7中提供的建立索引的方式。不管是CopyTable方式,仍是Inplace方式,建立索引的過程當中,原表只能容許讀取,不可寫。對應用有較大的限制,所以MySQL最新版本中,InnoDB支持了所謂的Online方式建立索引。InnoDB的Online Add Index,首先是Inplace方式建立索引,無需使用臨時表。在遍歷聚簇索引,收集記錄並插入到新索引的過程當中,原表記錄可修改。而修改的記錄保存在Row Log中。當聚簇索引遍歷完畢,並所有插入到新索引以後,重放Row Log中的記錄修改,使得新索引與聚簇索引記錄達到一致狀態。
與Copy Table方式相比,Online Add Index採用的是Inplace方式,無需Copy Table,減小了空間開銷;與此同時,Online Add Index只有在重放Row Log最後一個Block時鎖表,減小了鎖表的時間。與Inplace方式相比,Online Add Index吸取了Inplace方式的優點,卻減小了鎖表的時間。help create index;CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name[index_type]ON tbl_name (index_col_name,...)[index_option][algorithm_option | lock_option] ...index_col_name:col_name [(length)] [ASC | DESC]index_option:KEY_BLOCK_SIZE [=] value| index_type| WITH PARSER parser_name| COMMENT 'string'index_type:USING {BTREE | HASH}create index idx_c on sbtest1(c(20)) ALGORITHM=DEFAULT;create index idx_c on sbtest1(c(20)) ALGORITHM=INPLACE;寫不會阻塞,會先寫到緩存,而後完成以後同步數據;copy的時候會阻塞寫操做create index idx_c on sbtest1(c(20)) ALGORITHM=COPY;innodb_online_alter_log_max_size
若是DDL執行時間很長,期間又產生了大量的dml操做,以致於超過了innodb_online_alter_log_max_size變量所指定的大小,會引發DB_ONLINE_LOG_TOO_BIG錯誤。默認爲128M,特別對於須要拷貝大表的alter操做,考慮臨時加大該值,以此得到更大的日誌緩存空間。
指定InnoDB表的聯機DDL操做期間使用的臨時日誌文件大小的上限(以字節爲單位)。每一個正在建立的索引或要更改的表都有一個這樣的日誌文件。此日誌文件存儲在DDL操做期間在表中插入,更新或刪除的數據。臨時日誌文件在須要時由innodb_sort_buffer_size的值擴展,最大爲innodb_online_alter_log_max_size指定的最大值。若是臨時日誌文件超出大小上限,則ALTER TABLE操做將失敗,而且將回滾全部未提交的併發DML操做。所以,此選項的較大值容許在聯機DDL操做期間發生更多DML,但在表被鎖定以應用日誌中的數據時,還會延長DDL操做結束時的時間段。冗餘索引
根據最左匹配原則,一個索引是另外一個索引的子集;使用pt-duplicate-key-checker檢查select * from sys.schema_redundant_indexes;無用索引:幾乎從未被使用過的索引
pt-index-usage檢查低利用率索引,提供刪除建議
select * from sys.schema_unused_indexes;全表掃描select * from sys.schema_tables_with_full_table_scans;使用索引一、讓MySQL自動選擇select ... from t where ...二、建議選擇:select .. from t use index(idx_name) where ...三、強制索引select ... from t force index(idex_name) where...索引統計表統計信息
show table status ;select * from information_schema.tables;select * from mysql.innodb_table_stats;索引統計信息show index from table;select * from information_schema.STATISTICS;select * from mysql.innodb_index_stats;
innodb_stats_auto_recalc
默認開啓,當修改數據量大於10%,自動更新統計信息;
innodb_stats_persistent
默認開啓,統計信息持久化存儲;當關閉時,統計信息不持久化,每次動態採集,存儲在內存中,重啓實例(須要從新統計),不推薦
innodb_stats_persistent_sample_pages
統計信息持久化存儲時,默認每次採集20個page頁innodb_stats_on_metadata默認禁用,訪問元數據時更新統計信息;iinnodb_stats_transient_sample_pages
動態採集page,默認8個
MySQL -A登陸不會去更新統計信息不接-A的話當表或者分區表比較多的時候登陸會比較慢use database是也須要更新統計信息,因此有時候很慢執行計劃typeALL 掃描全表數據index 遍歷索引range 索引範圍查找ref 使用非惟一索引查找數據fulltext 使用全文索引const 使用主鍵或者惟一索引,且匹配的結果只有一條記錄。system const 鏈接類型的特例,查詢的表爲系統表。possible_keys可能使用的索引,但不必定會使用。查詢涉及到的字段上若存在索引,則該索引將被列出來。當該列爲NULL時就需考慮當前的SQL是否須要優化。key顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示爲NULL。查詢中若使用了覆蓋索引(覆蓋索引:索引的數據覆蓋了須要查詢的全部數據),則該索引僅出如今key列表中extraextra的信息很是豐富,常見的有: 1.Using index 使用覆蓋索引 2.Using where 使用了用where子句來過濾結果集 3.Using filesort 使用文件排序,使用非索引列進行排序時出現,很是消耗性能,儘可能優化。 4.Using temporary 使用了臨時表索引不可用的狀況一、經過索引掃描的記錄數超過20%-30%,可能會變成全表掃描;
二、聯合索引中,第一個索引列使用範圍查詢;(這時用的部分索引)三、聯合索引中,第一個查詢不是最左索引列;四、模糊查詢條件列最左以通配符%開始(覆蓋索引除外);五、兩個獨立索引,其中一個用於檢索,一個用於排序(只能用到一個索引)六、join查詢時,關聯列數據類型(以及字符集)不一致也會致使索引不可用隱式類型轉換u1='123' 不會轉換u1='a' 能夠正常走索引聯合索引
desc select * from t7 where name='zyq';desc select * from t7 where c='abc';![]()
desc select * from t7 where c='zyq' and pad='sdfafadfasfdaf';
desc select * from t7 where c='abc' and name='zyq';