ä»ä¹æ¯æ§è¡è®¡å
æ ¹æ®è¡¨ãåãç´¢å¼åWHEREåå¥ä¸çæ¡ä»¶ç详ç»ä¿¡æ¯ï¼MySQLä¼åå¨èèäºè®¸å¤ææ¯æ¥ææå°æ§è¡SQLæ¥è¯¢ä¸æ¶åçæ¥æ¾ã对ä¸ä¸ªå·¨å¤§è¡¨çæ¥è¯¢å¯ä»¥å¨ä¸è¯»åææè¡çæ åµä¸æ§è¡ï¼æ¶åå¤ä¸ªè¡¨çèæ¥å¯ä»¥å¨ä¸æ¯è¾æ¯ä¸ªè¡ç»åçæ åµä¸æ§è¡ããä¼åå¨éæ©æ§è¡ææææ¥è¯¢çæä½éç§°ä¸ºâæ¥è¯¢æ§è¡è®¡å(query execution plan)âï¼ä¹ç§°ä¸ºEXPLAIN计åãã
æ§è¡è®¡åè½åä»ä¹
éè¿æ§è¡è®¡åæä»¬å¯ä»¥ç¥éMySQL æ¯å¦ä½å¤çä½ ç SQL è¯å¥çãåææ¥è¯¢è¯å¥ææ¯è¡¨ç»æçæ§è½ç¶é¢ï¼æ»çæ¥è¯´éè¿ EXPLAIN æä»¬å¯ä»¥å以ä¸äºæ ï¼
- æ¥ç表ç读å顺åº
- æ¥çæ°æ®è¯»åæä½çæä½ç±»å
- æ¥çåªäºç´¢å¼å¯ä»¥ä½¿ç¨
- æ¥çç´¢å¼è¢«å®é 使ç¨
- è·å表ä¹é´çå¼ç¨
- æ¯å¼ 表æå¤å°è¡è¢«ä¼å卿¥è¯¢
æ§è¡è®¡åè¯æ³
æ§è¡è®¡åå¯ä»¥éè¿ ãEXPLAINã ããDESCRIBEãããDESCãå ³é®åæ¥æ¥è¯¢çï¼ä½æ¯ä¸è¬ä¼ä½¿ç¨ãEXPLAINãè¿è¡æ¥è¯¢ï¼ãDESCRIBEã主è¦ç¨äºæ¥è¯¢è¡¨ç»æãEXPLAIN为SELECTè¯å¥ä¸ä½¿ç¨çæ¯ä¸ªè¡¨è¿åä¸è¡ä¿¡æ¯ï¼å®æç §MySQLå¨å¤çè¯å¥æ¶è¯»å表ç顺åºååºè¾åºä¸ç表ã
EXPLAINè¯æ³å¦ä¸ï¼
{EXPLAIN | DESCRIBE | DESC}
[explain_type]
{explainable_stmt}
explain_type: {
EXTENDED
| PARTITIONS
| FORMAT = format_name
}
format_name: {
TRADITIONAL
| JSON
| TREE
}
explainable_stmt: {
SELECT statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement
}
åæ®µè§£éï¼
- explain_typeï¼å¯é项ãexplain_typeæä»¥ä¸ä¸ä¸ªé项 EXTENDEDï¼æ§è¡è®¡åæ©å±çæ§è¡æ ¼å¼PARTITIONSï¼å¨è¾èçMySQLçæ¬ä¸ï¼ååºä¿¡æ¯æ¯ä½¿ç¨EXPLAIN PARTITIONSçæçã为äºååå ¼å®¹ï¼ä»ç¶å¯ä»¥è¯å«è¯¥è¯æ³ï¼ä½ç°å¨é»è®¤å¯ç¨ååºè¾åºï¼å æ¤PARTITIONSå ³é®åæ¯å¤ä½çï¼å·²å¼ç¨ã使ç¨å®ä¼å¯¼è´ä¸ä¸ªè¦åï¼å¹¶ä¸å¨MySQL 8.0ä¸ä»EXPLAINè¯æ³ä¸å é¤äºå®ãFORMATï¼æ§è¡è®¡åè¾åºæ ¼å¼ï¼é»è®¤ä¸ºTRADITIONALï¼ä»¥è¡¨æ ¼çå½¢å¼è¾åºãMySQL 8.0ä¹åæJSONåTRADITIONALä¸¤ä¸ªéæ©ï¼MySQL 8.0å¼å§å¢å äºTREEè¾åºæ ¼å¼ã妿æ¯ä½¿ç¨JSONæ ¼å¼è¾åºçè¯ï¼æ§è¡è®¡åä¸çNULLå¼å°ä¸ä¼å±ç¤ºã 妿explain_typeä¸åï¼é»è®¤æ¯FORMAT = TRADITIONAL å¨MySQL 8.0å¼å§ï¼EXTENDEDåPARTITIONSå·²åºå¼ï¼åªæFORMATä¸ä¸ªé项ã
- explainable_stmtï¼å¿ 填项ï¼å¯ä½¿ç¨EXPLAINçSQLè¯å¥ãEXPLAIN å¯ä»¥å SELECTãDELETEã INSERT,ãREPLACEæUPDATE è¯å¥ä¸èµ·ä½¿ç¨ã
ãé¢å¤è¯ï¼ã EXPLAINå ³é®åè¿å¯ä»¥åDESCRIBEãDESCæè SHOW COLUMNS䏿 ·å±ç¤ºè¡¨ç»æãMySQL 8.0.18å¼å§è¿å¯ä»¥ä½¿ç¨EXPLAIN ANALYZEè¯å¥æ¥åæSQLè¯å¥ãæå ´è¶£çå¯ä»¥å®è£ MySQL 8.0è¯è¯çã
EXPLAIN 详解
å åå»ºä¸¤å¼ è¡¨ç¨äºæµè¯ï¼ä¸¤å¼ è¡¨ç»æé¤äºuser1å¤äºä¸ä¸ªå¯ä¸ç´¢å¼ä»¥å¤ï¼å ¶ä»é½ç¸å
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_name` varchar(40) NOT NULL DEFAULT '' COMMENT 'å
¨å',
`gender` tinyint(2) NOT NULL DEFAULT '0' COMMENT 'æ§å«',
`create_date` datetime NOT NULL COMMENT 'å建æ¶é´',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COMMENT='ç¨æ·è¡¨'
CREATE TABLE `user1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_name` varchar(40) NOT NULL DEFAULT '' COMMENT 'å
¨å',
`gender` tinyint(2) NOT NULL DEFAULT '0' COMMENT 'æ§å«',
`create_date` datetime NOT NULL COMMENT 'å建æ¶é´',
PRIMARY KEY (`id`),
KEY `uk_user_name` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COMMENT='ç³»ç»ç¨æ·è¡¨'
æ§è¡ä¸é¢SQLï¼æ¥çæ§è¡è®¡å齿åªäºå
explain select * from user;
æ¯ä¸ªå代表çå«ä¹å¦ä¸ï¼
åå JSONæ ¼å¼çéé¢ å«ä¹
id select_id SELECT è¯å¥id
select_type None SELECT ç±»å
table table_name 表å
partitions partitions å¹é çååºä¿¡æ¯
type access_type é对å表çè®¿é®æ¹æ³
possible_keys possible_keys å¯è½ç¨å°çç´¢å¼
key key å®é ä¸ä½¿ç¨çç´¢å¼
key_len key_length å®é 使ç¨å°çç´¢å¼é¿åº¦
ref ref å½ä½¿ç¨ç´¢å¼åç弿¥è¯¢æ¶ï¼ ä¸ç´¢å¼åè¿è¡çå¼å¹é ç对象信æ¯
rows rows é¢ä¼°çéè¦è¯»åçè®°å½æ¡æ°
filtered filtered æä¸ªè¡¨ç»è¿æç´¢æ¡ä»¶è¿æ»¤åå©ä½è®°å½æ¡æ°çç¾åæ¯
Extra None é¢å¤çä¿¡æ¯
åæ®µè§£é
对select_type åæ®µè§£éä¹åå äºè§£ä¸ä¸ä¸é¢å 个åè¯ï¼
â
ãåæ¥è¯¢ç©åãï¼åæ¥è¯¢çç»æé常ç¼åå¨å åæä¸´æ¶è¡¨ä¸ã
ãå ³è/ç¸å ³åæ¥è¯¢ãï¼åæ¥è¯¢çæ§è¡ä¾èµäºå¤é¨æ¥è¯¢ã夿°æ åµä¸æ¯åæ¥è¯¢ç WHERE åå¥ä¸å¼ç¨äºå¤é¨æ¥è¯¢å å«çåã
â
id
SELECTæ¥è¯¢çåºåå·ï¼å¯ä»¥ä¸ºNULLãidç¸åï¼æ§è¡é¡ºåºç¸åï¼ä»ä¸å¾ä¸æ§è¡ï¼idä¸åï¼idè¶å¤§è¶å 被æ§è¡ã é£ä»ä¹æ åµä¸idç¸åï¼ä»ä¹æ åµä¸ä¸åå¢ï¼
- å表ãè¿æ¥æ¥è¯¢(å è¿ãå·¦è¿ãå³è¿)è¯å¥ä¸ï¼idç¸å
å表就ä¸ç¨è¿å¤è¯´äºï¼å°±ä¸å¼ 表ï¼idå°±ä¸ä¸ªè¯å®æ¯ç¸åçã
对äºè¿æ¥æ¥è¯¢æ¥è¯´ï¼ä¸ä¸ª SELECTå ³é®ååè¾¹ç FROM åå¥ä¸å¯ä»¥è·éå¤ä¸ª è¡¨ï¼æä»¥å¨è¿æ¥æ¥è¯¢çæ§è¡è®¡åä¸ï¼æ¯ä¸ªè¡¨é½ä¼å¯¹åºä¸æ¡è®°å½ï¼ä½æ¯è¿äºè®°å½ç id å¼é½æ¯ç¸åçï¼æ¯å¦ï¼
EXPLAIN SELECT * FROM `user` INNER JOIN user1 ON `user`.id = user1.id
å¯ä»¥çå°ä¸¤æ¡è®°å½å¯¹åºä¸¤å¼ 表ï¼idæ¯ç¸åçã
- æåæ¥è¯¢çè¯å¥idå¯è½ç¸åä¹å¯è½ä¸å
为ä»ä¹æå¯è½ç¸å乿å¯è½ä¸åçï¼é£æ¯å 为æ¥è¯¢ä¼åå¨è§å¾è¿æ¡å å«åæ¥è¯¢çè¯å¥å¯ä»¥ä½¿ç¨è¿æ¥æ¥è¯¢è¿è¡ä¼åï¼ å°±ä¼å¯¹è¿æ¡è¯å¥è¿è¡éåä¸ºè¿æ¥æ¥è¯¢ï¼æä»¥æ³ç¥éæ¥è¯¢ä¼å卿¯å¦éåäºæ¥è¯¢è¯å¥ï¼å°±å¯ä»¥éè¿explainæ¥çãæ¯å¦ï¼
ãæªè¢«ä¼åçãï¼
EXPLAIN SELECT * FROM `user` WHERE id IN (SELECT id FROM user1) OR `user`.gender = 1;
æ§è¡è®¡åç»æï¼
ã被ä¼åçè¯å¥ãï¼
EXPLAIN SELECT * FROM `user` WHERE id IN (SELECT id FROM user1)
æ§è¡è®¡åç»æï¼
å¯ä»¥çå°è¢«ä¼åååidæ¯ä¸åçï¼ä¹å°±æ¯æ§è¡é¡ºåºä¸åäºã
- Unionè¿æ¥è¯å¥ä¸idä¸å
ãä¸è¬æ¥è¯´ãï¼å¯¹äºå å«UNIONåå¥çæ¥è¯¢è¯å¥æ¥è¯´ï¼æ¯ä¸ªSELECTå ³é®å对åºä¸ä¸ª idå¼ã å çä¸é¢è¿æ¡è¯å¥ï¼
EXPLAIN SELECT * FROM `user` union SELECT * FROM user1;
EXPLAIN ç»æï¼
å¯ä»¥çå°ï¼user表åuser1表ä¹é´ç¨union è¿æ¥ï¼ç»æå´æä¸æ¡è®°å½ï¼è¿æ¯ä¸ºä»ä¹å¢ï¼æ¯å 为UNIONè¿æ¥æ¥è¯¢å°çç»æè¦å»éï¼æä¹å»éå¢ï¼mysqlæ¯å¨å ¶å é¨å建äºä¸´æ¶è¡¨è¿è¡å»éï¼è¿éå¯ä»¥çå°è¡¨åæ¯<unionM,N>å ¶ä¸ï¼MãNåå«ä»£è¡¨ä¸¤å¼ 表æ§è¡è®¡åçidï¼ç¬¬ä¸è¡çid为NULL表æè¿ä¸ªä¸´æ¶è¡¨æ¯ä¸ºäºåå¹¶æ°æ®å»éæå建çãä¸é¢æä»¬è¯´è¿idä¹ä¼ä¸ºç©ºï¼å°±æ¯å¨ä½¿ç¨unionè¿è¡æ¥è¯¢çæ¶åã
åçä¸é¢è¿æ¡è¯å¥ï¼
EXPLAIN SELECT * FROM `user` UNION ALL SELECT * FROM user1;
EXPLAIN ç»æï¼
å¯ä»¥çå°ä½¿ç¨UNION ALLä¹åï¼ç»æå°±åæäº2æ¡è®°å½ï¼è¿æ¯å 为UNION ALLä¸éè¦å»éï¼æ¥å°ä»ä¹ç»æå°±è¿åä»ä¹ç»æï¼æä»¥ä¹ä¸ä¼åºç°ä¸´æ¶è¡¨ã
table
被æ¥è¯¢ç表åï¼å¯è½æ¯çå®åå¨ç表ï¼ä¹å¯è½æ¯ä¸´æ¶è¡¨æè æ´¾ç表ä¹ç±»çãé¤äºçå®è¡¨å¯è½åºç°ç3ç§è¡¨åå¦ä¸ï¼
- <unionM,N>ï¼éè¿unionæ¥è¯¢äº§ççç»æï¼MãNåå«ä»£è¡¨çæ§è¡è®¡åidçå¼
- <derivedN>ï¼Nçå¼ä¸ºæ´¾ç表çidå¼ãæ´¾ç表å¯è½æ¯FROMè¯å¥ä¸çåæ¥è¯¢
- <subqueryN>ï¼N为ç©ååæ¥è¯¢çidå¼
select_type
- SIMPLE ï¼ç®åSELECTæ¥è¯¢ï¼æ¥è¯¢ä¸ä¸å å«åæ¥è¯¢æè UNION
- PRIMARY ï¼å¯¹äºå å« UNIONãUNION ALL æè åæ¥è¯¢ç夿æ¥è¯¢æ¥è¯´ï¼å®æ¯ç±å ä¸ªå°æ¥è¯¢ ç»æçï¼å ¶ä¸æå·¦è¾¹çé£ä¸ªæ¥è¯¢ç select_type å¼å°±æ¯ PRIMARYãå¨è§£éidçä¾å䏿ã
- UNION ï¼å¯¹äºå å« UNION æè UNION ALL ç夿æ¥è¯¢æ¥è¯´ï¼å®æ¯ç±å ä¸ªå°æ¥è¯¢ç»æçï¼ å ¶ä¸é¤äºæå·¦è¾¹çé£ä¸ªå°æ¥è¯¢ä»¥å¤ï¼å ¶ä½çæ¥è¯¢ç select_type å¼å°±æ¯ UNIONãå¨è§£éidçä¾å䏿ã
- UNION RESULTï¼MySQL éæ©ä½¿ç¨ä¸´æ¶è¡¨æ¥å®æ UNION æ¥è¯¢çå»éå·¥ä½ï¼é对该临æ¶è¡¨çæ¥ è¯¢ç select_type å°±æ¯ UNION RESULTãå¨è§£éidçä¾å䏿ã
- SUBQUERYï¼ä¸ä¼è¢«æ¥è¯¢ä¼åå¨ä¼åçåæ¥è¯¢ä¸ï¼ä¸ä¾èµäºå¤é¨æ¥è¯¢çç»æéï¼ç¬¬ä¸ä¸ª SELECT å ³é®å代表çé£ä¸ªæ¥è¯¢ç select_type å°±æ¯ SUBQUERYã
EXPLAIN SELECT * FROM `user` WHERE id =(SELECT id FROM user1 WHERE id = 1);
ç±äº select_type 为 SUBQUERY çåæ¥è¯¢ä¼è¢«ç©åï¼æä»¥åªéè¦æ§è¡ä¸éã
- DEPENDENT UNIONï¼å¯¹äºå å« UNION æè UNION ALL ç夿æ¥è¯¢æ¥è¯´ï¼å¦æåä¸ªå°æ¥è¯¢é½ä¾èµäºå¤å±æ¥è¯¢çè¯ï¼é£é¤äºæå·¦è¾¹çé£ä¸ªå°æ¥è¯¢ä¹å¤ï¼å ¶ä½çå°æ¥è¯¢ç select_type çå¼å°±æ¯ DEPENDENT UNIONã
- DEPENDENT SUBQUERYï¼åæ¥è¯¢ä¸ç第ä¸ä¸ª select æ¥è¯¢ï¼ä¾èµäºå¤é¨æ¥è¯¢çç»æéï¼select_type çå¼ å°±æ¯DEPENDENT SUBQUERY
- DERIVEDï¼å¯¹äºéç¨ç©åçæ¹å¼æ§è¡çå 嫿´¾çè¡¨çæ¥è¯¢ï¼è¯¥æ´¾ç表对åºçåæ¥è¯¢çselect_typeå°±æ¯DERIVEDã
EXPLAIN SELECT * FROM (SELECT id , user_name FROM user GROUP BY user_name) derived_user WHERE derived_user.id > 1;
id=2ç select_type æ¯ DERIVED ï¼è¯´æè¯¥åæ¥è¯¢æ¯ä»¥ç©åçæ¹å¼æ§è¡çãid =1çè®°å½ä»£è¡¨å¤å±æ¥è¯¢ï¼å®ç table åæ¾ç¤ºçæ¯<derived2>ï¼è¡¨ç¤ºè¯¥æ¥è¯¢æ¯å°æ´¾ç表ç©åä¹åç表è¿è¡æ¥è¯¢çã
- MATERIALIZEDï¼å½æ¥è¯¢ä¼åå¨å¨æ§è¡å å«åæ¥è¯¢çè¯å¥æ¶ï¼éæ©å°åæ¥è¯¢ç©åä¹åä¸å¤å±æ¥è¯¢è¿è¡è¿æ¥æ¥è¯¢æ¶ï¼è¯¥åæ¥è¯¢å¯¹åºç select_type 屿§å°±æ¯ MATERIALIZEDã
EXPLAIN SELECT * FROM user1 WHERE user_name IN (SELECT user_name FROM `user`);
æ§è¡è®¡åçç¬¬ä¸æ¡è®°å½ç id å¼ä¸º 2ï¼ä»å®ç select_type å¼ä¸º NATERIALIED å¯ ä»¥çåºï¼æ¥è¯¢ä¼å卿¯è¦æåæ¥è¯¢å è½¬æ¢æç©å表ãç¬¬äºæ¡è®°å½ç table åç弿¯<subquery2>ï¼è¯´æè¯¥è¡¨ å ¶å®å°±æ¯ id 为 2 对åºçåæ¥è¯¢æ§è¡ä¹å产ççç©å表ï¼ç¶åå° s1 å该ç©å表è¿è¡è¿æ¥æ¥è¯¢
- UNCACHEABLE SUBQUERYï¼ä¸ä¸ªåæ¥è¯¢ï¼å ¶ç»ææ æ³ç¼åï¼å¿ 须为å¤é¨æ¥è¯¢çæ¯ä¸è¡éæ°è®¡ç®ãåºç°ççæ åµæå°
- UNCACHEABLE UNIONï¼å±äºä¸å¯ç¼ååæ¥è¯¢(UNCACHEABLE SUBQUERY)çUNIONä¸ç第äºä¸ªæä»¥åçselectãåºç°ççæ åµæå°
partitions
åååºè¡¨æå ³ï¼ä¸è¬æ åµä¸æä»¬çæ¥è¯¢è¯å¥çæ§è¡è®¡åç partitions åçå¼ é½æ¯ NULLã
type
typeè¡¨ç¤ºè¡¨è¿æ¥ç±»åæè æ°æ®è®¿é®ç±»åï¼å°±æ¯è¡¨ä¹é´éè¿ä»ä¹æ¹å¼å»ºç«è¿æ¥çï¼æè éè¿ä»ä¹æ¹å¼è®¿é®å°æ°æ®çã宿¯è¾ä¸ºéè¦çä¸ä¸ªææ ï¼ç»æå¼ä»æå¥½å°æå便¬¡æ¯ï¼
ãsystem > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALLã
åºç°æ¯è¾å¤çæ¯ ãsystem>const>eq_ref>ref>range>index>ALLã ä¸è¬æ¥è¯´ï¼å¾ä¿è¯æ¥è¯¢è³å°è¾¾å° range 级å«ï¼æå¥½è½è¾¾å° refã
- system :å½è¡¨ä¸åªæä¸æ¡è®°å½å¹¶ä¸è¯¥è¡¨ä½¿ç¨çåå¨å¼æçç»è®¡æ°æ®æ¯ç²¾ç¡®çï¼æ¯å¦ MyISAMãMemoryï¼é£ä¹å¯¹è¯¥è¡¨çè®¿é®æ¹æ³å°±æ¯ systemã
- constï¼æ ¹æ®ä¸»é®æè å¯ä¸äºçº§ç´¢å¼åä¸å¸¸æ°è¿è¡çå¼å¹é æ¶ï¼å¯¹å表çè®¿é®æ¹æ³å°±æ¯ constãå 为åªå¹é ä¸è¡æ°æ®ï¼æ¥è¯¢ä¼åå¨ä¼æå®å½åå¸¸æ°æ¥å¯¹å¾ ï¼constç±»åçtableæ¥è¯¢çå¾å¿«ï¼å 为åªä¼è¢«è¯»å䏿¬¡ã
EXPLAIN SELECT * FROM `user` WHERE id = 1
- eq_ref ï¼å¨è¿æ¥æ¥è¯¢æ¶ï¼å¦æè¢«é©±å¨è¡¨æ¯éè¿ä¸»é®æè å¯ä¸äºçº§ç´¢å¼åçå¼å¹é çæ¹å¼è¿è¡è®¿é®ï¼æè å¦æè¯¥ä¸»é®æè å¯ä¸äºçº§ç´¢å¼æ¯èåç´¢å¼çè¯ï¼ææçç´¢å¼åé½å¿ é¡»è¿è¡ç弿¯è¾ï¼å对该被驱å¨è¡¨çè®¿é®æ¹æ³å°±æ¯eq_refã 驱å¨è¡¨ä¸è¢«é©±å¨è¡¨ï¼A表åB表joinè¿æ¥æ¥è¯¢ï¼å¦æéè¿A表çç»æéä½ä¸ºå¾ªç¯åºç¡æ°æ®ï¼ç¶å䏿¡ä¸æ¡å°éè¿è¯¥ç»æéä¸çæ°æ®ä½ä¸ºè¿æ»¤æ¡ä»¶å°Bè¡¨ä¸æ¥è¯¢æ°æ®ï¼ç¶ååå¹¶ç»æãé£ä¹æä»¬ç§°A表为驱å¨è¡¨ï¼B表为被驱å¨è¡¨
EXPLAIN SELECT * FROM `user` INNER JOIN user1 ON `user`.id = user1.id;
仿§è¡è®¡åçç»æä¸å¯ä»¥çåºï¼MySQL æç®å° user1 ä½ä¸ºé©±å¨è¡¨ï¼userä½ä¸ºè¢«é©± å¨è¡¨ãuser1 çè®¿é®æ¹æ³æ¯ eq_refï¼è¡¨æå¨è®¿é® user1 è¡¨çæ¶åå¯ä»¥éè¿ä¸»é®ççå¼å¹é æ¥è¿è¡è®¿é®ã
- refï¼å½éè¿æ®éçäºçº§ç´¢å¼åä¸å¸¸éè¿è¡çå¼å¹é æ¶æ¥æ¥è¯¢æä¸ªè¡¨ï¼é£ä¹å¯¹è¯¥è¡¨çè®¿é®æ¹æ³å°±å¯è½æ¯ refã æ¬è´¨ä¸ä¹æ¯ä¸ç§ç´¢å¼è®¿é®ï¼å®è¿åææå¹é æä¸ªåç¬å¼çè¡ï¼ç¶èï¼å®å¯è½ 伿¾å°å¤ä¸ªç¬¦åæ¡ä»¶çè¡ï¼æä»¥å®å±äºæ¥æ¾åæ«æçæ··åä½ã
- fulltextï¼ä½¿ç¨äºå ¨æç´¢å¼è¿è¡æ¥è¯¢ã
- ref_or_null ï¼ææ¶åæä»¬ä¸ä» æ³æ¾åºæä¸ªäºçº§ç´¢å¼åçå¼çäºæä¸ªå¸¸æ°çè®°å½ï¼è¿æ³æè¯¥åçå¼ä¸ºNULL çè®°å½ä¹æ¾åºæ¥ï¼è¿ä¸ªæ¶åtypeå°±æ¯ref_or_nullã
- index_merge ï¼ä¸è¬æ åµä¸å¯¹äºæä¸ªè¡¨çæ¥è¯¢åªè½ä½¿ç¨å°ä¸ä¸ªç´¢å¼ï¼å¨æäºåºæ¯ä¸å¯ä»¥ä½¿ç¨ ç´¢å¼åå¹¶çæ¹å¼æ¥æ§è¡æ¥è¯¢
- unique_subqueryï¼unique_subquery æ¯éå¯¹å¨ ä¸äºå å«INåæ¥è¯¢çæ¥è¯¢è¯å¥ä¸ï¼å¦ææ¥è¯¢ä¼åå¨å³å®å°INåæ¥è¯¢è½¬æ¢ä¸ºEXISTS åæ¥è¯¢ï¼èä¸åæ¥è¯¢å¯ä»¥ä½¿ç¨å°ä¸»é®è¿è¡çå¼å¹é çè¯ï¼é£ä¹è¯¥åæ¥è¯¢æ§è¡è®¡å ç type åçå¼å°±æ¯ unique_subqueryã
EXPLAIN SELECT * FROM user1 WHERE id IN (SELECT id FROM `user` WHERE user1.user_name = `user`.user_name) OR user1.id = 1;
- index_subquery ï¼index_subquery ä¸ unique_subquery 类似ï¼åªä¸è¿è®¿é®â¼¦æ¥è¯¢ä¸ç表æ¶ä½¿â½¤çæ¯æ®éçç´¢å¼ã
EXPLAIN SELECT * FROM `user` WHERE user_name IN (SELECT user_name FROM user1) OR user_name='name';
- range ï¼å¦æä½¿ç¨ç´¢å¼è·åæäºèå´åºé´çè®°å½ï¼é£ä¹å°±å¯è½ä½¿ç¨å°rangeè®¿é®æ¹æ³ï¼ ä¸è¬å°±æ¯å¨ä½ ç where è¯å¥ä¸åºç°äº betweenã<ã>ãin ççæ¥è¯¢ã
EXPLAIN SELECT * FROM user1 WHERE user_name > 'ç´¢ç ç'
- index ï¼å½ä½¿ç¨ç´¢å¼è¦çï¼ä½éè¦æ«æå ¨é¨çç´¢å¼è®°å½æ¶ï¼è¯¥è¡¨çè®¿é®æ¹æ³å°±æ¯ indexã
EXPLAIN SELECT id , user_name FROM user1 WHERE user_name > 'ç´¢ç ç'
- ALLï¼å ¨è¡¨æ«æï¼éåå ¨è¡¨æ¾å°å¹é çè¡ã
possible_keys ä¸ key
possible_keys æ¯å¯è½ä½¿ç¨å°çç´¢å¼å表ï¼keyæ¯å®é 使ç¨å°çç´¢å¼å表ãå½possible_keysåºç°å¤ä¸ªç´¢å¼æ¶ï¼æ¥è¯¢ä¼åå¨ä¼è®¡ç®ä½¿ç¨åªä¸ä¸ªæå 个æè ä¸ä½¿ç¨ç´¢å¼çææ¬æ´ä½ï¼æåéæ©çç´¢å¼å°±ä¼å¨keyéé¢åºç°ã éè¦æ³¨æçä¸ç¹æ¯ï¼possible keysåä¸çå¼å¹¶ä¸æ¯è¶å¤è¶å¥½ï¼å¯è½ä½¿ç¨çç´¢å¼è¶å¤ï¼æ¥è¯¢ä¼åå¨è®¡ç®æ¥è¯¢ææ¬æ¶å°±å¾è±è´¹æ´é¿æ¶é´ï¼æä»¥å¦æå¯ä»¥çè¯ï¼å°½éå é¤é£äºç¨ä¸å°çç´¢å¼ã
key_len
key_lenå表示å½ä¼åå¨å³å®ä½¿ç¨æä¸ªç´¢å¼æ§è¡æ¥è¯¢æ¶ï¼è¯¥ç´¢å¼è®°å½çæå¤§é¿åº¦ãè®¡ç®æ¹å¼æ¯è¿æ ·çï¼
对äºä½¿ç¨åºå®é¿åº¦ç±»åçç´¢å¼åæ¥è¯´ï¼å®å®é å ç¨çåå¨ç©ºé´çæå¤§é¿åº¦å°±æ¯è¯¥åºå®å¼ï¼å¯¹äºæå®å符éçåé¿ç±»åçç´¢å¼åæ¥è¯´ï¼æ¯å¦æä¸ªç´¢å¼åçç±»å æ¯ VARCHAR(100)ï¼ä½¿ç¨çåç¬¦éæ¯utf8ï¼é£ä¹è¯¥åå®é å ç¨çæå¤§åå¨ç©ºé´å°± æ¯ 100 x 3 = 300 个åèã å¦æè¯¥ç´¢å¼åå¯ä»¥åå¨ NULL å¼ï¼å key_len æ¯ä¸å¯ä»¥åå¨ NULL 弿¶å¤ 1 个 åèã 对äºåé¿å段æ¥è¯´ï¼é½ä¼æ 2 个åèçç©ºé´æ¥åå¨è¯¥åé¿åçå®é é¿åº¦ã æ¯å¦ä¸é¢è¿ä¸ªè¯å¥ï¼
EXPLAIN SELECT * FROM user1 WHERE user_name = 'ç´¢ç ç';
æ ¹æ®æ§è¡è®¡åå¯ä»¥çåºä½¿ç¨äºç´¢å¼idx_user_nameï¼user_nameåæ®µæ¯varchar(40) NOT NULLï¼ä½¿ç¨çåç¬¦éæ¯utf8mb4ï¼utf8mb4å符éåå符æå¤å ç¨4个åè空é´ãéè¿è¿äºä¿¡æ¯å¯ä»¥å¾å°40*4+2=162ï¼è·æ§è¡è®¡åä¸çç»æä¸æ ·ï¼å¦æuser_nameåæ®µå 许为NULLï¼é£ä¹ç»æå°±åæäº163ã
MySQL 卿§è¡è®¡åä¸è¾åº key_len åä¸»è¦æ¯ä¸ºäºè®©æä»¬åºåæä¸ªä½¿ç¨èåç´¢å¼çæ¥è¯¢å ·ä½ç¨äºå 个索å¼å(èåç´¢å¼ææå·¦åç¼çç¹æ§ï¼å¦æèåç´¢å¼è½å ¨é¨ä½¿ç¨ä¸ï¼åæ¯èåç´¢å¼å段çç´¢å¼é¿åº¦ä¹åï¼è¿ä¹å¯ä»¥ç¨æ¥å¤å®èåç´¢å¼æ¯å¦é¨å使ç¨ï¼è¿æ¯å ¨é¨ä½¿ç¨)ï¼è䏿¯ä¸ºäºåç¡®ç说æé对æä¸ªå ·ä½åå¨å¼æåå¨åé¿å段çå®é é¿åº¦å ç¨ç空é´å°åºæ¯å ç¨ 1 个åèè¿æ¯ 2 个åèã
key_len 表示索å¼ä¸ä½¿ç¨çåèæ°ï¼å¯éè¿è¯¥åè®¡ç®æ¥è¯¢ä¸ä½¿ç¨çç´¢å¼çé¿åº¦ãå¨ä¸æå¤±ç²¾ç¡®æ§çæ åµä¸ï¼é¿åº¦è¶çè¶å¥½ãkey_lenæ¾ç¤ºçå¼ä¸ºç´¢å¼å段çæå¤§å¯è½é¿åº¦ï¼å¹¶éå®é 使ç¨é¿åº¦ï¼å³key_lenæ¯æ ¹æ®è¡¨å®ä¹è®¡ç®èå¾ï¼ä¸æ¯éè¿è¡¨å æ£ç´¢åºçã
ref
å½ä½¿ç¨ç´¢å¼åçå¼å¹é çæ¡ä»¶å»æ§è¡æ¥è¯¢æ¶ï¼ä¹å°±æ¯å¨è®¿é®æ¹æ³æ¯ constãeq_refãrefãref_or_nullãunique_sutbqueryãindex_subopery å ¶ä¸ä¹ä¸æ¶ï¼ref åå±ç¤ºçå°±æ¯ä¸ç´¢å¼åä½çå¼å¹é çåæ®µæè 彿°çãæ¯å¦å¨ä¸é¢çkey_lençä¾åä¸ï¼refç弿¯constï¼è¡¨ç¤ºä¸user_nameä½çå¼å¹é ç对象æ¯ä¸ä¸ªå¸¸æ°ã ææ¶åä¹ä¼å±ç¤ºçå¼å¹é å ·ä½çåæ®µï¼æ¯å¦ï¼
EXPLAIN SELECT * FROM `user` INNER JOIN user1 ON `user`.user_name = user1.user_name WHERE `user`.user_name > 'username4';
å¯ä»¥çå°ç¬¬äºårefç弿¯db_test.user.user_name(æ°æ®åº.表å.å ·ä½å段)ï¼è¡¨user1使ç¨äºç´¢å¼idx_user_nameï¼è¿è¡¨ç¤ºä¸è¡¨user1ç´¢å¼idx_user_nameåçå¼å¹é çæ¯è¡¨userä¸çuser_nameåæ®µã
ææ¶åä¸ç´¢å¼åè¿è¡çå¼å¹é ç对象æ¯ä¸ä¸ªå½æ°ï¼refåä¼è¾åºå¼func
rows
妿æ¥è¯¢ä¼åå¨å³å®ä½¿ç¨å ¨è¡¨æ«æçæ¹å¼å¯¹æä¸ªè¡¨æ§è¡æ¥è¯¢æ¶ï¼rows å就代表é¢è®¡éè¦æ«æçè¡æ°ï¼å¦æä½¿ç¨ç´¢å¼æ¥æ§è¡æ¥æ¶ï¼rows å就代表é¢è®¡æ«æçç´¢å¼è®°å½è¡æ°ãrowsç弿¯é¢ä¼°å¼ï¼å¯¹äºInnoDB 弿ç表æ¥è¯´ï¼è¿ä¸ªå¼å¯è½ä¸ä¼ä¸ç´é½æ¯åç¡®çã
EXPLAIN SELECT * FROM `user` WHERE id > 4
user表ä¸å äº13æ¡æ°æ®ï¼æ ¹æ®ä¸é¢é£æ¡SQLè¯å¥æ¥è¯¢æ¡ä»¶è½å¨æ°æ®åºå¹é å°çç»ææ9æ¡ï¼rowså°±æ¯9
filtered
filtered表示满足æ¥è¯¢æ¡ä»¶çè¡æ°å é¢ä¼°æ»¡è¶³æ¡ä»¶çè¡æ°rowsçç¾åæ¯ãfilteredçå¼ä»100å¼å§åå°çåæ¶è¿æ»¤æçè¡æ°ä¹å¨å¢å ã
EXPLAIN SELECT * FROM `user` INNER JOIN user1 ON `user`.user_name = user1.user_name WHERE `user`.user_name > 'username4';
第ä¸è¡ç»ærows=13ï¼filtered=33.33%ï¼å°±æ¯è¯´ä»é¢ä¼°ç¬¦åæ¡ä»¶çè¡æ°rowsä¸äºæ¬¡çéåº33.33%çè¡æ°ç¬¦åæ¡ä»¶ï¼ä¹å°±æ¯è¿æ»¤æäº13*0.3333â5ï¼æ»¡è¶³æ¡ä»¶çè¿5è¡ååuser1表è¿è¡è¿æ¥ãfilteredåªæ¯ä¸ä¸ªé¢ä¼°å¼ï¼åèå¼ä¸å¤§ã
Extra
顾åæä¹ï¼Extra åæ¯ç¨æ¥è¯´æä¸äºé¢å¤ä¿¡æ¯çï¼æä»¬å¯ä»¥éè¿è¿äºé¢å¤ä¿¡æ¯æ¥æ´åç¡®ççè§£ MySQL å°åºå°å¦ä½æ§è¡ç»å®çæ¥è¯¢è¯å¥ã妿è¦ä½¿æ¥è¯¢å°½å¯è½å¿«ï¼è¯·æ³¨æä½¿ç¨ Using filesort åUsing temporaryçExtraåå¼ã EXPLAINæ33个左å³Extraä¿¡æ¯ï¼æå ´è¶£çå¯ä»¥å°MySQLå®ç½çä¸ãè¿éå°±ç®åä»ç»å 个ç»å¸¸è½éå°çã
- Using indexï¼å½æä»¬çæ¥è¯¢å表以åæç´¢æ¡ä»¶ä¸åªå å«å±äºæä¸ªç´¢å¼çåï¼ä¹å°±æ¯å¨å¯ä»¥ 使ç¨ç´¢å¼è¦ççæ åµä¸ï¼å¨ Extra åå°ä¼æç¤ºè¯¥é¢å¤ä¿¡æ¯ã
- Using filesortï¼æä¸äºæ åµä¸å¯¹ç»æéä¸çè®°å½è¿è¡æåºæ¯å¯ä»¥ä½¿ç¨å°ç´¢å¼çï¼å¾å¤æ åµä¸æåºæä½æ æ³ä½¿ç¨å°ç´¢å¼ï¼åªè½å¨å åä¸ï¼è®°å½è¾å°çæ¶åï¼æè ç£çä¸ï¼è®°å½è¾å¤çæ¶åï¼è¿è¡æåºï¼MySQLæè¿ç§å¨å å䏿è ç£çä¸è¿è¡æåºçæ¹å¼ç»ç§°ä¸ºæä»¶æåº(filesort)ã妿æä¸ªæ¥è¯¢éè¦ä½¿ç¨æä»¶æåºçæ¹å¼æ§è¡æ¥è¯¢ï¼å°±ä¼å¨æ§è¡è®¡åçExtraå䏿¾ç¤ºUsing filesortã
- Using temporaryï¼å¨è®¸å¤æ¥è¯¢çæ§è¡è¿ç¨ä¸ï¼MySQL å¯è½ä¼åå©ä¸´æ¶è¡¨æ¥å®æä¸äºåè½ï¼æ¯å¦ å»éãæåºä¹ç±»çï¼æ¯å¦æä»¬å¨æ§è¡è®¸å¤å å« DISTINCTãGROUP BYãUNION ç åå¥çæ¥è¯¢è¿ç¨ä¸ï¼å¦æä¸è½ææå©ç¨ç´¢å¼æ¥å®ææ¥è¯¢ï¼MySQL 徿å¯è½å¯»æ±é è¿å»ºç«å é¨ç临æ¶è¡¨æ¥æ§è¡æ¥è¯¢ã妿æ¥è¯¢ä¸ä½¿ç¨å°äºå é¨ç临æ¶è¡¨ï¼å¨æ§è¡è®¡åçExtraåå°ä¼æ¾ç¤ºUsing temporary
- Using whereï¼å½æä»¬ä½¿ç¨å ¨è¡¨æ«ææ¥æ§è¡å¯¹æä¸ªè¡¨çæ¥è¯¢ï¼å¹¶ä¸è¯¥è¯å¥çWHEREåå¥ä¸æé对该表çæç´¢æ¡ä»¶æ¶ï¼å¨ Extra åä¸ä¼æ¾ç¤ºUsing whereï¼å½ä½¿ç¨ç´¢å¼è®¿é®æ¥æ§è¡å¯¹æä¸ªè¡¨çæ¥è¯¢ï¼å¹¶ä¸è¯¥è¯å¥ç WHERE åå¥ä¸æé¤äºè¯¥ç´¢å¼å å«çåä¹å¤çå ¶ä»æç´¢æ¡ä»¶æ¶ï¼å¨ Extra åä¸ä¹ä¼æ¾ç¤ºUsing whereãUsing whereåªæ¯è¡¨ç¤º MySQL使ç¨whereåå¥ä¸çæ¡ä»¶å¯¹è®°å½è¿è¡äºè¿æ»¤ã
- Using join buffer (Block Nested Loop)ï¼å¨è¿æ¥æ¥è¯¢æ§è¡è¿ç¨ä¸ï¼å½è¢«é©±å¨è¡¨ä¸è½ææçå©ç¨ç´¢å¼å 快访é®é度ï¼MySQLä¸è¬ä¼ä¸ºå ¶åé ä¸ååå«join bufferçå å忥å å¿«æ¥è¯¢é度ï¼éè¿ä½¿ç¨join bufferæ¥åå°å¯¹è¢«é©±å¨è¡¨çè®¿é®æ¬¡æ°ï¼ä»èæé«æ§è½ã
- Using index conditionï¼å¦æå¨æ¥è¯¢è¯å¥çæ§è¡è¿ç¨ä¸å°è¦ä½¿ç¨ç´¢å¼æ¡ä»¶ä¸æ¨è¿ä¸ªç¹æ§ï¼å¨ Extra åä¸å°ä¼æ¾ç¤º Using index conditionã
- No tables usedï¼å½æ¥è¯¢è¯å¥ç没æFROMå奿æFROM DUALå奿¶å°ä¼æç¤ºè¯¥é¢å¤ä¿¡æ¯ã
- Impossible WHEREï¼æ¥è¯¢è¯å¥çWHEREå奿°¸è¿ä¸ºFALSEæ¶å°ä¼æç¤ºè¯¥é¢å¤ä¿¡æ¯
- Zero limitï¼å½LIMITåå¥çåæ°ä¸º0æ¶ï¼è¡¨ç¤ºå¹¶ä¸æç®ä»è¡¨ä¸è¯»åºä»»ä½è®°å½ï¼å°ä¼æç¤ºè¯¥é¢å¤ä¿¡æ¯ã
æ»ç»
MySQLæ§è¡è®¡åå¨é¢è¯ä¸ä¼ç»å¸¸é®å°ï¼å°¤å ¶æ¯typeåæ®µä¼ç»å¸¸è¢«é®å°ãåæ¶ï¼äºè§£æ§è¡è®¡åå¨å·¥ä½ä¸ä¹è½æ´å¥½ç对SQLæ¥è¯¢è¿è¡ä¼åï¼æä»¥æ§è¡è®¡åæ¯mysqlå¦ä¹ è¿ç¨ä¸çä¸ä¸ªå¿ 夿è½ï¼æ¥å å®ä¸ä¸èªå·±çæè½å ã