1. ä»ä¹æ¯ç´¢å¼
ç´¢å¼æ¯å¸®å©æ°æ®åºé«æè·åæ°æ®çæ°æ®ç»æãç®èè¨ä¹,ç´¢å¼æ¯æ°æ®ç»æ
2. ç´¢å¼çåºå±æ°æ®ç»æ
2.1 Hashç´¢å¼
åå¸è¡¨æ¯é®å¼å¯¹çéåï¼éè¿é®(key)å³å¯å¿«éååºå¯¹åºçå¼(value)ï¼å æ¤åå¸è¡¨å¯ä»¥å¿«éæ£ç´¢æ°æ®ï¼æ¥è¿ Oï¼1ï¼ï¼ã
为ä½è½å¤éè¿ key å¿«éååº valueå¢ï¼ åå å¨äº åå¸ç®æ³ï¼ä¹å«æ£åç®æ³ï¼ãéè¿åå¸ç®æ³ï¼æä»¬å¯ä»¥å¿«éæ¾å° value 对åºç indexï¼æ¾å°äº index ä¹å°±æ¾å°äºå¯¹åºç valueã
index = hash % array.size()

使¯ï¼åå¸ç®æ³æä¸ª Hash å²çª é®é¢ï¼ä¹å°±æ¯è¯´å¤ä¸ªä¸åç key æåå¾å°ç index ç¸åãé常æ åµä¸ï¼æä»¬å¸¸ç¨çè§£å³åæ³æ¯ é¾å°åæ³ãé¾å°åæ³å°±æ¯å°åå¸å²çªæ°æ®åæ¾å¨é¾è¡¨ä¸ãå°±æ¯å¦ JDK1.8 ä¹å HashMap å°±æ¯éè¿é¾å°åæ³æ¥è§£å³åå¸å²çªçãä¸è¿ï¼JDK1.8 以åHashMap为äºåå°é¾è¡¨è¿é¿çæ¶åæç´¢æ¶é´è¿é¿å¼å ¥äºçº¢é»æ ã
为ä»ä¹MySQL 没æä½¿ç¨å ¶ä½ä¸ºç´¢å¼çæ°æ®ç»æå¢ï¼
- Hash å²çªé®é¢ ï¼æä»¬ä¸é¢ä¹æå°è¿Hash å²çªäºï¼ä¸è¿å¯¹äºæ°æ®åºæ¥è¯´è¿è¿ä¸ç®æå¤§ç缺ç¹ã
- Hash ç´¢å¼ä¸æ¯æé¡ºåºåèå´æ¥è¯¢(Hash ç´¢å¼ä¸æ¯æé¡ºåºåèå´æ¥è¯¢æ¯å®æå¤§ç缺ç¹ï¼ hashç´¢å¼ä¸åå¨çå°±æ¯Hashç ï¼hash ç å½¼æ¤ä¹é´æ¯æ²¡æè§å¾çï¼ä¸ Hash æä½å¹¶ä¸è½ä¿è¯é¡ºåºæ§ï¼æä»¥å¼ç¸è¿çä¸¤ä¸ªæ°æ®ï¼Hashå¼ç¸å·®å¾è¿ï¼è¢«åå°ä¸åçæ¡¶ä¸ã
2.2 æ
æå¾å¤æ å¯ä»¥ä½ä¸ºç´¢å¼çæ°æ®ç»æï¼ä½mysqlçInnoDB使ç¨b+æ
-
B+ æ
åæ¥è¯´å°±æ¯ä¸ç§ä¸ºç£çæè å ¶ä»åå¨è®¾å¤è设计çä¸ç§å¹³è¡¡äºåæ ,å¨B+tree䏿æè®°å½é½æç §keyç大å°åæ¾å¨å¶åç»ç¹ä¸ï¼åå¶åç»ç¹ç´æ¥ç¨æéè¿æ¥
-
äºåæç´¢æ
äºåæç´¢æ çè§åæ¯ç¶èç¹å¤§äºå·¦å©åèç¹ï¼å°äºå³å©åèç¹
-
平衡äºåæ
é¦å æ¯ä¸ä¸ªäºåæç´¢æ ï¼ä½æ¯è¦æ±ä»»æä¸ä¸ªèç¹çå·¦å³å©åèç¹çé«åº¦å·®ä¸å¤§äº1
-
Bæ
é¦å æ¯ä¸ä¸ªå¹³è¡¡äºåæ ï¼ä½æ¯åè¦æ±æ¯ä¸ªå¶åèç¹å°æ ¹èç¹çè·ç¦»ç¸ç
é£ä¹Bæ åB+æ çåºå«æ¯ä»ä¹å¢ï¼
- B+æ çå¶åèç¹å¯ä»¥å å«ä¸ä¸ªæéï¼æåå¦ä¸ä¸ªå¶åèç¹
- B+æ é®å¼çæ·è´åå¨éå¶åèç¹ï¼é®å¼+è®°å½åå¨å¨å¶åèç¹
2.2.1 B æ & B+æ
B æ ä¹ç§° B-æ ,å ¨ç§°ä¸º å¤è·¯å¹³è¡¡æ¥æ¾æ ï¼B+ æ æ¯ B æ çä¸ç§åä½ãB æ å B+æ ä¸ç B æ¯ Balanced ï¼å¹³è¡¡ï¼çææã
ç®å大é¨åæ°æ®åºç³»ç»åæä»¶ç³»ç»é½éç¨ B-Tree æå ¶åç§ B+Tree ä½ä¸ºç´¢å¼ç»æã
B æ & B+æ ä¸¤è æä½å¼åå¢ï¼
- B æ çææèç¹æ¢åæ¾é®(key) ä¹åæ¾ æ°æ®(data)ï¼èB+æ åªæå¶åèç¹åæ¾ key å dataï¼å ¶ä»å èç¹åªåæ¾ keyã
- B æ çå¶åèç¹é½æ¯ç¬ç«ç;B+æ çå¶åèç¹æä¸æ¡å¼ç¨é¾æåä¸å®ç¸é»çå¶åèç¹ã
- B æ çæ£ç´¢çè¿ç¨ç¸å½äºå¯¹èå´å çæ¯ä¸ªèç¹çå ³é®ååäºåæ¥æ¾ï¼å¯è½è¿æ²¡æå°è¾¾å¶åèç¹ï¼æ£ç´¢å°±ç»æäºãè B+æ çæ£ç´¢æçå°±å¾ç¨³å®äºï¼ä»»ä½æ¥æ¾é½æ¯ä»æ ¹èç¹å°å¶åèç¹çè¿ç¨ï¼å¶åèç¹çé¡ºåºæ£ç´¢å¾ææ¾ã
2.2.2 为ä»ä¹è¦ç¨b+æ ?
æ°æ®åºåå¨çæ°æ®å®é 䏿¯åå¨ç£çä¸çï¼ä¹æä»¥éæ©b+æ ä¹åè¿ä¸ªæå ³ã
2.2.2.1 ç£ç
ä¸é¢æä»¬ç®åäºè§£ä¸ä¸ç£çæ¯å¦ä½å·¥ä½çã
ç£ç大æ¦é¿è¿ä¸ªæ ·åï¼
ç£ç主è¦ç±ç£çççãä¼ å¨æèã读åç£å¤´åé©¬è¾¾ç»æã
为äºåå¨å®¹é,主轴åç©¿ç³è«è¦ä¸æ ·æå¤ä¸ªç£ççç»æä¸ä¸ªéµåãéè¿é©¬è¾¾é©±å¨ä¸»è½´è½¬å¨ä»¥åä¼ å¨æèç§»å¨ï¼ä½¿è¯»åç£å¤´å¨ç£ççä¸è¯»åæ°æ®ã大æ¦å¦ä¸ï¼
ç£ççç±å¾å¤åå¾ä¸ççåå¿åç»æï¼è¿äºå被称为ç£éï¼æ°æ®å°±æ¯åå¨è¿äºç£éä¸ã
æ¯ä¸ªç£éåååæå称为æåºã
妿ç£çæ¯ä¸è®°äºæ¬ï¼é£ä¹ä¸å¼ ç£ççå°±æ¯æ¬åçä¸é¡µçº¸ï¼èä¸»è½´å°±æ¯æ¬åçè£ è®¢çº¿ï¼ç£éå°±æ¯çº¸é¡µçè¡ï¼èæåºå¯ä»¥ç使¯å¾å®½çåã
妿å¨ç£çä¸åå¨ä¸é¦è¯,æ³è±¡ä¸å¤§æ¦è¿ä¸ªæ ·åã
ç£çç读 I/O æä½,éè¦æ¾å°æ°æ®æå¨çç£ççï¼ä»¥å对åºçç£éåæåºãè¿äºæä½ç±»ä¼¼äºä»ä¸æ¬ä¹¦ä¸æ¾å°æ°æ®æå¨ç页ï¼è¡ï¼åã
å 为æ¯ä¸ªç£ççé½å¯¹åºä¸ä¸ªç£å¤´ï¼æä»¥æ§è½çå ³é®å°±å¨äºæ¾è¡ååï¼å³å¯»éåç£çæè½¬ã寻éå³éè¿ç£å¤´æ¾å°æ°æ®æå¨çç£éï¼ç¸å½äºæ¢è¡å°æ°æ®æå¨è¡ãç±äºç£å¤´åªè½æ°´å¹³ç§»å¨ï¼å³åªè½æ¢è¡å¯»éï¼æ æ³å¨æå®ç£éä¸ç§»å¨ï¼å æ¤éè¦ç£çé«éæè½¬ç§»å¨å°æå®æåºï¼ç±»ä¼¼åæ¥èæ¶ï¼ç¬ä¸å¨ï¼çº¸å¨ã
ç»¼ä¸æè¿°ï¼ç£ççè¯»åæ¯éè¿æºæ¢°è¿å¨æ¥å®ä½æ°æ®æå¨ä½ç½®ï¼è cpu æ¯éè¿çµä¿¡å·è¿è¡æ°åè¿ç®ãç²ç¥çè®¤ä¸ºï¼æºæ¢°æ¥è¯¢æ°æ®ï¼ä¸å éå¤çæ°æ®çæ§è½å®å ¨ä¸æ¯å¨ä¸ä¸ªéçº§ï¼æ»ä¹ä¸å¥è¯å°±æ¯ç£çå¤çå¤ªæ ¢å¤ªæ ¢äºã
è½ç¶ç£çå¤çæ°æ®å¤ªæ ¢äºï¼ä½æ¯å®æ¯ç®åç¸å¯¹å»ä»·ä¸ç¨³å®çåå¨è®¾å¤ï¼æä»¥åä¸è½èå¼ä¸ç¨ï¼ä½å¤§è´å¯ä»¥éè¿ä»¥ä¸æ¹æ³è¿è¡ä¼åã
- å°½éåå° I/O 次æ°ï¼æ¯å¦å¯ä»¥ä½¿ç¨ç¼å
- æ¯æ¬¡ I/O å°½éè·åæ´å¤çæ°æ®
- æ¯æ¬¡ I/O å°½éè·åæç¨çæ°æ®ï¼å½ç¶ç¸åºçä¹é´æ¥åå°æ» I/O 次æ°
2.2.2.2 为ä»ä¹ç¨b+æ 䏿¯bæ
ä¸æä¸ºäºè§£å³ç£çå¤çæ°æ®å¤ªæ ¢çé®é¢ï¼æä»¬å¯ä»¥ä»ï¼å°½éåå° I/O 次æ°ï¼æ¯å¦å¯ä»¥ä½¿ç¨ç¼åï¼æ¯æ¬¡ I/O å°½éè·åæ´å¤çæ°æ®ï¼æ¯æ¬¡ I/O å°½éè·åæç¨çæ°æ®ï¼å½ç¶ç¸åºçä¹é´æ¥åå°æ» I/O 次æ°ï¼è¿ä¸ç¹åºåãå¯ä»¥åç°bæ å¾ç¬¦åç£çå¤çï¼å®å è½½ä¸æ¬¡èç¹ï¼å¯ä»¥å è½½å¾å¤è·¯å¾æ°æ®ï¼åæ¶ææ¥è¯¢èå´ç¼©åå°æ´å°ã大大åå°äº I/O æ¬¡æ°æè 坻鿬¡æ°ã
使¯bæ ä»ç¶æä¸ä¸ªè´å½ç缺é·ï¼é£å°±æ¯å®çç´¢å¼æ°æ®ä¸ä¸å¡ç»å®å¨ä¸åï¼èä¸å¡æ°æ®ç大å°å¾æå¯è½è¿è¿è¶ è¿äºç´¢å¼æ°æ®ï¼è¿ä¼å¤§å¤§åå°ä¸æ¬¡ I/O æç¨æ°æ®çè·åï¼é´æ¥çå¢å I/O 次æ°å»è·åæç¨çç´¢å¼æ°æ®ã
å 为ä¸å¡æ°æ®ææ¯æä»¬æ¥è¯¢æç»çç®çï¼ä½æ¯å®åæ¯å¨ãäºåãæ¥æ¾ä¸éè¿ç¨æ ç¨çæ°æ®ï¼å æ¤ï¼å¦æåªæä¸å¡æ°æ®åå¨å¨æç»æ¥è¯¢å°çé£ä¸ªèç¹æ¯ä¸æ¯å°±å¯ä»¥äºï¼è¿å ¶å®å°±æ¯b+æ ã
B+ æ ä¸ï¼éå¶åèç¹åªä¿åç´¢å¼æ°æ®ï¼å¶åèç¹ä¿åç´¢å¼æ°æ®ä¸ä¸å¡æ°æ®ãè¿æ ·å³ä¿è¯äºå¶åèç¹çç®çº¦å¹²åï¼æ°æ®é大大åå°ï¼åä¿è¯äºæç»è½æ¥å°å¯¹åºçä¸å¡æ°ãæ¢æé«äºå次 I/O æ°æ®çæææ§ï¼ååå°äº I/O 次æ°ï¼è¿å®ç°äºä¸å¡ã
2.2.3 ä¸å弿ä¸B+æ çåºå«
å¨ MySQL ä¸ï¼MyISAM 弿å InnoDB 弿齿¯ä½¿ç¨ B+Tree ä½ä¸ºç´¢å¼ç»æï¼ä½æ¯ï¼ä¸¤è çå®ç°æ¹å¼ä¸å¤ªä¸æ ·ãï¼ä¸é¢çå 容æ´çèªãJava å·¥ç¨å¸ä¿®ç¼ä¹éãï¼
MyISAM 弿ä¸ï¼B+Tree å¶èç¹ç data ååæ¾çæ¯æ°æ®è®°å½çå°åãå¨ç´¢å¼æ£ç´¢çæ¶åï¼é¦å æç § B+Tree æç´¢ç®æ³æç´¢ç´¢å¼ï¼å¦ææå®ç Key åå¨ï¼åååºå ¶ data åçå¼ï¼ç¶å以 data åçå¼ä¸ºå°å读åç¸åºçæ°æ®è®°å½ãè¿è¢«ç§°ä¸ºâéèç°ç´¢å¼âã
InnoDB 弿ä¸ï¼å ¶æ°æ®æä»¶æ¬èº«å°±æ¯ç´¢å¼æä»¶ãç¸æ¯ MyISAMï¼ç´¢å¼æä»¶åæ°æ®æä»¶æ¯å离çï¼å ¶è¡¨æ°æ®æä»¶æ¬èº«å°±æ¯æ B+Tree ç»ç»çä¸ä¸ªç´¢å¼ç»æï¼æ çå¶èç¹ data åä¿åäºå®æ´çæ°æ®è®°å½ãè¿ä¸ªç´¢å¼ç key æ¯æ°æ®è¡¨ç主é®ï¼å æ¤ InnoDB è¡¨æ°æ®æä»¶æ¬èº«å°±æ¯ä¸»ç´¢å¼ãè¿è¢«ç§°ä¸ºâèç°ç´¢å¼ï¼æèéç´¢å¼ï¼âï¼èå ¶ä½çç´¢å¼é½ä½ä¸ºè¾ å©ç´¢å¼ï¼è¾ å©ç´¢å¼ç data ååå¨ç¸åºè®°å½ä¸»é®çå¼è䏿¯å°åï¼è¿ä¹æ¯å MyISAM ä¸åçå°æ¹ã卿 ¹æ®ä¸»ç´¢å¼æç´¢æ¶ï¼ç´æ¥æ¾å° key æå¨çèç¹å³å¯ååºæ°æ®ï¼å¨æ ¹æ®è¾ å©ç´¢å¼æ¥æ¾æ¶ï¼åéè¦å ååºä¸»é®çå¼ï¼å¨èµ°ä¸é主索å¼ã å æ¤ï¼å¨è®¾è®¡è¡¨çæ¶åï¼ä¸å»ºè®®ä½¿ç¨è¿é¿çåæ®µä½ä¸ºä¸»é®ï¼ä¹ä¸å»ºè®®ä½¿ç¨éåè°çåæ®µä½ä¸ºä¸»é®ï¼è¿æ ·ä¼é æä¸»ç´¢å¼é¢ç¹åè£ã
3. ç´¢å¼çåç±»
3.1 æ ¹æ®åºç¨åºå
3.1.1 主é®ç´¢å¼
æ°æ®è¡¨ç主é®å使ç¨çå°±æ¯ä¸»é®ç´¢å¼ã
ä¸å¼ æ°æ®è¡¨æåªè½æä¸ä¸ªä¸»é®ï¼å¹¶ä¸ä¸»é®ä¸è½ä¸º nullï¼ä¸è½éå¤ã
å¨ MySQL ç InnoDB ç表ä¸ï¼å½æ²¡ææ¾ç¤ºçæå®è¡¨ç䏻鮿¶ï¼InnoDB ä¼èªå¨å æ£æ¥è¡¨ä¸æ¯å¦æå¯ä¸ç´¢å¼çåæ®µï¼å¦ææï¼åéæ©è¯¥åæ®µä¸ºé»è®¤ç主é®ï¼å¦å InnoDB å°ä¼èªå¨å建ä¸ä¸ª 6Byte çèªå¢ä¸»é®ã
3.1.2 äºçº§ç´¢å¼(è¾ å©ç´¢å¼)
äºçº§ç´¢å¼åç§°ä¸ºè¾ å©ç´¢å¼ï¼æ¯å 为äºçº§ç´¢å¼çå¶åèç¹åå¨çæ°æ®æ¯ä¸»é®ãä¹å°±æ¯è¯´ï¼éè¿äºçº§ç´¢å¼ï¼å¯ä»¥å®ä½ä¸»é®çä½ç½®ã
å¯ä¸ç´¢å¼ï¼æ®éç´¢å¼ï¼åç¼ç´¢å¼çç´¢å¼å±äºäºçº§ç´¢å¼ã
- å¯ä¸ç´¢å¼(Unique Key) ï¼å¯ä¸ç´¢å¼ä¹æ¯ä¸ç§çº¦æãå¯ä¸ç´¢å¼ç屿§åä¸è½åºç°éå¤çæ°æ®ï¼ä½æ¯å è®¸æ°æ®ä¸º NULLï¼ä¸å¼ 表å 许å建å¤ä¸ªå¯ä¸ç´¢å¼ã建ç«å¯ä¸ç´¢å¼çç®ç大é¨åæ¶å齿¯ä¸ºäºè¯¥å±æ§åçæ°æ®çå¯ä¸æ§ï¼è䏿¯ä¸ºäºæ¥è¯¢æçã
- æ®éç´¢å¼(Index) ï¼æ®éç´¢å¼çå¯ä¸ä½ç¨å°±æ¯ä¸ºäºå¿«éæ¥è¯¢æ°æ®ï¼ä¸å¼ 表å 许å建å¤ä¸ªæ®éç´¢å¼ï¼å¹¶å è®¸æ°æ®éå¤å NULLã
- åç¼ç´¢å¼(Prefix) ï¼åç¼ç´¢å¼åªéç¨äºå符串类åçæ°æ®ãåç¼ç´¢å¼æ¯å¯¹ææ¬çåå 个å符å建索å¼ï¼ç¸æ¯æ®éç´¢å¼å»ºç«çæ°æ®æ´å°ï¼ å 为åªååå 个å符ã
- å ¨æç´¢å¼(Full Text) ï¼å ¨æç´¢å¼ä¸»è¦æ¯ä¸ºäºæ£ç´¢å¤§ææ¬æ°æ®ä¸çå ³é®åçä¿¡æ¯ï¼æ¯ç®åæç´¢å¼ææ°æ®åºä½¿ç¨çä¸ç§ææ¯ãMysql5.6 ä¹ååªæ MYISAM å¼ææ¯æå ¨æç´¢å¼ï¼5.6 ä¹å InnoDB 乿¯æäºå ¨æç´¢å¼ã
3.2 æ ¹æ®ç´¢å¼åæ°æ®æ¯å¦åå¼åºå
3.2.1 èç°ç´¢å¼
èç°ç´¢å¼å³ç´¢å¼ç»æåæ°æ®ä¸èµ·åæ¾çç´¢å¼ã主é®ç´¢å¼å±äºèç°ç´¢å¼ã
å¦æè¡¨è®¾ç½®äºä¸»é®ï¼å主é®å°±æ¯èç°ç´¢å¼
å¦æè¡¨æ²¡æä¸»é®ï¼åä¼é»è®¤ç¬¬ä¸ä¸ªNOT NULLï¼ä¸å¯ä¸ï¼UNIQUEï¼çåä½ä¸ºèç°ç´¢å¼
以ä¸é½æ²¡æï¼åä¼é»è®¤å建ä¸ä¸ªéèçrow_idä½ä¸ºèç°ç´¢å¼
èç°ç´¢å¼çä¼ç¹
èç°ç´¢å¼çæ¥è¯¢é度é常çå¿«ï¼å 为æ´ä¸ª B+æ æ¬èº«å°±æ¯ä¸é¢å¤å平衡æ ï¼å¶åèç¹ä¹é½æ¯æåºçï¼å®ä½å°ç´¢å¼çèç¹ï¼å°±ç¸å½äºå®ä½å°äºæ°æ®ã
èç°ç´¢å¼ç缺ç¹
- ä¾èµäºæåºçæ°æ® ï¼å 为 B+æ æ¯å¤è·¯å¹³è¡¡æ ï¼å¦æç´¢å¼çæ°æ®ä¸æ¯æåºçï¼é£ä¹å°±éè¦å¨æå ¥æ¶æåºï¼å¦ææ°æ®æ¯æ´åè¿å¥½ï¼å¦å类似äºå符串æ UUID è¿ç§åé¿å龿¯è¾çæ°æ®ï¼æå ¥ææ¥æ¾çé度è¯å®æ¯è¾æ ¢ã
- æ´æ°ä»£ä»·å¤§ ï¼ å¦æå¯¹ç´¢å¼åçæ°æ®è¢«ä¿®æ¹æ¶ï¼é£ä¹å¯¹åºçç´¢å¼ä¹å°ä¼è¢«ä¿®æ¹ï¼ èä¸åµèç°ç´¢å¼çå¶åèç¹è¿åæ¾çæ°æ®ï¼ä¿®æ¹ä»£ä»·è¯å®æ¯è¾å¤§çï¼ æä»¥å¯¹äºä¸»é®ç´¢å¼æ¥è¯´ï¼ä¸»é®ä¸è¬é½æ¯ä¸å¯è¢«ä¿®æ¹çã
3.2.2 éèç°ç´¢å¼
éèç°ç´¢å¼å³ç´¢å¼ç»æåæ°æ®åå¼åæ¾çç´¢å¼ãäºçº§ç´¢å¼å±äºéèç°ç´¢å¼ã
éèç°ç´¢å¼çä¼ç¹
æ´æ°ä»£ä»·æ¯èç°ç´¢å¼è¦å° ãéèç°ç´¢å¼çæ´æ°ä»£ä»·å°±æ²¡æèç°ç´¢å¼é£ä¹å¤§äºï¼éèç°ç´¢å¼çå¶åèç¹æ¯ä¸åæ¾æ°æ®ç
éèç°ç´¢å¼ç缺ç¹
è·èç°ç´¢å¼ä¸æ ·ï¼éèç°ç´¢å¼ä¹ä¾èµäºæåºçæ°æ®
å¯è½ä¼äºæ¬¡æ¥è¯¢(å表) :è¿åºè¯¥æ¯éèç°ç´¢å¼æå¤§ç缺ç¹äºã 彿¥å°ç´¢å¼å¯¹åºçæéæä¸»é®åï¼å¯è½è¿éè¦æ ¹æ®æéæä¸»é®åå°æ°æ®æä»¶æè¡¨ä¸æ¥è¯¢ã
妿è¿ä¸æ¸ æ¥èç°ç´¢å¼åéèç°ç´¢å¼ãçäºä¸é¢å表åè¦çç´¢å¼å°±ç¥éäºã
4. å表æ¥è¯¢åè¦çç´¢å¼
4.1 ä»ä¹æ¯å表æ¥è¯¢
ç¬¬ä¸æ¬¡å éè¿éèç°ç´¢å¼æç´¢å¾å°ä¸»é®ï¼ç¶ååéè¿ä¸»é®å»æç´¢å徿éè¦çæ°æ®ï¼è¿è¡äºä¸¤æ¬¡æç´¢æä»¥å«å表ãçè§£ä¸äºçä¸ä¸ä¸é¢çä¾åå°±ç¥éäºã
示ä¾
建表
id åæ®µæ¯ä¸»é®ç´¢å¼ï¼å±äºèç°ç´¢å¼ï¼age åæ®µæ¯æ®éç´¢å¼ï¼äºçº§ç´¢å¼ï¼
mysql> create table user(
-> id int(10) auto_increment,
-> name varchar(30),
-> age tinyint(4),
-> primary key (id),
-> index idx_age (age)
-> )engine=innodb charset=utf8mb4;
å¡«å æ°æ®
insert into user(name,age) values('å¼ ä¸',30);
insert into user(name,age) values('æå',20);
insert into user(name,age) values('çäº',40);
insert into user(name,age) values('åå
«',10);
mysql> select * from user;
+----+--------+------+
| id | name | age |
+----+--------+------+
| 1 | å¼ ä¸ | 30 |
| 2 | æå | 20 |
| 3 | çäº | 40 |
| 4 | åå
« | 10 |
+----+--------+------+
ç´¢å¼åå¨ç»æ
id æ¯ä¸»é®ï¼æä»¥æ¯èç°ç´¢å¼ï¼å ¶å¶åèç¹åå¨çæ¯å¯¹åºè¡è®°å½çæ°æ®
èç°ç´¢å¼ï¼ClusteredIndexï¼
èç°ç´¢å¼å³ç´¢å¼ç»æåæ°æ®ä¸èµ·åæ¾çç´¢å¼ãå¯¹äº InnoDB å¼æè¡¨æ¥è¯´ï¼è¯¥è¡¨çç´¢å¼(B+æ )çæ¯ä¸ªéå¶åèç¹åå¨ç´¢å¼ï¼å¶åèç¹åå¨ç´¢å¼åç´¢å¼å¯¹åºçæ°æ®ã
æ®éç´¢å¼ï¼secondaryIndexï¼
age æ¯æ®éç´¢å¼ï¼äºçº§ç´¢å¼ï¼ï¼éèç°ç´¢å¼ï¼å ¶å¶åèç¹åå¨çæ¯èç°ç´¢å¼ççå¼
ç´¢å¼æ¥æ¾è¿ç¨
èç°ç´¢å¼æ¥æ¾è¿ç¨
妿æ¥è¯¢æ¡ä»¶ä¸ºä¸»é®ï¼èç°ç´¢å¼ï¼ï¼ååªéæ«æä¸æ¬¡B+æ å³å¯éè¿èç°ç´¢å¼å®ä½å°è¦æ¥æ¾çè¡è®°å½æ°æ®ã
å¦ï¼select * from user where id = 1;
æ®éç´¢å¼æ¥æ¾è¿ç¨
妿æ¥è¯¢æ¡ä»¶ä¸ºæ®éç´¢å¼ï¼éèç°ç´¢å¼ï¼ï¼éè¦æ«æä¸¤æ¬¡B+æ ï¼ç¬¬ä¸æ¬¡æ«æéè¿æ®éç´¢å¼å®ä½å°èç°ç´¢å¼çå¼ï¼ç¶åç¬¬äºæ¬¡æ«æéè¿èç°ç´¢å¼çå¼å®ä½å°è¦æ¥æ¾çè¡è®°å½æ°æ®ã
å¦ï¼select * from user where age = 30;
- å éè¿æ®éç´¢å¼ age=30 å®ä½å°ä¸»é®å¼ id=1
- åéè¿èéç´¢å¼ id=1 å®ä½å°è¡è®°å½æ°æ®
4.2 è¦çç´¢å¼
4.2.1 ä»ä¹æ¯è¦çç´¢å¼
åªéè¦å¨ä¸æ£µç´¢å¼æ ä¸å°±è½è·åSQLæéçææåæ°æ®ï¼æ éå表ï¼é度æ´å¿«ã
示ä¾
select id,age from user where age = 10;
è¿æ¯ä¹åçæç´¢è¿ç¨ï¼ä½æ¯éè¿æ®éç´¢å¼ age=30 å®ä½å°ä¸»é®å¼ id=1æ¶å·²ç»æ¯æéçææåæ°æ®äºï¼å æ¤æ éå表
4.2.2 å¦ä½å®ç°è¦çç´¢å¼
å°è¢«æ¥è¯¢çåæ®µï¼å»ºç«å°èåç´¢å¼éå»
select id,age from user where age = 10;
explainåæï¼å 为ageæ¯æ®éç´¢å¼ï¼ä½¿ç¨å°äºageç´¢å¼ï¼éè¿ä¸æ¬¡æ«æB+æ å³å¯æ¥è¯¢å°ç¸åºçç»æï¼è¿æ ·å°±å®ç°äºè¦çç´¢å¼
å建ç»åç´¢å¼
select id,age,name from user where age = 10;
explainåæï¼ageæ¯æ®éç´¢å¼ï¼ä½nameåä¸å¨ç´¢å¼æ ä¸ï¼æä»¥éè¿ageç´¢å¼å¨æ¥è¯¢å°idåageçå¼åï¼éè¦è¿è¡åè¡¨åæ¥è¯¢nameçå¼ãæ¤æ¶çExtraåçNULL表示è¿è¡äºå表æ¥è¯¢ã
è¿ä¸ªæ¶åå¯ä»¥å建ç»åç´¢å¼
drop index idx_age on user;
create index idx_age_name on user(`age`,`name`);
explainåæï¼æ¤æ¶å段ageånameæ¯ç»åç´¢å¼idx_age_nameï¼æ¥è¯¢çåæ®µidãageãnameçå¼ååé½å¨ç´¢å¼æ ä¸ï¼åªéæ«æä¸æ¬¡ç»åç´¢å¼B+æ å³å¯ï¼è¿å°±æ¯å®ç°äºç´¢å¼è¦çï¼æ¤æ¶çExtraåæ®µä¸ºUsing index表示使ç¨äºç´¢å¼è¦çã
4.2.3 ä»ä¹æ¶å使ç¨è¦çç´¢å¼
å ¨è¡¨countæ¥è¯¢ä¼å
mysql> create table user(
-> id int(10) auto_increment,
-> name varchar(30),
-> age tinyint(4),
-> primary key (id),
-> )engine=innodb charset=utf8mb4;
æ¤æ¶
select count(age) from user;
使ç¨ç´¢å¼è¦çä¼åï¼å建ageåæ®µç´¢å¼
create index idx_age on user(age);
åæ¥è¯¢å表ä¼å
åæå¨æè¿°ç´¢å¼è¦ç使ç¨çä¾åå°±æ¯
ä¾å¦ï¼select id,age,name from user where age = 10;
使ç¨ç´¢å¼è¦çï¼å»ºç»åç´¢å¼idx_age_name(age,name)å³å¯
å页æ¥è¯¢
ä¾å¦ï¼select id,age,name from user order by age limit 100,2;
å 为nameåæ®µä¸æ¯ç´¢å¼ï¼æä»¥å¨å页æ¥è¯¢éè¦è¿è¡å表æ¥è¯¢ï¼æ¤æ¶Extra为Using filesortæä»¶æåºï¼æ¥è¯¢æ§è½ä½ä¸ã
使ç¨ç´¢å¼è¦çï¼å»ºç»åç´¢å¼idx_age_name(age,name)
5. Mysqlå¦ä½æä½ç´¢å¼
1.æ·»å PRIMARY KEYï¼ä¸»é®ç´¢å¼ï¼
ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` )
2.æ·»å UNIQUE(å¯ä¸ç´¢å¼)
ALTER TABLE `table_name` ADD UNIQUE ( `column` )
3.æ·»å INDEX(æ®éç´¢å¼)
ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
4.æ·»å FULLTEXT(å ¨æç´¢å¼)
ALTER TABLE `table_name` ADD FULLTEXT ( `column`)
5.æ·»å å¤åç´¢å¼
ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
6.æ¥çç´¢å¼
show index from `table_name`;
7.å é¤ç´¢å¼
drop index `index_name` on `table_name`;
8.强å¶èµ°ç´¢å¼çä¸ç§æ¹å¼
select * from `table_name` force index(`index_name`) where xxx
6. ç´¢å¼ä½¿ç¨åå
6.1 ç´¢å¼ä½¿ç¨è§å-æå·¦å¹é åå(éç¹)
æå·¦å¹é ååï¼æå·¦ä¼å ï¼ä»¥æå·¦è¾¹ç为起ç¹ä»»ä½è¿ç»çç´¢å¼é½è½å¹é ä¸ãåæ¶éå°èå´æ¥è¯¢(>ã<ãbetweenãlike)å°±ä¼åæ¢å¹é ã
ç´¢å¼çåºå±æ¯ä¸é¢B+æ ï¼é£ä¹èåç´¢å¼å½ç¶è¿æ¯ä¸é¢B+æ ï¼åªä¸è¿èåç´¢å¼çå¥å¼æ°é䏿¯ä¸ä¸ªï¼èæ¯å¤ä¸ªãæå»ºä¸é¢B+æ åªè½æ ¹æ®ä¸ä¸ªå¼æ¥æå»ºï¼å æ¤æ°æ®åºä¾æ®èåç´¢å¼æå·¦çåæ®µæ¥æå»ºB+æ ã
åå¦å建ä¸ä¸ªï¼a,b)çèåç´¢å¼ï¼é£ä¹å®çç´¢å¼æ æ¯è¿æ ·ç
å¯ä»¥çå°aç弿¯æé¡ºåºçï¼1ï¼1ï¼2ï¼2ï¼3ï¼3ï¼èbç弿¯æ²¡æé¡ºåºç1ï¼2ï¼1ï¼4ï¼1ï¼2ãæä»¥b = 2è¿ç§æ¥è¯¢æ¡ä»¶æ²¡æåæ³å©ç¨ç´¢å¼ï¼å 为èåç´¢å¼é¦å æ¯æaæåºçï¼bæ¯æ åºçã
åæ¶æä»¬è¿å¯ä»¥åç°å¨aå¼ç¸ççæ åµä¸ï¼bå¼åæ¯æé¡ºåºæåçï¼ä½æ¯è¿ç§é¡ºåºæ¯ç¸å¯¹çãæä»¥æå·¦å¹é ååéä¸èå´æ¥è¯¢å°±ä¼åæ¢ï¼å©ä¸çåæ®µé½æ æ³ä½¿ç¨ç´¢å¼ãä¾å¦a = 1 and b = 2 a,båæ®µé½å¯ä»¥ä½¿ç¨ç´¢å¼ï¼å 为å¨aå¼ç¡®å®çæ åµä¸bæ¯ç¸å¯¹æåºçï¼èa>1and b=2ï¼aåæ®µå¯ä»¥å¹é ä¸ç´¢å¼ï¼ä½bå¼ä¸å¯ä»¥ï¼å 为aç弿¯ä¸ä¸ªèå´ï¼å¨è¿ä¸ªèå´ä¸bæ¯æ åºçã
6.1.1 å ¨å¼å¹é æ¥è¯¢æ¶
select * from table_name where a = '1' and b = '2' and c = '3'
select * from table_name where b = '2' and a = '1' and c = '3'
select * from table_name where c = '3' and b = '2' and a = '1'
ç¨å°äºç´¢å¼
whereåå¥å 个æç´¢æ¡ä»¶é¡ºåºè°æ¢ä¸å½±åæ¥è¯¢ç»æï¼å 为Mysql䏿æ¥è¯¢ä¼åå¨ï¼ä¼èªå¨ä¼åæ¥è¯¢é¡ºåºã
=ãinä¼èªå¨ä¼å顺åº
6.1.2 å¹é 左边çåæ¶
select * from table_name where a = '1'
select * from table_name where a = '1' and b = '2'
select * from table_name where a = '1' and b = '2' and c = '3'
é½ä»æå·¦è¾¹å¼å§è¿ç»å¹é ï¼ç¨å°äºç´¢å¼
select * from table_name where b = '2'
select * from table_name where c = '3'
select * from table_name where b = '1' and c = '3'
è¿äºæ²¡æä»æå·¦è¾¹å¼å§ï¼æåæ¥è¯¢æ²¡æç¨å°ç´¢å¼ï¼ç¨çæ¯å ¨è¡¨æ«æ
select * from table_name where a = '1' and c = '3'
妿ä¸è¿ç»æ¶ï¼åªç¨å°äºaåçç´¢å¼ï¼bååcå齿²¡æç¨å°ï¼æ æ³è·³è¿æä¸ªå使ç¨åç»ç´¢å¼å
6.1.3 å¹é ååç¼
妿忝å符åçè¯å®çæ¯è¾è§åæ¯å æ¯è¾å符串ç第ä¸ä¸ªå符ï¼ç¬¬ä¸ä¸ªå符å°çåªä¸ªå符串就æ¯è¾å°ï¼å¦æä¸¤ä¸ªå符串第ä¸ä¸ªå符ç¸éï¼é£å°±åæ¯è¾ç¬¬äºä¸ªå符ï¼ç¬¬äºä¸ªå符æ¯è¾å°çé£ä¸ªå符串就æ¯è¾å°ï¼ä¾æ¬¡ç±»æ¨ï¼æ¯è¾å符串ã
妿aæ¯å符类åï¼é£ä¹åç¼å¹é ç¨çæ¯ç´¢å¼ï¼åç¼åä¸ç¼åªè½å ¨è¡¨æ«æäº
select * from table_name where a like 'As%'; //åç¼é½æ¯æå¥½åºçï¼èµ°ç´¢å¼æ¥è¯¢
select * from table_name where a like '%As'//å
¨è¡¨æ¥è¯¢
select * from table_name where a like '%As%'//å
¨è¡¨æ¥è¯¢
6.1.4 å¹é èå´å¼
select * from table_name where a > 1 and a < 3
å¯ä»¥å¯¹æå·¦è¾¹çåè¿è¡èå´æ¥è¯¢
select * from table_name where a > 1 and a < 3 and b > 1;
å¤ä¸ªååæ¶è¿è¡èå´æ¥æ¾æ¶ï¼åªæå¯¹ç´¢å¼æå·¦è¾¹çé£ä¸ªåè¿è¡èå´æ¥æ¾æç¨å°B+æ ç´¢å¼ï¼ä¹å°±æ¯åªæaç¨å°ç´¢å¼ï¼å¨1<a<3çèå´å bæ¯æ åºçï¼ä¸è½ç¨ç´¢å¼ï¼æ¾å°1<a<3çè®°å½åï¼åªè½æ ¹æ®æ¡ä»¶ b > 1ç»§ç»éæ¡è¿æ»¤
6.1.5 精确å¹é æä¸åå¹¶èå´å¹é å¦å¤ä¸å
å¦æå·¦è¾¹çåæ¯ç²¾ç¡®æ¥æ¾çï¼å³è¾¹çåå¯ä»¥è¿è¡èå´æ¥æ¾
select * from table_name where a = 1 and b > 3;
a=1çæ åµä¸bæ¯æåºçï¼è¿è¡èå´æ¥æ¾èµ°çæ¯èåç´¢å¼
6.1.6 æåº
ä¸è¬æ åµä¸ï¼æä»¬åªè½æè®°å½å è½½å°å åä¸ï¼åç¨ä¸äºæåºç®æ³ï¼æ¯å¦å¿«éæåºï¼å½å¹¶æåºçå¨å åä¸å¯¹è¿äºè®°å½è¿è¡æåºï¼ææ¶åæ¥è¯¢çç»æé太大ä¸è½å¨å åä¸è¿è¡æåºçè¯ï¼è¿å¯è½ææ¶åå©ç£ç空é´åæ¾ä¸é´ç»æï¼æåºæä½å®æå忿好åºçç»æè¿å客æ·ç«¯ãMysql䏿è¿ç§åå å䏿ç£çä¸è¿è¡æåºçæ¹å¼ç»ç§°ä¸ºæä»¶æåºãæä»¶æåºéå¸¸æ ¢ï¼ä½å¦æorderåå¥ç¨å°äºç´¢å¼åï¼å°±æå¯è½ç廿件æåºçæ¥éª¤
select * from table_name order by a,b,c limit 10;
å 为b+æ ç´¢å¼æ¬èº«å°±æ¯æç §ä¸è¿°è§åæåºçï¼æä»¥å¯ä»¥ç´æ¥ä»ç´¢å¼ä¸æåæ°æ®ï¼ç¶åè¿è¡å表æä½ååºè¯¥ç´¢å¼ä¸ä¸å å«çå就好äº
order byçåå¥åé¢ç顺åºä¹å¿ é¡»æç §ç´¢å¼åç顺åºç»åºï¼æ¯å¦
select * from table_name order by b,c,a limit 10;
è¿ç§é¢ å顺åºç没æç¨å°ç´¢å¼
select * from table_name order by a limit 10;
select * from table_name order by a,b limit 10;
è¿ç§ç¨å°é¨åç´¢å¼
select * from table_name where a =1 order by b,c limit 10;
6.2 å建索å¼ç注æäºé¡¹
- éæ©åéçåæ®µå建索å¼ï¼
- ä¸ä¸º NULL çåæ®µ ï¼ç´¢å¼åæ®µçæ°æ®åºè¯¥å°½éä¸ä¸º NULLï¼å ä¸ºå¯¹äºæ°æ®ä¸º NULL çåæ®µï¼æ°æ®åºè¾é¾ä¼åã妿忮µé¢ç¹è¢«æ¥è¯¢ï¼ä½åé¿å ä¸äºä¸º NULLï¼å»ºè®®ä½¿ç¨ 0,1,true,false è¿æ ·è¯ä¹è¾ä¸ºæ¸ æ°çç弿çå符ä½ä¸ºæ¿ä»£ã
- 被é¢ç¹æ¥è¯¢çåæ®µ ï¼æä»¬å建索å¼çåæ®µåºè¯¥æ¯æ¥è¯¢æä½é常é¢ç¹çåæ®µã
- 被ä½ä¸ºæ¡ä»¶æ¥è¯¢çåæ®µ ï¼è¢«ä½ä¸º WHERE æ¡ä»¶æ¥è¯¢çåæ®µï¼åºè¯¥è¢«èè建ç«ç´¢å¼ã
- é¢ç¹éè¦æåºçåæ®µ ï¼ç´¢å¼å·²ç»æåºï¼è¿æ ·æ¥è¯¢å¯ä»¥å©ç¨ç´¢å¼çæåºï¼å å¿«æåºæ¥è¯¢æ¶é´ã
- 被ç»å¸¸é¢ç¹ç¨äºè¿æ¥çåæ®µ ï¼ç»å¸¸ç¨äºè¿æ¥çåæ®µå¯è½æ¯ä¸äºå¤é®åï¼å¯¹äºå¤é®åå¹¶ä¸ä¸å®è¦å»ºç«å¤é®ï¼åªæ¯è¯´è¯¥åæ¶åå°è¡¨ä¸è¡¨çå ³ç³»ã对äºé¢ç¹è¢«è¿æ¥æ¥è¯¢çåæ®µï¼å¯ä»¥èè建ç«ç´¢å¼ï¼æé«å¤è¡¨è¿æ¥æ¥è¯¢çæçã
-
被é¢ç¹æ´æ°çåæ®µåºè¯¥æ é建ç«ç´¢å¼ã
è½ç¶ç´¢å¼è½å¸¦æ¥æ¥è¯¢ä¸çæçï¼ä½æ¯ç»´æ¤ç´¢å¼çææ¬ä¹æ¯ä¸å°çã 妿ä¸ä¸ªå段ä¸è¢«ç»å¸¸æ¥è¯¢ï¼åè被ç»å¸¸ä¿®æ¹ï¼é£ä¹å°±æ´ä¸åºè¯¥å¨è¿ç§å段ä¸å»ºç«ç´¢å¼äºã
-
å°½å¯è½çèè建ç«èåç´¢å¼è䏿¯ååç´¢å¼ã
å ä¸ºç´¢å¼æ¯éè¦å ç¨ç£ç空é´çï¼å¯ä»¥ç®åç解为æ¯ä¸ªç´¢å¼é½å¯¹åºçä¸é¢ B+æ ã妿ä¸ä¸ªè¡¨çåæ®µè¿å¤ï¼ç´¢å¼è¿å¤ï¼é£ä¹å½è¿ä¸ªè¡¨çæ°æ®è¾¾å°ä¸ä¸ªä½éåï¼ç´¢å¼å ç¨ç空é´ä¹æ¯å¾å¤çï¼ä¸ä¿®æ¹ç´¢å¼æ¶ï¼èè´¹çæ¶é´ä¹æ¯è¾å¤çã妿æ¯èåç´¢å¼ï¼å¤ä¸ªå段å¨ä¸ä¸ªç´¢å¼ä¸ï¼é£ä¹å°ä¼è约å¾å¤§ç£ç空é´ï¼ä¸ä¿®æ¹æ°æ®çæä½æçä¹ä¼æåã
-
注æé¿å åä½ç´¢å¼ã
åä½ç´¢å¼æçæ¯ç´¢å¼çåè½ç¸åï¼è½å¤å½ä¸ç´¢å¼(a, b)å°±è¯å®è½å½ä¸ç´¢å¼(a) ï¼é£ä¹ç´¢å¼(a)å°±æ¯åä½ç´¢å¼ãå¦ï¼name,city ï¼åï¼name ï¼è¿ä¸¤ä¸ªç´¢å¼å°±æ¯åä½ç´¢å¼ï¼è½å¤å½ä¸åè çæ¥è¯¢è¯å®æ¯è½å¤å½ä¸åè çã å¨å¤§å¤æ°æ åµä¸ï¼é½åºè¯¥å°½éæ©å±å·²æçç´¢å¼è䏿¯å建æ°ç´¢å¼ã
-
èèå¨å符串类åçåæ®µä¸ä½¿ç¨åç¼ç´¢å¼ä»£æ¿æ®éç´¢å¼ã
åç¼ç´¢å¼ä» éäºå符串类åï¼è¾æ®éç´¢å¼ä¼å ç¨æ´å°ç空é´ï¼æä»¥å¯ä»¥èè使ç¨åç¼ç´¢å¼å¸¦æ¿æ®éç´¢å¼ã
6.3 ç´¢å¼çä¼ç¼ºç¹
6.3.1 ä¼ç¹
- 使ç¨ç´¢å¼å¯ä»¥å¤§å¤§å å¿« æ°æ®çæ£ç´¢é度ï¼å¤§å¤§åå°æ£ç´¢çæ°æ®éï¼, è¿ä¹æ¯å建索å¼çæä¸»è¦çåå ã
- éè¿å建å¯ä¸æ§ç´¢å¼ï¼å¯ä»¥ä¿è¯æ°æ®åºè¡¨ä¸æ¯ä¸è¡æ°æ®çå¯ä¸æ§ã
- é¿å å ¨è¡¨æ«æï¼å½èµ°ä¸å°ç´¢å¼æ¶ï¼å°±åªè½ä¸ä¸ªä¸ä¸ªçå»å¹é ï¼å¦æèµ°ç´¢å¼ï¼åå¯ä»¥æ ¹æ®Bæ æ¥å®ä½ï¼
- 使ç¨ç´¢å¼å¯ä»¥å¸®å©æå¡å¨é¿å æåºæè 临æ¶è¡¨ ï¼å¶åèç¹ä¸çæéï¼å¯ä»¥ææçæ¯æèå´æ¥è¯¢ï¼æ¤å¤å¶åèç¹æ¬èº«å°±æ¯æ ¹æ®keyè¿è¡æåºçï¼
- ç´¢å¼å°éæºIOåæé¡ºåºIO
6.3.2 缺ç¹
- å建索å¼åç»´æ¤ç´¢å¼éè¦èè´¹è®¸å¤æ¶é´ãå½å¯¹è¡¨ä¸çæ°æ®è¿è¡å¢å æ¹çæ¶åï¼å¦ææ°æ®æç´¢å¼ï¼é£ä¹ç´¢å¼ä¹éè¦å¨æçä¿®æ¹ï¼ä¼éä½ SQL æ§è¡æçã
- ç´¢å¼éè¦ä½¿ç¨ç©çæä»¶åå¨ï¼ä¹ä¼èè´¹ä¸å®ç©ºé´ã
åèæ¬è¿
- https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/mysql/MySQL%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95.md
- https://juejin.cn/post/6844904062329028621
- https://juejin.cn/post/6844903581548544014#heading-34
- https://juejin.cn/post/6844903645125820424#heading-9
- https://blog.csdn.net/sinat_41917109/article/details/88944290
- https://mp.weixin.qq.com/s/KxSlNnXQSaMemYdqyRCMOg