1. 程式人生 > 實用技巧 >MySQL索引的建立和使用

MySQL索引的建立和使用

一、索引

索引是快速查詢的關鍵,MySQL索引的建立對於MySQL的高效執行是很重要的,對於較少的資料量,有沒有索引可能沒什麼影響,但是當資料量較大時,查詢效能會急劇下降,特別是進行條件查詢的時候

二、索引的型別

  • 1、主鍵索引 PRIMARY KEY 主鍵索引是一種特殊的唯一索引,它不允許有空值,一般在建立表的時候建立,而且一個表只能有一個主鍵 建立表的時候建立主鍵
CREATE TABLE test(
id int(0) NOT NULL AUTO_INCREMENT,
hotelName varchar(255) DEFAULT NULL,
PRIMARY KEY('id')
);

使用ALTER命令新增主鍵

ALTER TABLE test ADD PRIMARY KEY('id');
  • 2、普通索引 這是最基本的索引,沒有做任何限制 建立表的時候指定
CREATE TABLE test(
id int(0) NOT NULL AUTO_INCREMENT,
hotelName varchar(255) DEFAULT NULL,
PRIMARY KEY('id'),
INDEX `hotelName`(`hotelName`)
);

使用ALTER命令新增普通索引

ALTER TABLE test ADD INDEX hotelName(hotelName)
  • 3、唯一索引 UNIQUE 唯一索引列的值必須是唯一的,可以有空值,如果是組合索引,那麼列值的組合必須是唯一的 建立表的時候指定
CREATE TABLE test(
id int(0) NOT NULL AUTO_INCREMENT,
hotelName varchar(255) DEFAULT NULL,
PRIMARY KEY('id'),
UNIQUE INDEX `hotelName`(`hotelName`)
);

使用ALTER命令新增唯一索引

ALTER TABLE test ADD UNIQUE hotelName(hotelName)
  • 4、組合索引 就是一個索引包含多個列 使用ALTER命令新增新增組合索引
ALTER TABLE test ADD INDEX indexName(列1, 列2, 列3....)
  • 5、全文索引 FULLTEXT 全文索引也是MyISAM的一個特殊索引型別,主要用於全文索引,InnoDB從Mysql5.6版本開始支援全文索引。 建立表的時候指定
CREATE TABLE test(
id int(0) NOT NULL AUTO_INCREMENT,
hotelName varchar(255) DEFAULT NULL,
PRIMARY KEY('id'),
FULLTEXT INDEX `hotelName`(`hotelName`)
);

使用ALTER命令新增新增全文索引

ALTER TABLE test ADD FULLTEXT (hotelName)

三、建立索引的一般原則

  • 1、對於查詢頻率高的欄位建立索引

索引的主要目的就是為了提升查詢的所讀,所以在查詢頻率高的欄位上要建立索引

  • 2、對排序、分組、聯合查詢頻率高的欄位建立索引

  • 3、索引的數量儘量要少,不要建立不必要的索引

沒建立一個索引都會佔用相應的物理控制元件 過多的索引會導致insert、update、delete語句的執行效率降低

  • 4、如果需要將多列設定為索引時,可以採用多列索引

  • 5、選擇唯一性索引

唯一性索引的值時唯一的,可以更快速的通過該索引來確定某條記錄

  • 6、儘量使用資料量少的索引

如果索引的值很長,那麼查詢速度會受到影響

  • 7、儘量使用字首來索引

如果索引欄位的值很長,最好使用值的字首來索引

  • 8、刪除不在使用或者很少使用的索引

對於一些不經常使用的索引,應當及時的刪除,從而減少索引對更新操作的影響

四、執行計劃 EXPLAIN

通過使用MySQL的執行計劃來檢視sql語句的執行效率,分析執行計劃的各個顯示內容,找出查詢效率低的原因

