## MySQL性能优化 ### 基本原则 想è¦å‘挥 MySQL 的最佳性能,需è¦éµå¾ª 3 个基本使用原则。 1. 让MySQL回归å˜å‚¨çš„基本èŒèƒ½ï¼šMySQL æ•°æ®åº“åªç”¨äºŽæ•°æ®çš„å˜å‚¨ï¼Œä¸è¿›è¡Œæ•°æ®çš„夿‚è®¡ç®—ï¼Œä¸æ‰¿è½½ä¸šåŠ¡é€»è¾‘ï¼Œç¡®ä¿å˜å‚¨å’Œè®¡ç®—分离; 2. æŸ¥è¯¢æ•°æ®æ—¶ï¼Œå°½é‡å•表查询,å‡å°‘跨库查询和多表关è”ï¼› 3. æœç»å¤§äº‹åŠ¡ã€å¤§ SQLã€å¤§æ‰¹é‡ã€å¤§å—段ç‰ä¸€ç³»åˆ—æ€§èƒ½æ€æ‰‹ã€‚ - 大事务:è¿è¡Œæ¥éª¤è¾ƒå¤šï¼Œæ¶‰åŠçš„è¡¨å’Œå—æ®µè¾ƒå¤šï¼Œå®¹æ˜“é€ æˆèµ„æºçš„äº‰æŠ¢ï¼Œç”šè‡³å½¢æˆæ»é”。一旦事务回滚,会导致资æºå 用时间过长。 - 大 SQLï¼šå¤æ‚çš„SQLæ„味ç€è¿‡å¤šçš„表的关è”,MySQL æ•°æ®åº“处ç†å…³è”超过3å¼ è¡¨ä»¥ä¸Šçš„SQL时,å 用资æºå¤šï¼Œæ€§èƒ½ä½Žä¸‹ã€‚ - 大批é‡ï¼šå¤šæ¡SQL一次性执行完æˆï¼Œå¯ä»¥å‡å°‘ä¸€æ¡æ¡æ‰§è¡ŒSQL产生的é¢å¤–开销,但必须确ä¿è¿›è¡Œå……分的测试,并且在业务低峰时段或者éžä¸šåŠ¡æ—¶æ®µæ‰§è¡Œã€‚ - 大嗿®µï¼šblobã€textç±»åž‹çš„å¤§å—æ®µè¦å°½é‡å°‘用,必须è¦ç”¨æ—¶ï¼Œå°½é‡ä¸Žä¸»ä¸šåŠ¡è¡¨åˆ†ç¦»ï¼Œå‡å°‘å¯¹è¿™ç±»å—æ®µçš„æ£€ç´¢å’Œæ›´æ–°ã€‚ ### 建库建表 1. 必须指定默认å˜å‚¨å¼•擎为 InnoDB,并且ç¦ç”¨ MyISAM å˜å‚¨å¼•擎,éšç€ MySQL 8.0 版本的å‘布,所有的数æ®å—典表都已ç»è½¬æ¢æˆäº† InnoDB,MyISAM å˜å‚¨å¼•擎已æˆä¸ºäº†åކå²ã€‚ 2. 默认å—符集 UTF8mb4,以å‰ç‰ˆæœ¬çš„ UTF8 是 UTF8mb3,未包å«ä¸ªåˆ«ç‰¹æ®Šå—符,新版本的 UTF8mb4 åŒ…å«æ‰€æœ‰å—符,官方强烈建议使用æ¤å—符集。 3. å…³é—区分大å°å†™åŠŸèƒ½ã€‚è®¾ç½®å‚æ•°`lower_case_table_names`的值为`1`,å³å¯å…³é—区分大å°å†™åŠŸèƒ½ï¼Œå³å¤§å†™å—æ¯ T å’Œå°å†™å—æ¯ t ä¸€æ ·ã€‚ 4. å˜å‚¨è¿‡ç¨‹ã€è§¦å‘器ã€è§†å›¾ã€eventç‰åŠŸèƒ½å°½é‡åœ¨ç¨‹åºä¸å®žçŽ°ï¼Œä¸€æ–¹é¢æ˜¯ä¸ºäº†å˜å‚¨å’Œè®¡ç®—分离,å¦ä¸€æ–¹é¢æ˜¯å› 为这些功能éžå¸¸ä¸å®Œæ•´ï¼Œè°ƒè¯•ã€æŽ’é”™ã€ç›‘控都éžå¸¸å›°éš¾ï¼Œç›¸å…³æ•°æ®å—典也ä¸å®Œå–„,å˜åœ¨æ½œåœ¨çš„风险。一般在生产数æ®åº“ä¸ï¼Œç¦æ¢ä½¿ç”¨ã€‚ 5. å•个数æ®åº“å®žä¾‹è¡¨æ•°é‡æŽ§åˆ¶åœ¨2000个以内。 #### InnoDB表的注æ„事项 1. 主键列使用`unsigned`整数,å¯ä»¥ä½¿ç”¨`auto_increment`,但是è¦ç¦æ¢æ‰‹åŠ¨æ›´æ–°ä¸»é”®ã€‚ 2. æ¯ä¸ªåˆ—éƒ½å¿…é¡»æ·»åŠ `comment`注释。 3. 在建表时必须显示指定`engine`。 4. è¡¨å¿…å¤‡ä¸‰å—æ®µï¼š`xxx_id`〠`xxx_create`〠`xxx_modified`。其ä¸`xxx_id`为主键,类型`unsigned`整数类型(例如:`int unsigned`);`xxx_create`ã€`xxx_modified`的类型å‡ä¸º`datetime`ç±»åž‹ï¼Œåˆ†åˆ«è®°å½•è¯¥æ¡æ•°æ®çš„创建时间ã€ä¿®æ”¹æ—¶é—´ã€‚ 5. æ‰€æœ‰å—æ®µå¿…须指定`not null`,为空值指定`default`å€¼ï¼Œå› ä¸ºMySQL难以优化`null`值,å«`null`值的å¤åˆç´¢å¼•会失效,最终导致查询效率低。 6. å•å¼ è¡¨çš„å—æ®µæ•°å°½é‡ç©ºå€¼åœ¨50ä¸ªå—æ®µä»¥å†…ï¼Œå¦‚æžœå—æ®µè¿‡å¤šå¯ä»¥è€ƒè™‘垂直拆分。 7. ç¦ç”¨`enum`å’Œ`set`ç±»åž‹ï¼Œå› ä¸ºè¿™æ ·çš„ç±»åž‹å…¼å®¹æ€§ä¸å¥½ä¸”性能较差。 8. 大文件ä¸åº”该使用`blob`类型而是ä¿å˜å®ƒä»¬çš„路径,`blob`å’Œ`text`è¿™æ ·çš„ç±»åž‹ä¼šå¯¼è‡´å¤„ç†æ€§èƒ½ä¸‹é™ï¼Œå…¨è¡¨æ‰«æä»£ä»·å¤§å¤§å¢žåŠ ã€‚ 9. 对货å¸ç‰å¯¹ç²¾åº¦æ•感的数æ®ï¼Œåº”该使用定点数(`decimal`ï¼‰è€Œä¸æ˜¯æµ®ç‚¹æ•°ï¼ˆ`float`)。 10. ä¿å˜IP地å€ä¸è¦ç”¨`char(15)`,应该使用`int unsigned`,å¯ä»¥ä½¿ç”¨`inet_aton`å’Œ`inet_ntoa`函数实现整数和IP地å€çš„转æ¢ã€‚ ### 使用索引 在å‰é¢[《关系型数æ®åº“MySQL》](../Day36-40/36-38.关系型数æ®åº“MySQL.md)一文ä¸ï¼Œæˆ‘们已ç»è®²åˆ°è¿‡ç´¢å¼•的相关知识,这里我们åšä¸€ä¸ªç®€å•的回顾。 #### 索引的设计原则 1. 创建索引的列并ä¸ä¸€å®šæ˜¯`select`æ“作ä¸è¦æŸ¥è¯¢çš„列,最适åˆåšç´¢å¼•的列是出现在`where`åå¥ä¸ç»å¸¸ç”¨ä½œç›é€‰æ¡ä»¶æˆ–连表åå¥ä¸ä½œä¸ºè¡¨è¿žæŽ¥æ¡ä»¶çš„列。 2. 具有唯一性的列,索引效果好;é‡å¤å€¼è¾ƒå¤šçš„列,索引效果差。 3. 如果为å—符串类型创建索引,最好指定一个å‰ç¼€é•¿åº¦ï¼Œåˆ›å»ºçŸç´¢å¼•。çŸç´¢å¼•å¯ä»¥å‡å°‘ç£ç›˜I/Oè€Œä¸”åœ¨åšæ¯”较时性能也更好,更é‡è¦çš„æ˜¯MySQL底层的高速索引缓å˜èƒ½å¤Ÿç¼“å˜æ›´å¤šçš„键值。 4. 创建一个包å«N列的å¤åˆç´¢å¼•(多列索引)时,相当于是创建了Nä¸ªç´¢å¼•ï¼Œæ¤æ—¶åº”该利用最左å‰ç¼€è¿›è¡ŒåŒ¹é…。 5. ä¸è¦è¿‡åº¦ä½¿ç”¨ç´¢å¼•ã€‚ç´¢å¼•å¹¶ä¸æ˜¯è¶Šå¤šè¶Šå¥½ï¼Œç´¢å¼•需è¦å 用é¢å¤–çš„å˜å‚¨ç©ºé—´è€Œä¸”会影å“写æ“作的性能(æ’å…¥ã€åˆ é™¤ã€æ›´æ–°æ•°æ®æ—¶ç´¢å¼•ä¹Ÿéœ€è¦æ›´æ–°ï¼‰ã€‚MySQLåœ¨ç”Ÿæˆæ‰§è¡Œè®¡åˆ’时,è¦è€ƒè™‘å„个索引的使用,这个也是需è¦è€—费时间的。 6. è¦æ³¨æ„å¯èƒ½ä½¿ç´¢å¼•失效的场景,例如:模糊查询使用了å‰ç½®é€šé…符ã€ä½¿ç”¨è´Ÿå‘æ¡ä»¶è¿›è¡ŒæŸ¥è¯¢ç‰ã€‚ ### 使用过程 过程,通常也称之为å˜å‚¨è¿‡ç¨‹ï¼Œå®ƒæ˜¯äº‹å…ˆç¼–译好å˜å‚¨åœ¨æ•°æ®åº“ä¸çš„一组SQL的集åˆã€‚调用å˜å‚¨è¿‡ç¨‹å¯ä»¥ç®€åŒ–应用程åºå¼€å‘人员的工作,å‡å°‘与数æ®åº“æœåŠ¡å™¨ä¹‹é—´çš„é€šä¿¡ï¼Œå¯¹äºŽæå‡æ•°æ®æ“作的性能是有帮助的,这些我们在之å‰çš„[《关系型数æ®åº“MySQL》](../Day36-40/36-38.关系型数æ®åº“MySQL.md)一文ä¸å·²ç»æåˆ°è¿‡ã€‚ ### æ•°æ®åˆ†åŒº MySQL支æŒåšæ•°æ®åˆ†åŒºï¼Œé€šè¿‡åˆ†åŒºå¯ä»¥å˜å‚¨æ›´å¤šçš„æ•°æ®ã€ä¼˜åŒ–查询,获得更大的åžåé‡å¹¶å¿«é€Ÿåˆ 除过期的数æ®ã€‚关于这个知识点建议大家看看MySQLçš„[官方文档](https://dev.mysql.com/doc/refman/5.7/en/partitioning-overview.html)。数æ®åˆ†åŒºæœ‰ä»¥ä¸‹å‡ ç§ç±»åž‹ï¼š 1. RANGE分区:基于连ç»åŒºé—´èŒƒå›´ï¼ŒæŠŠæ•°æ®åˆ†é…到ä¸åŒçš„分区。 ```SQL CREATE TABLE tb_emp ( eno INT NOT NULL, ename VARCHAR(20) NOT NULL, job VARCHAR(10) NOT NULL, hiredate DATE NOT NULL, dno INT NOT NULL ) PARTITION BY RANGE( YEAR(hiredate) ) ( PARTITION p0 VALUES LESS THAN (1960), PARTITION p1 VALUES LESS THAN (1970), PARTITION p2 VALUES LESS THAN (1980), PARTITION p3 VALUES LESS THAN (1990), PARTITION p4 VALUES LESS THAN MAXVALUE ); ``` 2. LIST分区:基于枚举值的范围,把数æ®åˆ†é…到ä¸åŒçš„分区。 3. HASH分区 / KEY分区:基于分区个数,把数æ®åˆ†é…到ä¸åŒçš„分区。 ```SQL CREATE TABLE tb_emp ( eno INT NOT NULL, ename VARCHAR(20) NOT NULL, job VARCHAR(10) NOT NULL, hiredate DATE NOT NULL, dno INT NOT NULL ) PARTITION BY HASH(dno) PARTITIONS 4; ``` ### SQL优化 1. 定ä½ä½Žæ•ˆçŽ‡çš„SQLè¯å¥ - 慢查询日志。 - 查看慢查询日志相关é…ç½® ```SQL mysql> show variables like 'slow_query%'; +---------------------------+----------------------------------+ | Variable_name | Value | +---------------------------+----------------------------------+ | slow_query_log | OFF | | slow_query_log_file | /mysql/data/localhost-slow.log | +---------------------------+----------------------------------+ mysql> show variables like 'long_query_time'; +-----------------+-----------+ | Variable_name | Value | +-----------------+-----------+ | long_query_time | 10.000000 | +-----------------+-----------+ ``` - 创建慢查询日志文件并修改所有者。 ```Bash touch /var/log/mysqld-slow.log chown mysql /var/log/mysqld-slow.log ``` - 修改全局慢查询日志é…置。 ```SQL mysql> set global slow_query_log_file='/var/log/mysqld-slow.log' mysql> set global slow_query_log='ON'; mysql> set global long_query_time=1; ``` - 或者直接修改MySQLé…置文件å¯ç”¨æ…¢æŸ¥è¯¢æ—¥å¿—。 ```INI [mysqld] slow_query_log=ON slow_query_log_file=/var/log/mysqld-slow.log long_query_time=1 ``` > **注æ„**:修改了é…置文件需è¦é‡å¯MySQL,CentOS上对应的命令是`systemctl restart mysqld`。 2. 通过`explain`了解SQL的执行计划。例如: ```SQL explain select ename, job, sal from tb_emp where dno=20\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: tb_emp type: ref possible_keys: fk_emp_dno key: fk_emp_dno key_len: 5 ref: const rows: 7 Extra: NULL 1 row in set (0.00 sec) ``` - `select_type`:查询类型(SIMPLE - ç®€å•æŸ¥è¯¢ã€PRIMARY - 主查询ã€UNION - 并集ã€SUBQUERY - åæŸ¥è¯¢ï¼‰ã€‚ - `table`:输出结果集的表。 - `type`:访问类型(ALL - 全表查询性能最差ã€indexã€rangeã€refã€eq_refã€constã€NULL)。 - `possible_keys`:查询时å¯èƒ½ç”¨åˆ°çš„索引。 - `key`:实际使用的索引。 - `key_len`ï¼šç´¢å¼•å—æ®µçš„长度。 - `rows`:扫æçš„行数,行数越少肯定性能越好。 - `extra`:é¢å¤–ä¿¡æ¯ã€‚ 3. 通过`show profiles`å’Œ`show profile for query`分æžSQL。 MySQL从5.0.37开始支æŒå‰–é¢ç³»ç»Ÿæ¥å¸®åŠ©ç”¨æˆ·äº†è§£SQL执行性能的细节,å¯ä»¥é€šè¿‡ä¸‹é¢çš„æ–¹å¼æ¥æŸ¥çœ‹MySQLæ˜¯å¦æ”¯æŒå’Œå¼€å¯äº†å‰–é¢ç³»ç»Ÿã€‚ ```SQL select @@have_profiling; select @@profiling; ``` 如果没有开å¯å‰–é¢ç³»ç»Ÿï¼Œå¯ä»¥é€šè¿‡ä¸‹é¢çš„SQLæ¥æ‰“开它。 ```SQL set profiling=1; ``` 接下æ¥å°±å¯ä»¥é€šè¿‡å‰–é¢ç³»ç»Ÿæ¥äº†è§£SQL的执行性能,例如: ```SQL mysql> select count(*) from tb_emp; +----------+ | count(*) | +----------+ | 14 | +----------+ 1 row in set (0.00 sec) mysql> show profiles; +----------+------------+-----------------------------+ | Query_ID | Duration | Query | +----------+------------+-----------------------------+ | 1 | 0.00029600 | select count(*) from tb_emp | +----------+------------+-----------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> show profile for query 1; +----------------------+----------+ | Status | Duration | +----------------------+----------+ | starting | 0.000076 | | checking permissions | 0.000007 | | Opening tables | 0.000016 | | init | 0.000013 | | System lock | 0.000007 | | optimizing | 0.000005 | | statistics | 0.000012 | | preparing | 0.000010 | | executing | 0.000003 | | Sending data | 0.000070 | | end | 0.000012 | | query end | 0.000008 | | closing tables | 0.000012 | | freeing items | 0.000032 | | cleaning up | 0.000013 | +----------------------+----------+ 15 rows in set, 1 warning (0.00 sec) ``` 4. 优化CRUDæ“作。 - 优化`insert`è¯å¥ - 在`insert`è¯å¥åŽé¢è·Ÿä¸Šå¤šç»„值进行æ’入在性能上优于分开`insert`。 - 如果有多个连接å‘åŒä¸€ä¸ªè¡¨æ’入数æ®ï¼Œä½¿ç”¨`insert delayed`å¯ä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½ã€‚ - 如果è¦ä»Žä¸€ä¸ªæ–‡æœ¬æ–‡ä»¶è£…载数æ®åˆ°è¡¨æ—¶ï¼Œä½¿ç”¨`load data infile`比`insert`性能好得多。 - 优化`order by`è¯å¥ - 如果`where`åå¥çš„æ¡ä»¶å’Œ`order by`åå¥çš„æ¡ä»¶ç›¸åŒï¼Œè€Œä¸”排åºçš„顺åºä¸Žç´¢å¼•的顺åºç›¸åŒï¼Œå¦‚æžœè¿˜åŒæ—¶æ»¡è¶³æŽ’åºå—段都是å‡åºæˆ–者é™åºï¼Œé‚£ä¹ˆåªé ç´¢å¼•å°±èƒ½å®ŒæˆæŽ’åºã€‚ - 优化`group by`è¯å¥ - 在使用`group by`åå¥åˆ†ç»„时,如果希望é¿å…排åºå¸¦æ¥çš„开销,å¯ä»¥ç”¨`order by null`ç¦ç”¨æŽ’åºã€‚ - 优化嵌套查询 - MySQL从4.1开始支æŒåµŒå¥—æŸ¥è¯¢ï¼ˆåæŸ¥è¯¢ï¼‰ï¼Œè¿™ä½¿å¾—å¯ä»¥å°†ä¸€ä¸ªæŸ¥è¯¢çš„结果当åšå¦ä¸€ä¸ªæŸ¥è¯¢çš„一部分æ¥ä½¿ç”¨ã€‚在æŸäº›æƒ…å†µä¸‹ï¼ŒåæŸ¥è¯¢å¯ä»¥è¢«æ›´æœ‰æ•ˆçŽ‡çš„è¿žæŽ¥æŸ¥è¯¢å–ä»£ï¼Œå› ä¸ºåœ¨è¿žæŽ¥æŸ¥è¯¢æ—¶MySQLä¸éœ€è¦åœ¨å†…å˜ä¸åˆ›å»ºä¸´æ—¶è¡¨æ¥å®Œæˆè¿™ä¸ªé€»è¾‘上需è¦å¤šä¸ªæ¥éª¤æ‰èƒ½å®Œæˆçš„æŸ¥è¯¢ã€‚ - 优化oræ¡ä»¶ - 如果æ¡ä»¶ä¹‹é—´æ˜¯`or`å…³ç³»ï¼Œåˆ™åªæœ‰åœ¨æ‰€æœ‰æ¡ä»¶éƒ½ç”¨åˆ°ç´¢å¼•的情况下索引æ‰ä¼šç”Ÿæ•ˆã€‚ - 优化分页查询 - 分页查询时,一个比较头疼的事情是如åŒ`limit 1000, 20`ï¼Œæ¤æ—¶MySQLå·²ç»æŽ’åºå‡ºå‰1020æ¡è®°å½•但是仅仅返回第1001到1020æ¡è®°å½•,å‰1000æ¡å®žé™…都用ä¸ä¸Šï¼ŒæŸ¥è¯¢å’ŒæŽ’åºçš„代价éžå¸¸é«˜ã€‚一ç§å¸¸è§çš„优化æ€è·¯æ˜¯åœ¨ç´¢å¼•ä¸Šå®ŒæˆæŽ’åºå’Œåˆ†é¡µçš„æ“ä½œï¼Œç„¶åŽæ ¹æ®è¿”回的结果åšè¡¨è¿žæŽ¥æ“作æ¥å¾—åˆ°æœ€ç»ˆçš„ç»“æžœï¼Œè¿™æ ·å¯ä»¥é¿å…出现全表查询,也é¿å…了外部排åºã€‚ ```SQL select * from tb_emp order by ename limit 10000, 20; select * from tb_emp t1 inner join (select eno from tb_emp order by ename limit 10000, 20) t2 on t1.eno=t2.eno; ``` 上é¢çš„代ç ä¸ï¼Œç¬¬2行SQL是优于第1行SQLçš„ï¼Œå½“ç„¶æˆ‘ä»¬çš„å‰ææ˜¯å·²ç»åœ¨`ename`å—æ®µä¸Šåˆ›å»ºäº†ç´¢å¼•。 - 使用SQLæç¤º - USE INDEX:建议MySQL使用指定的索引。 - IGNORE INDEX:建议MySQL忽略掉指定的索引。 - FORCE INDEX:强制MySQL使用指定的索引。 ### é…置优化 å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„å‘½ä»¤æ¥æŸ¥çœ‹MySQLæœåС噍é…ç½®å‚æ•°çš„默认值。 ```SQL show variables; show variables like 'key_%'; show variables like '%cache%'; show variables like 'innodb_buffer_pool_size'; ``` 通过下é¢çš„命令å¯ä»¥äº†è§£MySQLæœåС噍è¿è¡Œçжæ€å€¼ã€‚ ```SQL show status; show status like 'com_%'; show status like 'innodb_%'; show status like 'connections'; show status like 'slow_queries'; ``` 1. 调整`max_connections`:MySQL最大连接数é‡ï¼Œé»˜è®¤151。在Linux系统上,如果内å˜è¶³å¤Ÿä¸”ä¸è€ƒè™‘用户ç‰å¾…å“应时间这些问题,MySQLç†è®ºä¸Šå¯ä»¥æ”¯æŒåˆ°ä¸‡çº§è¿žæŽ¥ï¼Œä½†æ˜¯é€šå¸¸æƒ…况下,这个值建议控制在1000以内。 2. 调整`back_log`:TCP连接的积压请求队列大å°ï¼Œé€šå¸¸æ˜¯max_connections的五分之一,最大ä¸èƒ½è¶…过900。 3. 调整`table_open_cache`:这个值应该设置为max_connectionsçš„Nå€ï¼Œå…¶ä¸N代表æ¯ä¸ªè¿žæŽ¥åœ¨æŸ¥è¯¢æ—¶æ‰“开的表的最大个数。 4. 调整`innodb_lock_wait_timeout`ï¼šè¯¥å‚æ•°å¯ä»¥æŽ§åˆ¶InnoDB事务ç‰å¾…行é”的时间,默认值是50ms,对于å馈å“åº”è¦æ±‚较高的应用,å¯ä»¥å°†è¿™ä¸ªå€¼è°ƒå°é¿å…事务长时间挂起;对于åŽå°ä»»åŠ¡ï¼Œå¯ä»¥å°†è¿™ä¸ªå€¼è°ƒå¤§æ¥é¿å…å‘生大的回滚æ“作。 5. 调整`innodb_buffer_pool_size`:InnoDBæ•°æ®å’Œç´¢å¼•的内å˜ç¼“冲区大å°ï¼Œä»¥å—节为å•ä½ï¼Œè¿™ä¸ªå€¼è®¾ç½®å¾—越高,访问表数æ®éœ€è¦è¿›è¡Œçš„ç£ç›˜I/Oæ“作就越少,如果å¯èƒ½ç”šè‡³å¯ä»¥å°†è¯¥å€¼è®¾ç½®ä¸ºç‰©ç†å†…å˜å¤§å°çš„80%。 ### 架构优化 1. 通过拆分æé«˜è¡¨çš„访问效率。 - 垂直拆分 - 水平拆分 2. 逆范å¼ç†è®ºã€‚æ•°æ®è¡¨è®¾è®¡çš„规范程度称之为范å¼ï¼ˆNormal Formï¼‰ï¼Œè¦æå‡è¡¨çš„规范程度通常需è¦å°†å¤§è¡¨æ‹†åˆ†ä¸ºæ›´å°çš„表,范å¼çº§åˆ«è¶Šé«˜æ•°æ®å†—余越å°ï¼Œè€Œä¸”在æ’å…¥ã€åˆ é™¤ã€æ›´æ–°æ•°æ®æ—¶å‡ºé—®é¢˜çš„å¯èƒ½æ€§ä¼šå¤§å¹…度é™ä½Žï¼Œä½†æ˜¯èŠ‚çœäº†ç©ºé—´å°±æ„å‘³ç€æŸ¥è¯¢æ•°æ®æ—¶å¯èƒ½èŠ±è´¹æ›´å¤šçš„æ—¶é—´ï¼ŒåŽŸæ¥çš„å•表查询å¯èƒ½ä¼šå˜æˆè¿žè¡¨æŸ¥è¯¢ã€‚为æ¤ï¼Œé¡¹ç›®å®žè·µä¸æˆ‘ä»¬é€šå¸¸ä¼šè¿›è¡Œé€†èŒƒå¼æ“作,故æ„é™ä½ŽèŒƒå¼çº§åˆ«å¢žåР冗余æ¥å‡å°‘查询的时间开销。 - 1NF:列ä¸èƒ½å†æ‹†åˆ† - 2NF:所有的属性都ä¾èµ–于主键 - 3NF:所有的属性都直接ä¾èµ–äºŽä¸»é”®ï¼ˆæ¶ˆé™¤ä¼ é€’ä¾èµ–) - BCNF:消除éžå¹³å‡¡å¤šå€¼ä¾èµ– 3. 使用ä¸é—´è¡¨æé«˜ç»Ÿè®¡æŸ¥è¯¢é€Ÿåº¦ã€‚ 使用`insert into ä¸é—´è¡¨ select ... where ...`è¿™æ ·çš„è¯å¥å…ˆå°†éœ€è¦çš„æ•°æ®ç›é€‰å‡ºæ¥æ”¾åˆ°ä¸é—´è¡¨ä¸ï¼Œç„¶åŽå†å¯¹ä¸é—´è¡¨è¿›è¡Œç»Ÿè®¡ï¼Œé¿å…ä¸å¿…è¦çš„è¿ç®—和处ç†ã€‚ 4. 主从å¤åˆ¶å’Œè¯»å†™åˆ†ç¦»ï¼Œå…·ä½“内容请å‚考[《项目部署上线和性能调优》](./98.项目部署上线和性能调优.md)。 5. é…ç½®MySQL集群。 > **说明**ï¼šæœ¬ç« å†…å®¹å‚考了网易出å“的《深入浅出MySQL》一书,该书和《高性能MySQLã€‹ä¸€æ ·ï¼Œéƒ½å¯¹MySQL进行了深入细致的讲解,虽然总体感觉åŽè€…æ›´åŠ é«˜å±‹å»ºç“´ï¼Œä½†æ˜¯å‰è€…也算得上是æå‡MySQL技能的佳作(作者的文å—åŠŸåº•ç¨æ˜¾ç²—糙,深度也ä¸åŠåŽè€…),建议有兴趣的读者å¯ä»¥é˜…读这两本书。