索引就比如一本書的目錄,它會讓你更快的找到內容;mysql
讓獲取的數據更有目的性,從而提升數據庫檢索數據的性能;sql
索引創建在表的列上(字段)。數據庫
數據庫索引的設計原則:緩存
爲了使索引的使用效率更高,在建立索引時,必須考慮在哪些字段上建立索引和建立什麼類型的索引。服務器
那麼索引設計原則又是怎樣的?運維
1.選擇惟一性索引函數
惟一性索引的值是惟一的,能夠更快速的經過該索引來肯定某條記錄。性能
例如,學生表中學號是具備惟一性的字段。爲該字段創建惟一性索引能夠很快的肯定某個學生的信息。優化
若是使用姓名的話,可能存在同名現象,從而下降查詢速度。ui
2.爲常常須要排序、分組和聯合操做的字段創建索引
常常須要ORDER BY、GROUP BY、DISTINCT和UNION等操做的字段,排序操做會浪費不少時間。
若是爲其創建索引,能夠有效地避免排序操做。
3.爲常做爲查詢條件的字段創建索引
若是某個字段常常用來作查詢條件,那麼該字段的查詢速度會影響整個表的查詢速度。所以,
爲這樣的字段創建索引,能夠提升整個表的查詢速度。
4.限制索引的數目
索引的數目不是越多越好。每一個索引都須要佔用磁盤空間,索引越多,須要的磁盤空間就越大。
修改表時,對索引的重構和更新很麻煩。越多的索引,會使更新表變得很浪費時間。
5.儘可能使用數據量少的索引
若是索引的值很長,那麼查詢的速度會受到影響。例如,對一個CHAR(100)類型的字段進行全文
檢索須要的時間確定要比對CHAR(10)類型的字段須要的時間要多。
6.儘可能使用前綴來索引
若是索引字段的值很長,最好使用值的前綴來索引。例如,TEXT和BLOG類型的字段,進行全文檢索
會很浪費時間。若是隻檢索字段的前面的若干個字符,這樣能夠提升檢索速度。
7.刪除再也不使用或者不多使用的索引
表中的數據被大量更新,或者數據的使用方式被改變後,原有的一些索引可能再也不須要。數據庫管理
員應當按期找出這些索引,將它們刪除,從而減小索引對更新操做的影響。
8.小表不該創建索引;
包含大量的列而且不須要搜索非空值的時候能夠考慮不建索引
主鍵索引:只能有一個主鍵。
列的內容是惟一值
表建立的時候至少要有一個主鍵索引,最好和業務無關。
主鍵索引的創建,是在規範化建立表的時候就自動添加了
mysql> create table test(id int(4) not null auto_increment,name char(20) not null,primary key (id)); Query OK, 0 rows affected (0.02 sec) mysql> desc test; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | name | char(20) | NO | | NULL | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
PRI就表明主鍵索引
alter table test change id id int(4) primary key not null auto_increment;
加快查詢速度,工做中優化數據庫的關鍵。
在合適的列上創建索引,讓數據查詢更高效。
建立格式:
alter table 表名 add index 索引名(列名);
create index 索引名 on 表名(列名);
實例(MUL就表明是普通索引):
mysql> alter table test1 add key name_idx(name); Query OK, 0 rows affected (0.04 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc test1; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(10) | YES | | NULL | | | name | varchar(20) | YES | MUL | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
普通索引建立的條件
一、查詢需求多的 (業務邏輯中,where條件後常常查詢的條件)
二、惟一值多的列
(1)統計下總行數
(2)計算不重複的行數量
查看錶的惟一值數量:
select count(*) from mysql.user; select count(distinct user) from mysql.user; select count(distinct user,host) from mysql.user;
distinct通常是用來去除查詢結果中的重複記錄的
根據字段的前N個字符創建索引
就是若是想作索引的一些字符過多,而後就可使用前綴索引,之前幾個字符作索引
create index name_idx on test(name(8)); show index from test\G
實例
mysql> create index name_idx on test(name(2)); Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc test; +-------+----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+----------------+ | id | int(4) | NO | PRI | NULL | auto_increment | | name | char(20) | NO | MUL | NULL | | +-------+----------+------+-----+---------+----------------+ 2 rows in set (0.00 sec)
就是以表中的多個列作索引,把最經常使用來做爲條件查詢的列放在前面。
alter table ppp add key name_sex_idx(name,age);
內容是惟一的,但不是主鍵,是在主鍵上作的索引,除了惟一索引,其他的能夠說全是普通索引。
create unique index index_name on tese(name);
alter table ppp add unique key age_uidx(age);
刪除索引實例
mysql> alter table test1 drop index name_idx; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc test1; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | id | int(10) | YES | MUL | NULL | | | name | varchar(20) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
desc 表名 show index from 表名\G
使用的sql語句:explain 查詢執行計劃
id | select_type | table |type| possible_keys | key| key_len |ref|rows | Extra
explain顯示了mysql如何使用索引來處理select語句以及鏈接表。能夠幫助選擇更好的索引和寫出更優化的查詢語句。
使用方法,在select語句前加上explain就能夠了:
mysql> explain select id,name from test where name='baba'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: test type: ref possible_keys: ind_name key: ind_name key_len: 60 ref: const rows: 1 Extra: Using where; Using index 1 row in set (0.00 sec) ++++++++++++++++++++++++++++
explain select SQL_NO_CACHE * from test where name='baba'\G
SQL_NO_CACHE的做用是禁止緩存查詢結果。
SELECT識別符。這是SELECT查詢序列號。這個不重要,查詢序號即爲sql語句執行的順序
示查詢中每一個select子句的類型
select類型,它有如下幾種值:
輸出的行所用的表
鏈接類型。有多個參數,先從最佳類型到最差類型介紹,很重要
表示MySQL在表中找到所需行的方式,又稱「訪問類型」,常見類型以下:
ALL、index、range、ref、eq_ref、const、system、NULL
從左到右,性能從最差到最好
system 表僅有一行,這是const類型的特列,平時不會出現,這個也能夠忽略不計
const 表最多有一個匹配行,const用於比較primary key 或者unique索引。由於只匹配一行數據,因此很快。記住必定是用到primary key 或者unique,而且只檢索出兩條數據的 狀況下才會是const,能夠理解爲const是最優化的
指出MySQL能使用哪一個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用
顯示MySQL在查詢中實際使用的索引,
若沒有使用索引,顯示爲NULL
表示索引中使用的字節數,可經過該列計算查詢中使用的索引的長度(key_len顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的)
表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值
表示MySQL根據表統計信息及索引選用狀況,估算的找到所需的記錄所須要讀取的行數
包含不適合在其餘列中顯示但十分重要的額外信息
a. Using index
該值表示相應的select操做中使用了覆蓋索引(Covering Index)
b. Using where
表示mysql服務器將在存儲引擎檢索行後再進行過濾。許多where條件裏涉及索引中的列,當(而且若是)它讀取索引時,就能被存儲引擎檢驗,所以不是全部帶where字句的查詢都會顯示"Using where"。有時"Using where"的出現就是一個暗示:查詢可受益與不一樣的索引。
c. Using temporary
表示MySQL須要使用臨時表來存儲結果集,常見於排序和分組查詢
d. Using filesort
MySQL中沒法利用索引完成的排序操做稱爲「文件排序」
Using join buffer
該值強調了在獲取鏈接條件時沒有使用索引,
而且須要鏈接緩衝區來存儲中間結果。
若是出現了這個值,那應該注意,根據查詢的具體狀況可能須要添加索引來改進能。
f. Impossible where
這個值強調了where語句會致使沒有符合條件的行。
I. Index merges
當MySQL 決定要在一個給定的表上使用超過一個索引的時候,就會出現如下格式中的一個,詳細說明使用的索引以及合併的類型。
一、把一個大的不使用索引的SQL語句按照功能進行拆分
二、長的SQL語句沒法使用索引,能不能變成2條短的SQL語句讓它分別使用上索引
三、對SQL語句功能的拆分和修改
四、減小「爛」SQL
由運維(DBA)和開發交流(確認),共同肯定如何改,最終由DBA執行
五、制定開發流程
走不走索引的決定權在優化器上:
一、集羣因子過大,可能不走索引
二、未來結果集的條目佔總數據量的30%的時候,優化器就以爲走全表掃描計劃更好(where)
三、默認的order by單獨使用的時候,優化器也以爲全變掃面更好(where和limit)
四、子查詢儘可能避免 union或者union all
五、select 使用了不合理的條件或功能(沒有where 邏輯計算符號 運算符號+-*/ 函數)
六、帶有 select * 可能不走索引
七、where條件中有like 而且'%a%',能夠支持'a%',可是不必定
八、沒有查詢條件,或者查詢條件沒有創建索引
九、索引自己失效
十、對小表查詢
十一、統計數據不真實
十二、CBO計算走索引花費過大的狀況。其實也包含了上面的狀況,這裏指的是表佔有的block要比索引小。
1三、隱式轉換致使索引失效.這一點應當引發重視.也是開發中常常會犯的錯誤. 因爲表的字段tel_num定義爲varchar2(20),但在查詢時把該字段做爲number類型以where條件傳給數據庫,這樣會致使索引失效.
錯誤的例子:select * from test where tel_nume=13333333333;
正確的例子:select * from test where tel_nume='13333333333';
1四、not in ,not exist.
1五、in 儘可能改爲 union
1六、當變量採用的是times變量,而表的字段採用的是date變量時.或相反狀況。
1七、B-tree索引is null不會走,is not null會走,位圖索引 is null,is not null 都會走
1八、聯合索引 is not null 只要在創建的索引列(不分前後)都會走, in null時 必需要和創建索引第一列一塊兒使用,當創建索引第一位置條件是is null 時,其餘創建索引的列能夠是is null(但必須在全部列 都知足is null的時候),或者=一個值; 當創建索引的第一位置是=一個值時,其餘索引列能夠是任何狀況(包括is null =一個值),以上兩種狀況索引都會走。其餘狀況不會走。