EXPLAIN SELECT hotelID,c.city FROM hotelInfoApi as h, (SELECT city FROM hotelInfoApi GROUP BY city) as c WHERE h.city=c.city 

  • 執行計劃的id select 查詢的序列號,表示執行的順序
  • id相同,執行順序由上至下
  • id不同,如果是子查詢,id的序號會遞增,id值越大優先順序越高,越先被執行
  • 執行計劃的select_type 查詢的型別,主要用於區分普通查詢、聯合查詢、子查詢等
  • SIMPLE:簡單的select查詢,查詢中不包含子查詢或者union
  • PRIMARY:查詢中包含子查詢,最外層查詢則被標記為primary
  • SUBQUERY/MATERIALIZED:SUBQUERY表示在select或where列表中包含了子查詢,MATERIALIZED:表示 where 後面 in 條件的子查詢
  • UNION:表示 union 中的第二個或後面的 select 語句
  • UNION RESULT: union的結果
  • DERIVED:派生表
  • 執行計劃的table 查詢涉及到的表
  • 直接顯示錶名或者表的別名
  • <unionM,N> 由 ID 為 M,N 查詢 union 產生的結果
  • 由 ID 為 N 查詢產生的結果
  • 執行計劃的type 訪問型別, SQL查詢優化中的一個很重要的指標,結果值從好到壞依次是:system > const > eq_ref > ref > range > index > ALL。
  • system:系統表,少量資料,往往不需要進行磁碟IO
  • const:常量連線
  • eq_ref:主鍵索引(primary key)或者非空唯一索引(unique not null)等值掃描
  • ref:非主鍵非唯一索引等值掃描
  • range:範圍掃描
  • index:索引樹掃描
  • ALL:全表掃描(full table scan)
  • 執行計劃possible_keys 查詢過程中有可能用到的索引

  • 執行計劃key 實際使用的索引,如果為NULL,則沒有使用索引

  • 執行計劃rows 根據表統計資訊或者索引選用情況,大致估算出找到所需的記錄所需讀取的行數

  • 執行計劃filtered 表示返回的行數需讀取行數的百分比,filtered的值越大越好.

  • 執行計劃Extra 額外資訊

  • Using filesort:MySQL 對資料使用一個外部的檔案內容進行了排序,而不是按照表內的索引進行排序讀取。
  • Using temporary:使用臨時表儲存中間結果,也就是說 MySQL 在對查詢結果排序時使用了臨時表,常見於order by 或 group by。
  • Using index:表示 SQL 操作中使用了覆蓋索引(Covering Index),避免了訪問表的資料行,效率高。
  • Using index condition:表示 SQL 操作命中了索引,但不是所有的列資料都在索引樹上,還需要訪問實際的行記錄。
  • Using where:表示 SQL 操作使用了 where 過濾條件。
  • Select tables optimized away:基於索引優化 MIN/MAX 操作或者 MyISAM 儲存引擎優化 COUNT(*) 操作,不必等到執行階段再進行計算,查詢執行計劃生成的階段即可完成優化。
  • Using join buffer(Block Nested Loop):表示 SQL 操作使用了關聯查詢或者子查詢,且需要進行巢狀迴圈計算。

五、慢查詢日誌

MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指執行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。long_query_time的預設值為10,意思是執行10S以上的語句。預設情況下,MySQLl資料庫並不啟動慢查詢日誌,需要我們手動來設定這個引數,當然,如果不是調優需要的話,一般不建議啟動該引數,因為開啟慢查詢日誌會或多或少帶來一定的效能影響。慢查詢日誌支援將日誌記錄寫入檔案,也支援將日誌記錄寫入資料庫表。

  • 檢視是否開啟慢查詢功能
show variables like 'slow_query%';
# slow_query_log 慢查詢開啟狀態
# slow_query_log_file 慢查詢日誌存放的位置(這個目錄需要MySQL的執行帳號的可寫許可權,一般設定為MySQL的資料存放目錄)

show variables like 'long_query_time';
# long_query_time 查詢超過多少秒才記錄

  • 開啟慢查詢 臨時開啟
set global show_query_log='ON';
set global slow_query_log_file='/usr/local/var/mysql/192-slow.log';
set global long_query_time=2;

永久開啟,需要修改配置檔案(mysql.cnf)

[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/var/mysql/192-slow.log
long_query_time = 2

END