本篇內(nèi)容主要講解“MySQL索引優(yōu)化的性能分析和總結(jié)”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“MySQL索引優(yōu)化的性能分析和總結(jié)”吧!
為太康等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及太康網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為網(wǎng)站設(shè)計、做網(wǎng)站、太康網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!
案例分析
我們先簡單了解一下非關(guān)系型數(shù)據(jù)庫和關(guān)系型數(shù)據(jù)庫的區(qū)別。
MongoDB 是 NOSQL 中的一種。NoSQL 的全稱是 Not only SQL,非關(guān)系型數(shù)據(jù)庫。它的特點(diǎn)是性能高,擴(kuò)張性強(qiáng),模式靈活,在高并發(fā)場景表現(xiàn)得尤為突出。但目前它還只是關(guān)系型數(shù)據(jù)庫的補(bǔ)充,它在數(shù)據(jù)的一致性,數(shù)據(jù)的安全性,查詢的復(fù)雜性問題上和關(guān)系型數(shù)據(jù)庫還存在一定差距。
MySQL 是關(guān)系性數(shù)據(jù)庫中的一種,查詢功能強(qiáng),數(shù)據(jù)一致性高,數(shù)據(jù)安全性高,支持二級索引。但性能方面稍遜與 MongoDB,特別是百萬級別以上的數(shù)據(jù),很容易出現(xiàn)查詢慢的現(xiàn)象。這時候需要分析查詢慢的原因,一般情況下是程序員 sql 寫的爛,或者是沒有鍵索引,或者是索引失效等原因?qū)е碌摹?/p>
公司 ERP 系統(tǒng)數(shù)據(jù)庫主要是 MongoDB(最接近關(guān)系型數(shù)據(jù)的 NoSQL),其次是 redis,MySQL 只占很少的部分?,F(xiàn)在又重新使用 MySQL,歸功于阿里巴巴的奇門系統(tǒng)和聚石塔系統(tǒng)??紤]到訂單數(shù)量已經(jīng)是百萬級以上,對 MySQL 的性能分析也就顯得格外重要。
我們先通過兩個簡單的例子來入門。后面會詳細(xì)介紹各個參數(shù)的作用和意義。
說明:需要用到的 sql 已經(jīng)放在了 github 上了,喜歡的同學(xué)可以點(diǎn)一下 star,哈哈。https://github.com/ITDragonBlog/daydayup/tree/master/MySQL/
場景一:訂單導(dǎo)入,通過交易號避免重復(fù)導(dǎo)單
業(yè)務(wù)邏輯:訂單導(dǎo)入時,為了避免重復(fù)導(dǎo)單,一般會通過交易號去數(shù)據(jù)庫中查詢,判斷該訂單是否已經(jīng)存在。
最基礎(chǔ)的 sql 語句
mysql> select * from itdragon_order_list where transaction_id = "81X97310V32236260E";
+-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+
| id | transaction_id | gross | net | stock_id | order_status | descript | finance_descript | create_type | order_level | input_user | input_date |
+-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+
| 10000 | 81X97310V32236260E | 6.6 | 6.13 | 1 | 10 | ok | ok | auto | 1 | itdragon | 2017-08-18 17:01:49 |
+-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+
mysql> explain select * from itdragon_order_list where transaction_id = "81X97310V32236260E";
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | itdragon_order_list | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+
查詢的本身沒有任何問題,在線下的測試環(huán)境也沒有任何問題??墒牵δ芤坏┥暇€,查詢慢的問題就迎面而來。幾百上千萬的訂單,用全表掃描??。亢?
怎么知道該 sql 是全表掃描呢?通過 explain 命令可以清楚 MySQL 是如何處理 sql 語句的。打印的內(nèi)容分別表示:
id : 查詢序列號為 1。
select_type : 查詢類型是簡單查詢,簡單的 select 語句沒有 union 和子查詢。
table : 表是 itdragon_order_list。
partitions : 沒有分區(qū)。
type : 連接類型,all 表示采用全表掃描的方式。
possible_keys : 可能用到索引為 null。
key : 實(shí)際用到索引是 null。
key_len : 索引長度當(dāng)然也是 null。
ref : 沒有哪個列或者參數(shù)和 key 一起被使用。
Extra : 使用了 where 查詢。
因為數(shù)據(jù)庫中只有三條數(shù)據(jù),所以 rows 和 filtered 的信息作用不大。這里需要重點(diǎn)了解的是 type 為 ALL,全表掃描的性能是最差的,假設(shè)數(shù)據(jù)庫中有幾百萬條數(shù)據(jù),在沒有索引的幫助下會異常卡頓。
初步優(yōu)化:為 transaction_id 創(chuàng)建索引
mysql> create unique index idx_order_transaID on itdragon_order_list (transaction_id);
mysql> explain select * from itdragon_order_list where transaction_id = "81X97310V32236260E";
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | itdragon_order_list | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | NULL |
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+
這里創(chuàng)建的索引是唯一索引,而非普通索引。
唯一索引打印的 type 值是 const。表示通過索引一次就可以找到。即找到值就結(jié)束掃描返回查詢結(jié)果。
普通索引打印的 type 值是 ref。表示非唯一性索引掃描。找到值還要繼續(xù)掃描,直到將索引文件掃描完為止。(這里沒有貼出代碼),顯而易見,const 的性能要遠(yuǎn)高于 ref。并且根據(jù)業(yè)務(wù)邏輯來判斷,創(chuàng)建唯一索引是合情合理的。
再次優(yōu)化:覆蓋索引
mysql> explain select transaction_id from itdragon_order_list where transaction_id = "81X97310V32236260E";
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | itdragon_order_list | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | Using index |
+----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+
這里將 select * from 改為了 select transaction_id from 后,Extra 顯示 Using index,表示該查詢使用了覆蓋索引,這是一個非常好的消息,說明該 sql 語句的性能很好。若提示的是 Using filesort(使用內(nèi)部排序) 和 Using temporary(使用臨時表) 則表明該 sql 需要立即優(yōu)化了。
根據(jù)業(yè)務(wù)邏輯來的,查詢結(jié)構(gòu)返回 transaction_id 是可以滿足業(yè)務(wù)邏輯要求的。
場景二:訂單管理頁面,通過訂單級別和訂單錄入時間排序
業(yè)務(wù)邏輯:優(yōu)先處理訂單級別高,錄入時間長的訂單。
既然是排序,首先想到的應(yīng)該是 order by, 還有一個可怕的 Using filesort 等著你。
最基礎(chǔ)的 sql 語句
mysql> explain select * from itdragon_order_list order by order_level,input_date;
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
| 1 | SIMPLE | itdragon_order_list | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
首先,采用全表掃描就不合理,還使用了文件排序 Using filesort,更加拖慢了性能。
MySQL 在 4.1 版本之前文件排序是采用雙路排序的算法,由于兩次掃描磁盤,I/O 耗時太長。后優(yōu)化成單路排序算法。其本質(zhì)就是用空間換時間,但如果數(shù)據(jù)量太大,buffer 的空間不足,會導(dǎo)致多次 I/O 的情況。其效果反而更差。與其找運(yùn)維同事修改 MySQL 配置,還不如自己乖乖地建索引。
初步優(yōu)化:為 order_level,input_date 創(chuàng)建復(fù)合索引
mysql> create index idx_order_levelDate on itdragon_order_list (order_level,input_date);
mysql> explain select * from itdragon_order_list order by order_level,input_date;
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
| 1 | SIMPLE | itdragon_order_list | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort |
+----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+
創(chuàng)建復(fù)合索引后你會驚奇的發(fā)現(xiàn),和沒創(chuàng)建索引一樣???都是全表掃描,都用到了文件排序。是索引失效?還是索引創(chuàng)建失敗?我們試著看看下面打印情況
mysql> explain select order_level,input_date from itdragon_order_list order by order_level,input_date;
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+
| 1 | SIMPLE | itdragon_order_list | NULL | index | NULL | idx_order_levelDate | 68 | NULL | 3 | 100 | Using index |
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+
將 select * from 換成了 select order_level,input_date from 后。type 從 all 升級為 index,表示(full index scan)全索引文件掃描,Extra 也顯示使用了覆蓋索引。可是不對?。。。?!檢索雖然快了,但返回的內(nèi)容只有 order_level 和 input_date 兩個字段,讓業(yè)務(wù)同事怎么用?難道把每個字段都建一個復(fù)合索引?
MySQL 沒有這么笨,可以使用 force index 強(qiáng)制指定索引。在原來的 sql 語句上修改 force index(idx_order_levelDate) 即可。
mysql> explain select * from itdragon_order_list force index(idx_order_levelDate) order by order_level,input_date;
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+
| 1 | SIMPLE | itdragon_order_list | NULL | index | NULL | idx_order_levelDate | 68 | NULL | 3 | 100 | NULL |
+----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+
再次優(yōu)化:訂單級別真的要排序么?
其實(shí)給訂單級別排序意義并不大,給訂單級別添加索引意義也不大。因為 order_level 的值可能只有,低,中,高,加急,這四種。對于這種重復(fù)且分布平均的字段,排序和加索引的作用不大。
我們能否先固定 order_level 的值,然后再給 input_date 排序?如果查詢效果明顯,是可以推薦業(yè)務(wù)同事使用該查詢方式。
mysql> explain select * from itdragon_order_list where order_level=3 order by input_date;
+----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE | itdragon_order_list | NULL | ref | idx_order_levelDate | idx_order_levelDate | 5 | const | 1 | 100 | Using index condition |
+----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+
和之前的 sql 比起來,type 從 index 升級為 ref(非唯一性索引掃描)。索引的長度從 68 變成了 5,說明只用了一個索引。ref 也是一個常量。Extra 為 Using index condition 表示自動根據(jù)臨界值,選擇索引掃描還是全表掃描??偟膩碚f性能遠(yuǎn)勝于之前的 sql。
上面兩個案例只是快速入門,我們需嚴(yán)記一點(diǎn):優(yōu)化是基于業(yè)務(wù)邏輯來的。絕對不能為了優(yōu)化而擅自修改業(yè)務(wù)邏輯。如果能修改當(dāng)然是最好的。
索引簡介
官方定義:索引(Index) 是幫助 MySQL 高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
大家一定很好奇,索引為什么是一種數(shù)據(jù)結(jié)構(gòu),它又是怎么提高查詢的速度?我們拿最常用的二叉樹來分析索引的工作原理??聪旅娴膱D片:
創(chuàng)建索引的優(yōu)勢:
1. 提高數(shù)據(jù)的檢索速度,降低數(shù)據(jù)庫 IO 成本:使用索引的意義就是通過縮小表中需要查詢的記錄的數(shù)目從而加快搜索的速度。
2. 降低數(shù)據(jù)排序的成本,降低 CPU 消耗:索引之所以查的快,是因為先將數(shù)據(jù)排好序,若該字段正好需要排序,則真好降低了排序的成本。
創(chuàng)建索引的劣勢:
1. 占用存儲空間:索引實(shí)際上也是一張表,記錄了主鍵與索引字段,一般以索引文件的形式存儲在磁盤上。
2. 降低更新表的速度:表的數(shù)據(jù)發(fā)生了變化,對應(yīng)的索引也需要一起變更,從而減低的更新速度。否則索引指向的物理數(shù)據(jù)可能不對,這也是索引失效的原因之一。
3. 優(yōu)質(zhì)索引創(chuàng)建難:索引的創(chuàng)建并非一日之功,也并非一直不變。需要頻繁根據(jù)用戶的行為和具體的業(yè)務(wù)邏輯去創(chuàng)建最佳的索引。
索引分類
我們常說的索引一般指的是 BTree(多路搜索樹)結(jié)構(gòu)組織的索引。其中還有聚合索引,次要索引,復(fù)合索引,前綴索引,唯一索引,統(tǒng)稱索引,當(dāng)然除了 B + 樹外,還有哈希索引(hash index)等。
單值索引:一個索引只包含單個列,一個表可以有多個單列索引
唯一索引:索引列的值必須唯一,但允許有空值
復(fù)合索引:一個索引包含多個列,實(shí)際開發(fā)中推薦使用
實(shí)際開發(fā)中推薦使用復(fù)合索引,并且單表創(chuàng)建的索引個數(shù)建議不要超過五個
基本語法:
創(chuàng)建:
create [unique] index indexName on tableName (columnName...)
alter tableName add [unique] index [indexName] on (columnName...)
刪除:
drop index [indexName] on tableName
查看:
show index from tableName
哪些情況需要建索引:
1. 主鍵,唯一索引
2. 經(jīng)常用作查詢條件的字段需要創(chuàng)建索引
3. 經(jīng)常需要排序、分組和統(tǒng)計的字段需要建立索引
4. 查詢中與其他表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引
哪些情況不要建索引:
1. 表的記錄太少,百萬級以下的數(shù)據(jù)不需要創(chuàng)建索引
2. 經(jīng)常增刪改的表不需要創(chuàng)建索引
3. 數(shù)據(jù)重復(fù)且分布平均的字段不需要創(chuàng)建索引,如 true,false 之類。
4. 頻發(fā)更新的字段不適合創(chuàng)建索引
5. where 條件里用不到的字段不需要創(chuàng)建索引
性能分析
MySQL 自身瓶頸
MySQL 自身參見的性能問題有磁盤空間不足,磁盤 I/O 太大,服務(wù)器硬件性能低。
1. CPU:CPU 在飽和的時候一般發(fā)生在數(shù)據(jù)裝入內(nèi)存或從磁盤上讀取數(shù)據(jù)時候
2. IO:磁盤 I/O 瓶頸發(fā)生在裝入數(shù)據(jù)遠(yuǎn)大于內(nèi)存容量的時候
3. 服務(wù)器硬件的性能瓶頸:top,free,iostat 和 vmstat 來查看系統(tǒng)的性能狀態(tài)
explain 分析 sql 語句
使用 explain 關(guān)鍵字可以模擬優(yōu)化器執(zhí)行 sql 查詢語句,從而得知 MySQL 是如何處理 sql 語句。
+----+-------------+-------+------------+------+---------------+-----+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-----+---------+------+------+----------+-------+
id
select 查詢的序列號,包含一組可以重復(fù)的數(shù)字,表示查詢中執(zhí)行 sql 語句的順序。一般有三種情況:
第一種:id 全部相同,sql 的執(zhí)行順序是由上至下;
第二種:id 全部不同,sql 的執(zhí)行順序是根據(jù) id 大的優(yōu)先執(zhí)行;
第三種:id 既存在相同,又存在不同的。先根據(jù) id 大的優(yōu)先執(zhí)行,再根據(jù)相同 id 從上至下的執(zhí)行。
select_type
select 查詢的類型,主要是用于區(qū)別普通查詢,聯(lián)合查詢,嵌套的復(fù)雜查詢
simple:簡單的 select 查詢,查詢中不包含子查詢或者 union
primary:查詢中若包含任何復(fù)雜的子查詢,最外層查詢則被標(biāo)記為 primary
subquery:在 select 或 where 列表中包含了子查詢
derived:在 from 列表中包含的子查詢被標(biāo)記為 derived(衍生)MySQL 會遞歸執(zhí)行這些子查詢,把結(jié)果放在臨時表里。
union:若第二個 select 出現(xiàn)在 union 之后,則被標(biāo)記為 union,若 union 包含在 from 子句的子查詢中,外層 select 將被標(biāo)記為:derived
union result:從 union 表獲取結(jié)果的 select
partitions
表所使用的分區(qū),如果要統(tǒng)計十年公司訂單的金額,可以把數(shù)據(jù)分為十個區(qū),每一年代表一個區(qū)。這樣可以大大的提高查詢效率。
type
這是一個非常重要的參數(shù),連接類型,常見的有:all , index , range , ref , eq_ref , const , system , null 八個級別。性能從最優(yōu)到最差的排序:system > const > eq_ref > ref > range > index > all。
對 java 程序員來說,若保證查詢至少達(dá)到 range 級別或者最好能達(dá)到 ref 則算是一個優(yōu)秀而又負(fù)責(zé)的程序員。
all:(full table scan)全表掃描無疑是最差,若是百萬千萬級數(shù)據(jù)量,全表掃描會非常慢。
index:(full index scan)全索引文件掃描比 all 好很多,畢竟從索引樹中找數(shù)據(jù),比從全表中找數(shù)據(jù)要快。
range:只檢索給定范圍的行,使用索引來匹配行。范圍縮小了,當(dāng)然比全表掃描和全索引文件掃描要快。sql 語句中一般會有 between,in,>,< 等查詢。
ref:非唯一性索引掃描,本質(zhì)上也是一種索引訪問,返回所有匹配某個單獨(dú)值的行。比如查詢公司所有屬于研發(fā)團(tuán)隊的同事,匹配的結(jié)果是多個并非唯一值。
eq_ref:唯一性索引掃描,對于每個索引鍵,表中有一條記錄與之匹配。比如查詢公司的 CEO,匹配的結(jié)果只可能是一條記錄,
const:表示通過索引一次就可以找到,const 用于比較 primary key 或者 unique 索引。因為只匹配一行數(shù)據(jù),所以很快,若將主鍵至于 where 列表中,MySQL 就能將該查詢轉(zhuǎn)換為一個常量。
system:表只有一條記錄(等于系統(tǒng)表),這是 const 類型的特列,平時不會出現(xiàn),了解即可
possible_keys
顯示查詢語句可能用到的索引 (一個或多個或為 null),不一定被查詢實(shí)際使用。僅供參考使用。
key
顯示查詢語句實(shí)際使用的索引。若為 null,則表示沒有使用索引。
key_len
顯示索引中使用的字節(jié)數(shù),可通過 key_len 計算查詢中使用的索引長度。在不損失精確性的情況下索引長度越短越好。key_len 顯示的值為索引字段的最可能長度,并非實(shí)際使用長度,即 key_len 是根據(jù)表定義計算而得,并不是通過表內(nèi)檢索出的。
ref
顯示索引的哪一列或常量被用于查找索引列上的值。
rows
根據(jù)表統(tǒng)計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數(shù),值越大越不好。
extra
Using filesort: 說明 MySQL 會對數(shù)據(jù)使用一個外部的索引排序,而不是按照表內(nèi)的索引順序進(jìn)行讀取。MySQL 中無法利用索引完成的排序操作稱為 “文件排序” 。出現(xiàn)這個就要立刻優(yōu)化 sql。
Using temporary: 使用了臨時表保存中間結(jié)果,MySQL 在對查詢結(jié)果排序時使用臨時表。常見于排序 order by 和 分組查詢 group by。 出現(xiàn)這個更要立刻優(yōu)化 sql。
Using index: 表示相應(yīng)的 select 操作中使用了覆蓋索引(Covering index),避免訪問了表的數(shù)據(jù)行,效果不錯!如果同時出現(xiàn) Using where,表明索引被用來執(zhí)行索引鍵值的查找。如果沒有同時出現(xiàn) Using where,表示索引用來讀取數(shù)據(jù)而非執(zhí)行查找動作。
覆蓋索引(Covering Index) :也叫索引覆蓋,就是 select 的數(shù)據(jù)列只用從索引中就能夠取得,不必讀取數(shù)據(jù)行,MySQL 可以利用索引返回 select 列表中的字段,而不必根據(jù)索引再次讀取數(shù)據(jù)文件。
Using index condition: 在 5.6 版本后加入的新特性,優(yōu)化器會在索引存在的情況下,通過符合 RANGE 范圍的條數(shù) 和 總數(shù)的比例來選擇是使用索引還是進(jìn)行全表遍歷。
Using where: 表明使用了 where 過濾。
Using join buffer: 表明使用了連接緩存。
impossible where: where 語句的值總是 false,不可用,不能用來獲取任何元素。
distinct: 優(yōu)化 distinct 操作,在找到第一匹配的元組后即停止找同樣值的動作。
filtered
一個百分比的值,和 rows 列的值一起使用,可以估計出查詢執(zhí)行計劃 (QEP) 中的前一個表的結(jié)果集,從而確定 join 操作的循環(huán)次數(shù)。小表驅(qū)動大表,減輕連接的次數(shù)。
通過 explain 的參數(shù)介紹,我們可以得知:
1. 表的讀取順序 (id)
2. 數(shù)據(jù)讀取操作的操作類型 (type)
3. 哪些索引被實(shí)際使用 (key)
4. 表之間的引用 (ref)
5. 每張表有多少行被優(yōu)化器查詢 (rows)
性能下降的原因
從程序員的角度
1. 查詢語句寫的不好
2. 沒建索引,索引建的不合理或索引失效
3. 關(guān)聯(lián)查詢有太多的 join
從服務(wù)器的角度
1. 服務(wù)器磁盤空間不足
2. 服務(wù)器調(diào)優(yōu)配置參數(shù)設(shè)置不合理
總結(jié)
1. 索引是排好序且快速查找的數(shù)據(jù)結(jié)構(gòu)。其目的是為了提高查詢的效率。
2. 創(chuàng)建索引后,查詢數(shù)據(jù)變快,但更新數(shù)據(jù)變慢。
3. 性能下降的原因很可能是索引失效導(dǎo)致。
4. 索引創(chuàng)建的原則,經(jīng)常查詢的字段適合創(chuàng)建索引,頻繁需要更新的數(shù)據(jù)不適合創(chuàng)建索引。
5. 索引字段頻繁更新,或者表數(shù)據(jù)物理刪除容易造成索引失效。
6. 擅用 explain 分析 sql 語句
7. 除了優(yōu)化 sql 語句外,還可以優(yōu)化表的設(shè)計。如盡量做成單表查詢,減少表之間的關(guān)聯(lián)。設(shè)計歸檔表等。
到此,相信大家對“MySQL索引優(yōu)化的性能分析和總結(jié)”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!