
âä¸è¦ä½¿ç¨SELECT *âå ä¹å·²ç»æä¸ºäºä½¿ç¨MySQLç䏿¡éç§çå¾ï¼å°±è¿ãé¿éJavaå¼åæåãä¹æç¡®è¡¨ç¤ºä¸å¾ä½¿ç¨*ä½ä¸ºæ¥è¯¢çåæ®µåè¡¨ï¼æ´æ¯è®©è¿æ¡è§åæ¥æäºæå¨çå æã
é¿éJavaå¼åæå
ä¸è¿æå¨å¼åè¿ç¨ä¸ç´æ¥ä½¿ç¨SELECT *è¿æ¯æ¯è¾å¤çï¼åå æä¸¤ä¸ªï¼
- å 为ç®åï¼å¼åæçé常é«ï¼èä¸å¦æåæé¢ç¹æ·»å æä¿®æ¹å段ï¼SQLè¯å¥ä¹ä¸éè¦æ¹åï¼
- æè®¤ä¸ºè¿æ©ä¼åæ¯ä¸ªä¸å¥½çä¹ æ¯ï¼é¤éå¨ä¸å¼å§å°±è½ç¡®å®ä½ æç»å®é éè¦çåæ®µæ¯ä»ä¹ï¼å¹¶ä¸ºä¹å»ºç«æ°å½çç´¢å¼ï¼å¦åï¼æéæ©éå°éº»ç¦çæ¶åå对SQLè¿è¡ä¼åï¼å½ç¶åææ¯è¿ä¸ªéº»ç¦å¹¶ä¸è´å½ã
使¯æä»¬æ»å¾ç¥é为ä»ä¹ä¸å»ºè®®ç´æ¥ä½¿ç¨SELECT *ï¼æ¬æä»4个æ¹é¢ç»åºçç±ã
1. ä¸å¿ è¦çç£çI/O
æä»¬ç¥é MySQL æ¬è´¨ä¸æ¯å°ç¨æ·è®°å½åå¨å¨ç£çä¸ï¼å æ¤æ¥è¯¢æä½å°±æ¯ä¸ç§è¿è¡ç£çIOçè¡ä¸ºï¼åææ¯è¦æ¥è¯¢çè®°å½æ²¡æç¼åå¨å åä¸ï¼ã
æ¥è¯¢çåæ®µè¶å¤ï¼è¯´æè¦è¯»åçå 容ä¹å°±è¶å¤ï¼å æ¤ä¼å¢å¤§ç£ç IO å¼éãå°¤å ¶æ¯å½æäºåæ®µæ¯ TEXTãMEDIUMTEXTæè BLOB çç±»åçæ¶åï¼ææå°¤ä¸ºææ¾ã
é£ä½¿ç¨SELECT *ä¼ä¸ä¼ä½¿MySQLå ç¨æ´å¤çå åå¢ï¼
ç论ä¸ä¸ä¼ï¼å 为对äºServerå±èè¨ï¼å¹¶éæ¯å¨å åä¸åå¨å®æ´çç»æéä¹åä¸ä¸åä¼ ç»å®¢æ·ç«¯ï¼èæ¯æ¯ä»åå¨å¼æè·åå°ä¸è¡ï¼å°±åå°ä¸ä¸ªå«ånet_bufferçå å空é´ä¸ï¼è¿ä¸ªå åç大å°ç±ç³»ç»åénet_buffer_lengthæ¥æ§å¶ï¼é»è®¤æ¯16KBï¼å½net_bufferåæ»¡ä¹åå徿¬å°ç½ç»æ çå å空é´socket send bufferä¸åæ°æ®åéç»å®¢æ·ç«¯ï¼åéæåï¼å®¢æ·ç«¯è¯»å宿ï¼åæ¸ ç©ºnet_bufferï¼ç¶åç»§ç»è¯»åä¸ä¸è¡å¹¶åå ¥ã
ä¹å°±æ¯è¯´ï¼é»è®¤æ åµä¸ï¼ç»æéå ç¨çå åç©ºé´æå¤§ä¸è¿æ¯net_buffer_length大å°ç½¢äºï¼ä¸ä¼å 为å¤å ä¸ªåæ®µå°±å ç¨é¢å¤çå å空é´ã
2. å éç½ç»æ¶å»¶
æ¿æ¥ä¸ä¸ç¹ï¼è½ç¶æ¯æ¬¡é½æ¯æsocket send bufferä¸çæ°æ®åéç»å®¢æ·ç«¯ï¼åæ¬¡çæ¥æ°æ®éä¸å¤§ï¼å¯æ¶ä¸ä½ççæäººç¨*æTEXTãMEDIUMTEXTæè BLOB ç±»åçåæ®µä¹æ¥åºæ¥äºï¼æ»æ°æ®é大äºï¼è¿å°±ç´æ¥å¯¼è´ç½ç»ä¼ è¾ç次æ°åå¤äºã
妿MySQLååºç¨ç¨åºä¸å¨åä¸å°æºå¨ï¼è¿ç§å¼ééå¸¸ææ¾ãå³ä½¿MySQLæå¡å¨å客æ·ç«¯æ¯å¨åä¸å°æºå¨ä¸ï¼ä½¿ç¨çåè®®è¿æ¯TCPï¼éä¿¡ä¹æ¯éè¦é¢å¤çæ¶é´ã
3. æ æ³ä½¿ç¨è¦çç´¢å¼
为äºè¯´æè¿ä¸ªé®é¢ï¼æä»¬éè¦å»ºä¸ä¸ªè¡¨
CREATE TABLE `user_innodb` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`gender` tinyint(1) DEFAULT NULL,
`phone` varchar(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_NAME_PHONE` (`name`,`phone`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
æä»¬å建äºä¸ä¸ªåå¨å¼æä¸ºInnoDBç表user_innodbï¼å¹¶è®¾ç½®id为主é®ï¼å¦å¤ä¸ºnameåphoneå建äºèåç´¢å¼ï¼æåå表ä¸éæºåå§åäº500W+æ¡æ°æ®ã
InnoDBä¼èªå¨ä¸ºä¸»é®idåå»ºä¸æ£µå为主é®ç´¢å¼ï¼åå«åèç°ç´¢å¼ï¼çB+æ ï¼è¿ä¸ªB+æ çæéè¦çç¹ç¹å°±æ¯å¶åèç¹å å«äºå®æ´çç¨æ·è®°å½ï¼å¤§æ¦é¿è¿ä¸ªæ ·åã
主é®ç´¢å¼
妿æä»¬æ§è¡è¿ä¸ªè¯å¥
SELECT * FROM user_innodb WHERE name = 'èæ²é£';
使ç¨EXPLAINæ¥çä¸ä¸è¯å¥çæ§è¡è®¡åï¼
åç°è¿ä¸ªSQLè¯å¥ä¼ä½¿ç¨å°IDX_NAME_PHONEç´¢å¼ï¼è¿æ¯ä¸ä¸ªäºçº§ç´¢å¼ãäºçº§ç´¢å¼çå¶åèç¹é¿è¿ä¸ªæ ·åï¼
InnoDBåå¨å¼æä¼æ ¹æ®æç´¢æ¡ä»¶å¨è¯¥äºçº§ç´¢å¼çå¶åèç¹ä¸æ¾å°nameä¸ºèæ²é£çè®°å½ï¼ä½æ¯äºçº§ç´¢å¼ä¸åªè®°å½äºnameãphoneå主é®idåæ®µï¼è°è®©æä»¬ç¨çæ¯SELECT *å¢ï¼ï¼å æ¤InnoDBéè¦æ¿ç主é®idå»ä¸»é®ç´¢å¼ä¸æ¥æ¾è¿ä¸æ¡å®æ´çè®°å½ï¼è¿ä¸ªè¿ç¨å«åå表ã
æ³ä¸ä¸ï¼å¦æäºçº§ç´¢å¼çå¶åèç¹ä¸ææä»¬æ³è¦çæææ°æ®ï¼æ¯ä¸æ¯å°±ä¸éè¦å表äºå¢ï¼æ¯çï¼è¿å°±æ¯è¦çç´¢å¼ã
举个ä¾åï¼æä»¬æ°å¥½åªæ³æç´¢nameãphone以å主é®å段ã
SELECT id, name, phone FROM user_innodb WHERE name = "èæ²é£";
使ç¨EXPLAINæ¥çä¸ä¸è¯å¥çæ§è¡è®¡åï¼
å¯ä»¥çå°Extraä¸åæ¾ç¤ºUsing indexï¼è¡¨ç¤ºæä»¬çæ¥è¯¢å表以åæç´¢æ¡ä»¶ä¸åªå å«å±äºæä¸ªç´¢å¼çåï¼ä¹å°±æ¯ä½¿ç¨äºè¦çç´¢å¼ï¼è½å¤ç´æ¥æå¼å表æä½ï¼å¤§å¹ 度æé«æ¥è¯¢æçã
4. å¯è½ææ ¢JOINè¿æ¥æ¥è¯¢
æä»¬åå»ºä¸¤å¼ è¡¨t1ï¼t2è¿è¡è¿æ¥æä½æ¥è¯´ææ¥ä¸æ¥çé®é¢ï¼å¹¶åt1è¡¨ä¸æå ¥äº100æ¡æ°æ®ï¼åt2ä¸æå ¥äº1000æ¡æ°æ®ã
CREATE TABLE `t1` (
`id` int NOT NULL,
`m` int DEFAULT NULL,
`n` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT;
CREATE TABLE `t2` (
`id` int NOT NULL,
`m` int DEFAULT NULL,
`n` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT;
妿æä»¬æ§è¡ä¸é¢è¿æ¡è¯å¥
SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.m = t2.m;
è¿éæä½¿ç¨äºSTRAIGHT_JOIN强å¶ä»¤t1表ä½ä¸ºé©±å¨è¡¨ï¼t2表ä½ä¸ºè¢«é©±å¨è¡¨
对äºè¿æ¥æ¥è¯¢èè¨ï¼é©±å¨è¡¨åªä¼è¢«è®¿é®ä¸éï¼è被驱å¨è¡¨å´è¦è¢«è®¿é®å¥½å¤éï¼å ·ä½çè®¿é®æ¬¡æ°åå³äºé©±å¨è¡¨ä¸ç¬¦åæ¥è¯¢è®°å½çè®°å½æ¡æ°ãç±äºå·²ç»å¼ºå¶ç¡®å®äºé©±å¨è¡¨å被驱å¨è¡¨ï¼ä¸é¢æä»¬è¯´ä¸ä¸ä¸¤è¡¨è¿æ¥çæ¬è´¨ï¼
- t1ä½ä¸ºé©±å¨è¡¨ï¼é对驱å¨è¡¨çè¿æ»¤æ¡ä»¶ï¼æ§è¡å¯¹t1è¡¨çæ¥è¯¢ãå 为没æè¿æ»¤æ¡ä»¶ï¼ä¹å°±æ¯è·åt1è¡¨çæææ°æ®ï¼
- 对ä¸ä¸æ¥ä¸è·åå°çç»æéä¸çæ¯ä¸æ¡è®°å½ï¼é½åå«å°è¢«é©±å¨è¡¨ä¸ï¼æ ¹æ®è¿æ¥è¿æ»¤æ¡ä»¶æ¥æ¾å¹é è®°å½
ç¨ä¼ªä»£ç 表示çè¯æ´ä¸ªè¿ç¨æ¯è¿æ ·çï¼
// t1Resæ¯é对驱å¨è¡¨t1è¿æ»¤ä¹åçç»æé
for (t1Row : t1Res){
// t2æ¯å®æ´ç被驱å¨è¡¨
for(t2Row : t2){
if (满足joinæ¡ä»¶ && 满足t2çè¿æ»¤æ¡ä»¶){
åéç»å®¢æ·ç«¯
}
}
}
è¿ç§æ¹æ³æç®åï¼ä½åæ¶æ§è½ä¹æ¯æå·®ï¼è¿ç§æ¹å¼å«ååµå¥å¾ªç¯è¿æ¥ï¼Nested-LoopJoinï¼NLJï¼ãæä¹å å¿«è¿æ¥é度å¢ï¼
å ¶ä¸ä¸ä¸ªåæ³å°±æ¯å建索å¼ï¼æå¥½æ¯å¨è¢«é©±å¨è¡¨ï¼t2ï¼è¿æ¥æ¡ä»¶æ¶åå°çåæ®µä¸å建索å¼ï¼æ¯ç«è¢«é©±å¨è¡¨éè¦è¢«æ¥è¯¢å¥½å¤æ¬¡ï¼èä¸å¯¹è¢«é©±å¨è¡¨çè®¿é®æ¬è´¨ä¸å°±æ¯ä¸ªå表æ¥è¯¢èå·²ï¼å 为t1ç»æéå®äºï¼æ¯æ¬¡è¿æ¥t2çæ¥è¯¢æ¡ä»¶ä¹å°±å®æ»äºï¼ã
æ¢ç¶ä½¿ç¨äºç´¢å¼ï¼ä¸ºäºé¿å éè¹æ æ³ä½¿ç¨è¦çç´¢å¼çè¦è¾ï¼æä»¬ä¹åºè¯¥å°½éä¸è¦ç´æ¥SELECT *ï¼èæ¯å°çæ£ç¨å°çåæ®µä½ä¸ºæ¥è¯¢åï¼å¹¶ä¸ºå ¶å»ºç«éå½çç´¢å¼ã
使¯å¦ææä»¬ä¸ä½¿ç¨ç´¢å¼ï¼MySQLå°±ççæç §åµå¥å¾ªç¯æ¥è¯¢çæ¹å¼è¿è¡è¿æ¥æ¥è¯¢åï¼å½ç¶ä¸æ¯ï¼æ¯ç«è¿ç§åµå¥å¾ªç¯æ¥è¯¢å®å¨æ¯å¤ªæ ¢äºï¼
å¨MySQL8.0ä¹åï¼MySQLæä¾äºåºäºåçåµå¥å¾ªç¯è¿æ¥ï¼Block Nested-Loop Joinï¼BLJï¼æ¹æ³ï¼MySQL8.0忍åºäºhash joinæ¹æ³ï¼è¿ä¸¤ç§æ¹æ³é½æ¯ä¸ºäºè§£å³ä¸ä¸ªé®é¢èæåºçï¼é£å°±æ¯å°½éåå°è¢«é©±å¨è¡¨çè®¿é®æ¬¡æ°ã
è¿ä¸¤ç§æ¹æ³é½ç¨å°äºä¸ä¸ªå«åjoin bufferçåºå®å¤§å°çå ååºåï¼å ¶ä¸åå¨çè¥å¹²æ¡é©±å¨è¡¨ç»æéä¸çè®°å½ï¼è¿ä¸¤ç§æ¹æ³çåºå«å°±æ¯åå¨çå½¢å¼ä¸åèå·²ï¼ï¼å¦æ¤ä¸æ¥ï¼æè¢«é©±å¨è¡¨çè®°å½å è½½å°å åçæ¶åï¼ä¸æ¬¡æ§åjoin bufferä¸å¤æ¡é©±å¨è¡¨ä¸çè®°å½åå¹é ï¼å 为å¹é çè¿ç¨é½æ¯å¨å åä¸å®æçï¼æä»¥è¿æ ·å¯ä»¥æ¾èåå°è¢«é©±å¨è¡¨çI/O代价ï¼å¤§å¤§åå°äºéå¤ä»ç£çä¸å 载被驱å¨è¡¨ç代价ã使ç¨join bufferçè¿ç¨å¦ä¸å¾æç¤ºï¼
join buffer示æå¾
æä»¬çä¸ä¸ä¸é¢çè¿æ¥æ¥è¯¢çæ§è¡è®¡åï¼åç°ç¡®å®ä½¿ç¨å°äºhash joinï¼åææ¯æ²¡æä¸ºt2表çè¿æ¥æ¥è¯¢å段å建索å¼ï¼å¦åå°±ä¼ä½¿ç¨ç´¢å¼ï¼ä¸ä¼ä½¿ç¨join bufferï¼ã
æå¥½çæ 嵿¯join bufferè¶³å¤å¤§ï¼è½å®¹çº³é©±å¨è¡¨ç»æéä¸çææè®°å½ï¼è¿æ ·åªéè¦è®¿é®ä¸æ¬¡è¢«é©±å¨è¡¨å°±å¯ä»¥å®æè¿æ¥æä½äºãæä»¬å¯ä»¥ä½¿ç¨join_buffer_sizeè¿ä¸ªç³»ç»åéè¿è¡é ç½®ï¼é»è®¤å¤§å°ä¸º256KBã妿è¿è£ ä¸ä¸ï¼å°±å¾åæ¹æé©±å¨è¡¨çç»æéæ¾å°join bufferä¸äºï¼å¨å åä¸å¯¹æ¯å®æä¹åï¼æ¸ 空join bufferåè£ å ¥ä¸ä¸æ¹ç»æéï¼ç´å°è¿æ¥å®æä¸ºæ¢ã
éç¹æ¥äºï¼å¹¶ä¸æ¯é©±å¨è¡¨è®°å½çææåé½ä¼è¢«æ¾å°join bufferä¸ï¼åªææ¥è¯¢å表ä¸çååè¿æ»¤æ¡ä»¶ä¸çåæä¼è¢«æ¾å°join bufferä¸ï¼æä»¥å次æéæä»¬ï¼æå¥½ä¸è¦æ*ä½ä¸ºæ¥è¯¢å表ï¼åªéè¦ææä»¬å ³å¿ç忾尿¥è¯¢å表就好äºï¼è¿æ ·è¿å¯ä»¥å¨join buffer䏿¾ç½®æ´å¤çè®°å½ï¼åå°åæ¹ç次æ°ï¼ä¹å°±èªç¶åå°äºå¯¹è¢«é©±å¨è¡¨çè®¿é®æ¬¡æ°ã