一、索引
索引是快速查詢的關鍵,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