索引
索引是特殊數據結構:定義在查找時作為查找條件的字段,索引實現在存儲引擎。
- 索引可以降低服務需要掃描的數據量,減少了IO次數
- 索引可以幫助服務器避免排序和使用臨時表
- 索引可以幫助將隨機I/O轉為順序I/O
- 但是占用額外空間,影響插入速度
索引類型
B + Tree 索引:順序存儲,每一個葉子節點到根的距離都是相同的,左前綴索引,適合查詢范圍類的數據;
- 適合使用B-Tree索引的查詢類型
- - 全值匹配
- - 匹配最左前綴
- - 匹配范圍值
- - 精確匹配某一列並范圍匹配另一列(復合索引)
- - 只訪問索引的查詢
- 不適合使用B-tree索引的查詢類型
- - 不從最左列開始
- - 不能跳過索引中的列
- - 如果查詢中某個列是為范圍查詢那么右側的列無法再使用索引優化查詢
Hash索引:基於哈希表,構建出鍵值對的索引,特別適用於精確匹配索引中的索引列,只支持等值比較查詢(IN,=,<>);不適合於順序查詢,不支持模糊匹配;只有Memory存儲引擎支持顯式Hash索引
空間索引(R - Tree):只有MyISAM支持空間索引
全文索引(FULL TEXT):在文本中查找關鍵詞
高性能索引策略:
- 獨立使用列,盡量避免其參與運算
- 使用左前綴索引:索引構建於字段的左側的多少字符要通過索引選擇性來評估;索引選擇性:不重復的索引值和數據表的記錄總數的比值
- 多列索引:AND操作時更適合使用多列索引,而非為每個列創建單獨的索引
- 選擇合適的索引列次序:無排序和分組時,將選擇性最高放左側
索引的優化建議
- 只要列中含有NULL值,就最好不要在此例設置索引,復合索引如果有NULL值,此列在使用時也不會使用索引
- 盡量使用短索引,如果可以,應該制定一個前綴長度
- 對於經常在where子句使用的列,最好設置索引
- 對於有多個列where或者order by子句,應該建立復合索引
- 對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引
- 盡量不要在列上進行運算(函數操作和表達式操作)
- 盡量不要使用not in和<>操作
- 多表連接時,盡量小表驅動大表,即小表 join 大表
- 在千萬級分頁時使用limit
- 對於經常使用的查詢,可以開啟緩存
- 大部分情況連接效率遠大於子查詢
管理索引
創建索引
CREATE INDEX index_name ON tbl_name (index_col_name,...);
MariaDB [hellodb]> CREATE INDEX index_name ON students(name); #創建簡單索引 MariaDB [hellodb]> CREATE INDEX index_name_age ON students(name,age); #創建復合索引
示例
添加一個索引/創建一個存粹的索引
MariaDB [testdb]> alter table testtb add index ind_name(name);
創建一個聯合索引
MariaDB [testdb]> create index ind_id_name on testtb1 (id,name); MariaDB [testdb]> create index ind_id_name on testtb1 (id,name(20));
查看索引
SHOW INDEXES FROM [db_name.]tbl_name;
MariaDB [hellodb]> SHOW INDEX FROM students\G
刪除索引
DROP INDEX index_name ON tbl_name;
MariaDB [hellodb]> DROP INDEX index_name ON students;
重建索引 ***(mariadb中的innodb存儲引擎不支持重建索引)
MariaDB [testdb]> repair table table_name quick;
優化表空間
MariaDB [hellodb]> OPTIMIZE TABLE students;
查看索引使用的情況
啟用記錄索引使用情況:
SET GLOBAL userstat=1;
查看索引使用情況:
SHOW INDEX_STATISTICS;
我們可以統計不經常使用的索引從而進行優化
EXPLAIN命令
通過EXPLAIN來分析索引的有效性:EXPLAIN SELECT clause
,獲取查詢執行計划信息,用來查看查詢優化器如何執行查詢
MariaDB [hellodb]> EXPLAIN SELECT name FROM students WHERE name = 'Lin Daiyu'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: students type: ref possible_keys: index_name_age key: index_name_age key_len: 152 ref: const rows: 1 Extra: Using where; Using index
id:當前查詢語句中,每個SELECT語句的編號;復雜類型的查詢有三種:簡單子查詢、用於FROM子句中的子查詢、聯合查詢(UNION,注意:UNION查詢的分析結果會出現一個額外匿名臨時表)
select_type:
- SIMPLE :簡單查詢
- SUBQUERY: 簡單子查詢
- PRIMARY:最外面的SELECT
- DERIVED: 用於FROM中的子查詢
- UNION:UNION語句的第一個之后的SELECT語句
- UNION RESULT: 匿名臨時表
table:SELECT語句關聯到的表
type:關聯類型或訪問類型,即MySQL決定的如何去查詢表中的行的方式,以下順序,性能從低到高
- ALL: 全表掃描
- index:根據索引的次序進行全表掃描;如果在Extra列出現“Using index”表示了使用覆蓋索引,而非全表掃描
- range:有范圍限制的根據索引實現范圍掃描;掃描位置始於索引中的某一點,結束於另一點
- ref: 根據索引返回表中匹配某單個值的所有行
- eq_ref:僅返回一個行,但與需要額外與某個參考值做比較
- const, system: 直接返回單個行
possible_keys:查詢可能會用到的索引
key: 查詢中使用到的索引
key_len: 在索引使用的字節數
ref: 在利用key字段所表示的索引完成查詢時所用的列或某常量值
rows:MySQL估計為找所有的目標行而需要讀取的行數
Extra:額外信息
- Using index:MySQL將會使用覆蓋索引,以避免訪問表
- Using where:MySQL服務器將在存儲引擎檢索后,再進行一次過濾
- Using temporary:MySQL對結果排序時會使用臨時表
- Using filesort:對結果使用一個外部索引排序