æœ¬ç« è®¨è®ºMySQL 5.1.ä¸å®žçŽ°çš„分区。关于分区和分区概念的介ç»å¯ä»¥åœ¨18.1节,“MySQLä¸çš„分区概述â€ä¸æ‰¾åˆ°ã€‚MySQL 5.1 支æŒå“ªå‡ ç§ç±»åž‹çš„分区,在18.2节,“分区类型†ä¸è®¨è®ºã€‚关于å分区在18.2.5节,“å分区†ä¸è®¨è®ºã€‚现有分区表ä¸åˆ†åŒºçš„å¢žåŠ ã€åˆ 除和修改的方法在18.3节,“分区管ç†â€ ä¸ä»‹ç»ã€‚ 和分区表一åŒä½¿ç”¨çš„表维护命令在18.3.3节,“分区维护†ä¸ä»‹ç»ã€‚
请注æ„:MySQL 5.1ä¸çš„分区实现ä»ç„¶å¾ˆæ–°ï¼ˆpre-alphaå“质),æ¤æ—¶è¿˜ä¸æ˜¯å¯ç”Ÿäº§çš„(not production-ready)。 åŒæ ·ï¼Œè®¸å¤šä¹Ÿé€‚ç”¨äºŽæœ¬ç« ï¼šåœ¨è¿™é‡Œæ述的一些功能还没有实际上实现(分区维护和é‡æ–°åˆ†åŒºå‘½ä»¤ï¼‰ï¼Œå…¶ä»–çš„å¯èƒ½è¿˜æ²¡æœ‰å®Œå…¨å¦‚所æè¿°çš„é‚£æ ·å®žçŽ°(例如, 用于分区的数æ®ç›®å½•ï¼ˆDATA DIRECTORY)和索引目录(INDEX DIRECTORY)选项å—到Bug #13520) ä¸åˆ©çš„å½±å“). 我们已ç»è®¾æ³•åœ¨æœ¬ç« ä¸æ ‡å‡ºè¿™äº›å·®å¼‚。在æ出缺陷报告å‰ï¼Œæˆ‘们鼓励å‚考下é¢çš„一些资æºï¼š
这是一个为对MySQL分区技术感兴趣或用MySQL分区技术åšè¯•éªŒæ供的官方讨论论å›ã€‚æ¥è‡ªMySQL çš„å¼€å‘者和其他的人,会在上é¢å‘表和更新有关的æ料。它由分区开å‘和文献团队的æˆå‘˜è´Ÿè´£ç›‘控。
å·²ç»å½’档在缺陷系统ä¸çš„ã€æ‰€æœ‰åˆ†åŒºç¼ºé™·çš„ä¸€ä¸ªåˆ—è¡¨ï¼Œè€Œæ— è®ºè¿™äº›ç¼ºé™·çš„å¹´é™ã€ä¸¥é‡æ€§æˆ–当å‰çš„状æ€å¦‚ä½•ã€‚æ ¹æ®è®¸å¤šè§„则å¯ä»¥å¯¹è¿™äº›ç¼ºé™·è¿›è¡Œç›é€‰ï¼Œæˆ–者å¯ä»¥ä»ŽMySQL缺陷系统主页开始,然åŽæŸ¥æ‰¾ä½ 特别感兴趣的缺陷。
MySQL分区体系结构和领先的开å‘者Mikael Ronström ç»å¸¸åœ¨è¿™é‡Œè´´å…³äºŽä»–ç ”ç©¶MySQL 分区和MySQLç°‡çš„æ–‡ç« ã€‚
一个MySQL 新闻网站,它以汇集MySQL相关的网誌为特点,那些使用我的MySQL的人应该对æ¤æœ‰å…´è¶£ã€‚æˆ‘ä»¬é¼“åŠ±æŸ¥çœ‹é‚£äº›ç ”ç©¶MySQLåˆ†åŒºçš„äººçš„ç½‘èªŒé“¾æŽ¥ï¼Œæˆ–è€…æŠŠä½ è‡ªå·±çš„ç½‘èªŒåŠ åˆ°è¿™äº›æ–°é—»æŠ¥é“ä¸ã€‚
MySQL 5.1的二进制版本目å‰è¿˜ä¸å¯ç”¨ï¼›ä½†æ˜¯ï¼Œå¯ä»¥ä»ŽBitKeeper知识库ä¸èŽ·å¾—æºç 。è¦æ¿€æ´»åˆ†åŒºï¼Œéœ€è¦ä½¿ç”¨--with-分区选项编译æœåŠ¡å™¨ã€‚关于建立MySQL 的更多信æ¯ï¼Œè¯·å‚è§2.8节,“使用æºç 分å‘版安装MySQLâ€ã€‚如果在编译一个激活分区的MySQL 5.1创建ä¸ç¢°åˆ°é—®é¢˜ï¼Œå¯ä»¥åœ¨MySQL分区论å›ä¸æŸ¥æ‰¾è§£å†³åŠžæ³•ï¼Œå¦‚果在论å›ä¸å·²ç»è´´å‡ºçš„æ–‡ç« ä¸æ²¡æœ‰æ‰¾åˆ°é—®é¢˜çš„解决办法,å¯ä»¥åœ¨ä¸Šé¢å¯»æ‰¾å¸®åŠ©ã€‚
本节æ供了关于MySQL 5.1.分区在概念上的概述。
SQLæ ‡å‡†åœ¨æ•°æ®å˜å‚¨çš„物ç†æ–¹é¢æ²¡æœ‰æ供太多的指å—。SQLè¯è¨€çš„使用独立于它所使用的任何数æ®ç»“构或图表ã€è¡¨ã€è¡Œæˆ–列下的介质。但是,大部分高级数æ®åº“管ç†ç³»ç»Ÿå·²ç»å¼€å‘äº†ä¸€äº›æ ¹æ®æ–‡ä»¶ç³»ç»Ÿã€ç¡¬ä»¶æˆ–者这两者æ¥ç¡®å®šå°†è¦ç”¨äºŽå˜å‚¨ç‰¹å®šæ•°æ®å—物ç†ä½ç½®çš„方法。在MySQLä¸ï¼ŒInnoDBå˜å‚¨å¼•æ“Žé•¿æœŸæ”¯æŒè¡¨ç©ºé—´çš„概念,并且MySQLæœåŠ¡å™¨ç”šè‡³åœ¨åˆ†åŒºå¼•å…¥ä¹‹å‰ï¼Œå°±èƒ½é…置为å˜å‚¨ä¸åŒçš„æ•°æ®åº“使用ä¸åŒçš„物ç†è·¯å¾„(关于如何é…置的解释,请å‚è§7.6.1节,“使用符å·é“¾æŽ¥â€)。
分区åˆæŠŠè¿™ä¸ªæ¦‚念推进了一æ¥ï¼Œå®ƒå…è®¸æ ¹æ®å¯ä»¥è®¾ç½®ä¸ºä»»æ„大å°çš„规则,跨文件系统分é…å•ä¸ªè¡¨çš„多个部分。实际上,表的ä¸åŒéƒ¨åˆ†åœ¨ä¸åŒçš„ä½ç½®è¢«å˜å‚¨ä¸ºå•ç‹¬çš„表。用户所选择的ã€å®žçŽ°æ•°æ®åˆ†å‰²çš„规则被称为分区函数,这在MySQLä¸å®ƒå¯ä»¥æ˜¯æ¨¡æ•°ï¼Œæˆ–者是简å•çš„匹é…一个连ç»çš„数值区间或数值列表,或者是一个内部HASH函数,或一个线性HASHå‡½æ•°ã€‚å‡½æ•°æ ¹æ®ç”¨æˆ·æŒ‡å®šçš„分区类型æ¥é€‰æ‹©ï¼ŒæŠŠç”¨æˆ·æ供的表达å¼çš„值作为å‚数。该表达å¼å¯ä»¥æ˜¯ä¸€ä¸ªæ•´æ•°åˆ—值,或一个作用在一个或多个列值上并返回一个整数的函数。这个表达å¼çš„å€¼ä¼ é€’ç»™åˆ†åŒºå‡½æ•°ï¼Œåˆ†åŒºå‡½æ•°è¿”å›žä¸€ä¸ªè¡¨ç¤ºé‚£ä¸ªç‰¹å®šè®°å½•åº”è¯¥ä¿å˜åœ¨å“ªä¸ªåˆ†åŒºçš„åºå·ã€‚这个函数ä¸èƒ½æ˜¯å¸¸æ•°ï¼Œä¹Ÿä¸èƒ½æ˜¯ä»»æ„数。它ä¸èƒ½åŒ…å«ä»»ä½•æŸ¥è¯¢ï¼Œä½†æ˜¯å®žé™…上å¯ä»¥ä½¿ç”¨MySQL ä¸ä»»ä½•å¯ç”¨çš„SQL表达å¼ï¼Œåªè¦è¯¥è¡¨è¾¾å¼è¿”回一个å°äºŽMAXVALUE(最大å¯èƒ½çš„æ£æ•´æ•°ï¼‰çš„æ£æ•°å€¼ã€‚分区函数的例åå¯ä»¥åœ¨æœ¬ç« åŽé¢å…³äºŽåˆ†åŒºç±»åž‹çš„讨论ä¸æ‰¾åˆ° (请å‚è§18.2节,“分区类型†),也å¯åœ¨13.1.5节,“CREATE TABLEè¯æ³•â€çš„分区è¯æ³•æè¿°ä¸æ‰¾åˆ°ã€‚
当二进制ç å˜æˆå¯ç”¨æ—¶ï¼ˆä¹Ÿå°±æ˜¯è¯´ï¼Œ5.1 -max 二进制ç 将通过--with-partition 建立),分区支æŒå°±å°†åŒ…å«åœ¨MySQL 5.1çš„-max 版本ä¸ã€‚如果MySQL二进制ç 是使用分区支æŒå»ºç«‹çš„,那么激活它ä¸éœ€è¦ä»»ä½•å…¶ä»–的东西 (例如,在my.cnf 文件ä¸ï¼Œä¸éœ€è¦ç‰¹æ®Šçš„æ¡ç›®)。å¯ä»¥é€šè¿‡ä½¿ç”¨SHOW VARIABLES命令æ¥ç¡®å®šMySQL是å¦æ”¯æŒåˆ†åŒºï¼Œä¾‹å¦‚:
mysql> SHOW VARIABLES LIKE '%partition%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| have_partition_engine | YES |
+-----------------------+-------+
1 row in set (0.00 sec)
在如上列出的一个æ£ç¡®çš„SHOW VARIABLES 命令所产生的输出ä¸ï¼Œå¦‚果没有看到å˜é‡have_partition_engine的值为YES,那么MySQL的版本就ä¸æ”¯æŒåˆ†åŒºã€‚(注æ„:在显示任何有关分区支æŒä¿¡æ¯çš„命令SHOW ENGINES的输出ä¸ï¼Œä¸ä¼šç»™å‡ºä»»ä½•ä¿¡æ¯ï¼›å¿…须使用SHOW VARIABLES命令æ¥åšå‡ºè¿™ä¸ªåˆ¤æ–)。
对于创建了分区的表,å¯ä»¥ä½¿ç”¨ä½ çš„MySQL æœåŠ¡å™¨æ‰€æ”¯æŒçš„任何å˜å‚¨å¼•æ“Žï¼›MySQL 分区引擎在一个å•ç‹¬çš„层ä¸è¿è¡Œï¼Œå¹¶ä¸”å¯ä»¥å’Œä»»ä½•è¿™æ ·çš„层进行相互作用。在MySQL 5.1版ä¸ï¼ŒåŒä¸€ä¸ªåˆ†åŒºè¡¨çš„所有分区必须使用åŒä¸€ä¸ªå˜å‚¨å¼•æ“Žï¼›ä¾‹å¦‚,ä¸èƒ½å¯¹ä¸€ä¸ªåˆ†åŒºä½¿ç”¨MyISAM,而对å¦ä¸€ä¸ªä½¿ç”¨InnoDB。但是,这并ä¸å¦¨ç¢åœ¨åŒä¸€ä¸ª MySQL æœåŠ¡å™¨ä¸ï¼Œç”šè‡³åœ¨åŒä¸€ä¸ªæ•°æ®åº“ä¸ï¼Œå¯¹äºŽä¸åŒçš„分区表使用ä¸åŒçš„å˜å‚¨å¼•æ“Žã€‚
è¦ä¸ºæŸä¸ªåˆ†åŒºè¡¨é…置一个专门的å˜å‚¨å¼•æ“Žï¼Œå¿…须且åªèƒ½ä½¿ç”¨[STORAGE] ENGINE 选项,这如åŒä¸ºéžåˆ†åŒºè¡¨é…ç½®å˜å‚¨å¼•æ“Žä¸€æ ·ã€‚但是,必须记ä½[STORAGE] ENGINE(和其他的表选项)必须列在用在CREATE TABLEè¯å¥ä¸çš„其他任何分区选项之å‰ã€‚下é¢çš„例åç»™å‡ºäº†æ€Žæ ·åˆ›å»ºä¸€ä¸ªé€šè¿‡HASH分æˆ6个分区ã€ä½¿ç”¨InnoDBå˜å‚¨å¼•æ“Žçš„表:
CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE)
ENGINE=INNODB
PARTITION BY HASH(MONTH(tr_date))
PARTITIONS 6;
(注释:æ¯ä¸ªPARTITION åå¥å¯ä»¥åŒ…å«ä¸€ä¸ª [STORAGE] ENGINE 选项,但是在MySQL 5.1版本ä¸ï¼Œè¿™æ²¡æœ‰ä½œç”¨ï¼‰ã€‚
创建分区的临时表也是å¯èƒ½çš„;但是,这ç§è¡¨çš„生命周期åªæœ‰å½“å‰MySQL 的会è¯çš„时间那么长。对于éžåˆ†åŒºçš„ä¸´æ—¶è¡¨ï¼Œè¿™ä¹Ÿæ˜¯ä¸€æ ·çš„ã€‚
注释:分区适用于一个表的所有数æ®å’Œç´¢å¼•ï¼›ä¸èƒ½åªå¯¹æ•°æ®åˆ†åŒºè€Œä¸å¯¹ç´¢å¼•åˆ†åŒºï¼Œå之亦然,åŒæ—¶ä¹Ÿä¸èƒ½åªå¯¹è¡¨çš„一部分进行分区。
å¯ä»¥é€šè¿‡ä½¿ç”¨ç”¨æ¥åˆ›å»ºåˆ†åŒºè¡¨çš„CREATE TABLEè¯å¥çš„PARTITIONåå¥çš„DATA DIRECTORY(数æ®è·¯å¾„)和INDEX DIRECTORY(索引路径)选项,为æ¯ä¸ªåˆ†åŒºçš„æ•°æ®å’Œç´¢å¼•æŒ‡å®šç‰¹å®šçš„路径。æ¤å¤–,MAX_ROWSå’ŒMIN_ROWS选项å¯ä»¥ç”¨æ¥è®¾å®šæœ€å¤§å’Œæœ€å°çš„行数,它们å¯ä»¥å„自ä¿å˜åœ¨æ¯ä¸ªåˆ†åŒºé‡Œã€‚关于这些选项的更多信æ¯ï¼Œè¯·å‚è§18.3节,“分区管ç†â€ã€‚注释:这个特殊的功能由于Bug #13250çš„åŽŸå› ï¼Œç›®å‰è¿˜ä¸èƒ½å®žç”¨ã€‚在第一个5.1二进制版本投入使用时,我们应该已ç»æŠŠè¿™ä¸ªé—®é¢˜è§£å†³äº†ã€‚
分区的一些优点包括:
· 与å•ä¸ªç£ç›˜æˆ–文件系统分区相比,å¯ä»¥å˜å‚¨æ›´å¤šçš„æ•°æ®ã€‚
· 对于那些已ç»å¤±åŽ»ä¿å˜æ„义的数æ®ï¼Œé€šå¸¸å¯ä»¥é€šè¿‡åˆ 除与那些数æ®æœ‰å…³çš„åˆ†åŒºï¼Œå¾ˆå®¹æ˜“åœ°åˆ é™¤é‚£äº›æ•°æ®ã€‚相å地,在æŸäº›æƒ…å†µä¸‹ï¼Œæ·»åŠ æ–°æ•°æ®çš„过程åˆå¯ä»¥é€šè¿‡ä¸ºé‚£äº›æ–°æ•°æ®ä¸“é—¨å¢žåŠ ä¸€ä¸ªæ–°çš„åˆ†åŒºï¼Œæ¥å¾ˆæ–¹ä¾¿åœ°å®žçŽ°ã€‚
通常和分区有关的其他优点包括下é¢åˆ—出的这些。MySQL 分区ä¸çš„这些功能目å‰è¿˜æ²¡æœ‰å®žçŽ°ï¼Œä½†æ˜¯åœ¨æˆ‘们的优先级列表ä¸ï¼Œå…·æœ‰é«˜çš„优先级;我们希望在5.1的生产版本ä¸ï¼Œèƒ½åŒ…括这些功能。
· 一些查询å¯ä»¥å¾—到æžå¤§çš„优化,这主è¦æ˜¯å€ŸåŠ©äºŽæ»¡è¶³ä¸€ä¸ªç»™å®šWHERE è¯å¥çš„æ•°æ®å¯ä»¥åªä¿å˜åœ¨ä¸€ä¸ªæˆ–å¤šä¸ªåˆ†åŒºå†…ï¼Œè¿™æ ·åœ¨æŸ¥æ‰¾æ—¶å°±ä¸ç”¨æŸ¥æ‰¾å…¶ä»–å‰©ä½™çš„åˆ†åŒºã€‚å› ä¸ºåˆ†åŒºå¯ä»¥åœ¨åˆ›å»ºäº†åˆ†åŒºè¡¨åŽè¿›è¡Œä¿®æ”¹ï¼Œæ‰€ä»¥åœ¨ç¬¬ä¸€æ¬¡é…置分区方案时还ä¸æ›¾è¿™ä¹ˆåšæ—¶ï¼Œå¯ä»¥é‡æ–°ç»„织数æ®ï¼Œæ¥æ高那些常用查询的效率。
· 涉åŠåˆ°ä¾‹å¦‚SUM() å’Œ COUNT()è¿™æ ·èšåˆå‡½æ•°çš„查询,å¯ä»¥å¾ˆå®¹æ˜“地进行并行处ç†ã€‚è¿™ç§æŸ¥è¯¢çš„一个简å•ä¾‹å如 “SELECT salesperson_id, COUNT(orders) as order_total FROM sales GROUP BY salesperson_idï¼›â€ã€‚通过“并行â€ï¼Œ è¿™æ„味ç€è¯¥æŸ¥è¯¢å¯ä»¥åœ¨æ¯ä¸ªåˆ†åŒºä¸ŠåŒæ—¶è¿›è¡Œï¼Œæœ€ç»ˆç»“æžœåªéœ€é€šè¿‡æ€»è®¡æ‰€æœ‰åˆ†åŒºå¾—到的结果。
· 通过跨多个ç£ç›˜æ¥åˆ†æ•£æ•°æ®æŸ¥è¯¢ï¼Œæ¥èŽ·å¾—更大的查询åžåé‡ã€‚
è¦ç»å¸¸æ£€æŸ¥æœ¬é¡µå’Œæœ¬ç« ï¼Œå› ä¸ºå®ƒå°†éšMySQL 5.1åŽç»çš„分区进展而更新。
本节讨论在MySQL 5.1ä¸å¯ç”¨çš„分区类型。这些类型包括:
· RANGE 分区:基于属于一个给定连ç»åŒºé—´çš„列值,把多行分é…给分区。å‚è§18.2.1节,“RANGE分区â€ã€‚
· LIST 分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹é…一个离散值集åˆä¸çš„æŸä¸ªå€¼æ¥è¿›è¡Œé€‰æ‹©ã€‚å‚è§18.2.2节,“LIST分区â€ã€‚
· HASH分区:基于用户定义的表达å¼çš„返回值æ¥è¿›è¡Œé€‰æ‹©çš„分区,该表达å¼ä½¿ç”¨å°†è¦æ’入到表ä¸çš„这些行的列值进行计算。这个函数å¯ä»¥åŒ…å«MySQL ä¸æœ‰æ•ˆçš„ã€äº§ç”Ÿéžè´Ÿæ•´æ•°å€¼çš„任何表达å¼ã€‚å‚è§18.2.3节,“HASH分区â€ã€‚
· KEY 分区:类似于按HASH分区,区别在于KEY分区åªæ”¯æŒè®¡ç®—一列或多列,且MySQL æœåŠ¡å™¨æ供其自身的哈希函数。必须有一列或多列包å«æ•´æ•°å€¼ã€‚å‚è§18.2.4节,“KEY分区â€ã€‚
æ— è®ºä½¿ç”¨ä½•ç§ç±»åž‹çš„分区,分区总是在创建时就自动的顺åºç¼–å·ï¼Œä¸”从0开始记录,记ä½è¿™ä¸€ç‚¹éžå¸¸é‡è¦ã€‚当有一新行æ’入到一个分区表ä¸æ—¶ï¼Œå°±æ˜¯ä½¿ç”¨è¿™äº›åˆ†åŒºç¼–å·æ¥è¯†åˆ«æ£ç¡®çš„åˆ†åŒºã€‚ä¾‹å¦‚ï¼Œå¦‚æžœä½ çš„è¡¨ä½¿ç”¨4个分区,那么这些分区就编å·ä¸º0, 1, 2, å’Œ3。对于RANGEå’ŒLIST分区类型,确认æ¯ä¸ªåˆ†åŒºç¼–å·éƒ½å®šä¹‰äº†ä¸€ä¸ªåˆ†åŒºï¼Œå¾ˆæœ‰å¿…è¦ã€‚对HASH分区,使用的用户函数必须返回一个大于0的整数值。对于KEY分区,这个问题通过MySQLæœåŠ¡å™¨å†…部使用的 哈希函数自动进行处ç†ã€‚
分区的åå—基本上éµå¾ªå…¶ä»–MySQL æ ‡è¯†ç¬¦åº”å½“éµå¾ªçš„原则,例如用于表和数æ®åº“åå—çš„æ ‡è¯†ç¬¦ã€‚ä½†æ˜¯åº”å½“æ³¨æ„,分区的åå—是ä¸åŒºåˆ†å¤§å°å†™çš„。例如,下é¢çš„CREATE TABLEè¯å¥å°†ä¼šäº§ç”Ÿå¦‚下的错误:
mysql> CREATE TABLE t2 (val INT)
-> PARTITION BY LIST(val)(
-> PARTITION mypart VALUES IN (1,3,5),
-> PARTITION MyPart VALUES IN (2,4,6)
-> );
错误1488 (HY000): 表的所有分区必须有唯一的åå—。
è¿™æ˜¯å› ä¸ºMySQL认为分区åå—mypartå’ŒMyPart没有区别。
注释:在下é¢çš„ç« èŠ‚ä¸ï¼Œæˆ‘们没有必è¦æä¾›å¯ä»¥ç”¨æ¥åˆ›å»ºæ¯ç§åˆ†åŒºç±»åž‹è¯æ³•çš„所有å¯èƒ½å½¢å¼ï¼Œè¿™äº›ä¿¡æ¯å¯ä»¥åœ¨13.1.5节,“CREATE TABLEè¯æ³•â€ ä¸æ‰¾åˆ°ã€‚
按照RANGE分区的表是通过如下一ç§æ–¹å¼è¿›è¡Œåˆ†åŒºçš„,æ¯ä¸ªåˆ†åŒºåŒ…å«é‚£äº›åˆ†åŒºè¡¨è¾¾å¼çš„值ä½äºŽä¸€ä¸ªç»™å®šçš„è¿žç»åŒºé—´å†…的行。这些区间è¦è¿žç»ä¸”ä¸èƒ½ç›¸äº’é‡å ,使用VALUES LESS THANæ“作符æ¥è¿›è¡Œå®šä¹‰ã€‚在下é¢çš„å‡ ä¸ªä¾‹åä¸ï¼Œå‡å®šä½ 创建了一个如下的一个表,该表ä¿å˜æœ‰20家音åƒåº—çš„èŒå‘˜è®°å½•ï¼Œè¿™20家音åƒåº—çš„ç¼–å·ä»Ž1到20。
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)ï¼›
æ ¹æ®ä½ 的需è¦ï¼Œè¿™ä¸ªè¡¨å¯ä»¥æœ‰å¤šç§æ–¹å¼æ¥æŒ‰ç…§åŒºé—´è¿›è¡Œåˆ†åŒºã€‚一ç§æ–¹å¼æ˜¯ä½¿ç”¨store_id åˆ—ã€‚ä¾‹å¦‚ï¼Œä½ å¯èƒ½å†³å®šé€šè¿‡æ·»åŠ 一个PARTITION BY RANGEåå¥æŠŠè¿™ä¸ªè¡¨åˆ†å‰²æˆ4个区间,如下所示:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN (21)
)ï¼›
按照这ç§åˆ†åŒºæ–¹æ¡ˆï¼Œåœ¨å•†åº—1到5工作的雇员相对应的所有行被ä¿å˜åœ¨åˆ†åŒºP0ä¸ï¼Œå•†åº—6到10的雇员ä¿å˜åœ¨P1ä¸ï¼Œä¾æ¬¡ç±»æŽ¨ã€‚注æ„,æ¯ä¸ªåˆ†åŒºéƒ½æ˜¯æŒ‰é¡ºåºè¿›è¡Œå®šä¹‰ï¼Œä»Žæœ€ä½Žåˆ°æœ€é«˜ã€‚这是PARTITION BY RANGE è¯æ³•çš„è¦æ±‚;在这点上,它类似于C或Javaä¸çš„“switch ... caseâ€è¯å¥ã€‚
对于包å«æ•°æ®(72, 'Michael', 'Widenius', '1998-06-25', NULL, 13)的一个新行,å¯ä»¥å¾ˆå®¹æ˜“地确定它将æ’入到p2分区ä¸ï¼Œä½†æ˜¯å¦‚æžœå¢žåŠ äº†ä¸€ä¸ªç¼–å·ä¸ºç¬¬21的商店,将会å‘生什么呢?在这ç§æ–¹æ¡ˆä¸‹ï¼Œç”±äºŽæ²¡æœ‰è§„则把store_id大于20的商店包å«åœ¨å†…,æœåŠ¡å™¨å°†ä¸çŸ¥é“把该行ä¿å˜åœ¨ä½•å¤„,将会导致错误。 è¦é¿å…è¿™ç§é”™è¯¯ï¼Œå¯ä»¥é€šè¿‡åœ¨CREATE TABLEè¯å¥ä¸ä½¿ç”¨ä¸€ä¸ªâ€œcatchall†VALUES LESS THANåå¥ï¼Œè¯¥åå¥æ供给所有大于明确指定的最高值的值:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (store_id) (
PARTITION p0 VALUES LESS THAN (6),
PARTITION p1 VALUES LESS THAN (11),
PARTITION p2 VALUES LESS THAN (16),
PARTITION p3 VALUES LESS THAN MAXVALUE
)ï¼›
MAXVALUE 表示最大的å¯èƒ½çš„整数值。现在,store_id 列值大于或ç‰äºŽ16(定义了的最高值)的所有行都将ä¿å˜åœ¨åˆ†åŒºp3ä¸ã€‚在将æ¥çš„æŸä¸ªæ—¶å€™ï¼Œå½“商店数已ç»å¢žé•¿åˆ°25, 30, 或更多 ,å¯ä»¥ä½¿ç”¨ALTER TABLEè¯å¥ä¸ºå•†åº—21-25, 26-30,ç‰ç‰å¢žåŠ 新的分区 (关于如何实现的详细信æ¯å‚è§18.3节,“分区管ç†â€ )。
åœ¨å‡ ä¹Žä¸€æ ·çš„ç»“æž„ä¸ï¼Œä½ 还å¯ä»¥åŸºäºŽé›‡å‘˜çš„工作代ç æ¥åˆ†å‰²è¡¨ï¼Œä¹Ÿå°±æ˜¯è¯´ï¼ŒåŸºäºŽjob_code 列值的连ç»åŒºé—´ã€‚例如——å‡å®š2ä½æ•°å—的工作代ç 用æ¥è¡¨ç¤ºæ™®é€šï¼ˆåº—内的)工人,三个数å—代ç 表示办公室和支æŒäººå‘˜ï¼Œå››ä¸ªæ•°å—代ç 表示管ç†å±‚ï¼Œä½ å¯ä»¥ä½¿ç”¨ä¸‹é¢çš„è¯å¥åˆ›å»ºè¯¥åˆ†åŒºè¡¨ï¼š
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT NOT NULL,
store_id INT NOT NULL
)
PARTITION BY RANGE (job_code) (
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (10000)
)ï¼›
在这个例åä¸, 店内工人相关的所有行将ä¿å˜åœ¨åˆ†åŒºp0ä¸ï¼ŒåŠžå…¬å®¤å’Œæ”¯æŒäººå‘˜ç›¸å…³çš„所有行ä¿å˜åœ¨åˆ†åŒºp1ä¸ï¼Œç®¡ç†å±‚相关的所有行ä¿å˜åœ¨åˆ†åŒºp2ä¸ã€‚
在VALUES LESS THAN åå¥ä¸ä½¿ç”¨ä¸€ä¸ªè¡¨è¾¾å¼ä¹Ÿæ˜¯å¯èƒ½çš„。这里最值得注æ„çš„é™åˆ¶æ˜¯MySQL 必须能够计算表达å¼çš„返回值作为LESS THAN (<)æ¯”è¾ƒçš„ä¸€éƒ¨åˆ†ï¼›å› æ¤ï¼Œè¡¨è¾¾å¼çš„值ä¸èƒ½ä¸ºNULL ã€‚ç”±äºŽè¿™ä¸ªåŽŸå› ï¼Œé›‡å‘˜è¡¨çš„hired, separated, job_code,å’Œstore_id列已ç»è¢«å®šä¹‰ä¸ºéžç©ºï¼ˆNOT NULL)。
除了å¯ä»¥æ ¹æ®å•†åº—ç¼–å·åˆ†å‰²è¡¨æ•°æ®å¤–ï¼Œä½ è¿˜å¯ä»¥ä½¿ç”¨ä¸€ä¸ªåŸºäºŽä¸¤ä¸ªDATE (日期)ä¸çš„一个的表达å¼æ¥åˆ†å‰²è¡¨æ•°æ®ã€‚例如,å‡å®šä½ 想基于æ¯ä¸ªé›‡å‘˜ç¦»å¼€å…¬å¸çš„年份æ¥åˆ†å‰²è¡¨ï¼Œä¹Ÿå°±æ˜¯è¯´ï¼ŒYEAR(separated)的值。实现这ç§åˆ†åŒºæ¨¡å¼çš„CREATE TABLE è¯å¥çš„一个例å如下所示:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY RANGE (YEAR(separated)) (
PARTITION p0 VALUES LESS THAN (1991),
PARTITION p1 VALUES LESS THAN (1996),
PARTITION p2 VALUES LESS THAN (2001),
PARTITION p3 VALUES LESS THAN MAXVALUE
)ï¼›
在这个方案ä¸ï¼Œåœ¨1991å¹´å‰é›‡ä½£çš„所有雇员的记录ä¿å˜åœ¨åˆ†åŒºp0ä¸ï¼Œ1991年到1995年期间雇佣的所有雇员的记录ä¿å˜åœ¨åˆ†åŒºp1ä¸ï¼Œ 1996年到2000年期间雇佣的所有雇员的记录ä¿å˜åœ¨åˆ†åŒºp2ä¸ï¼Œ2000å¹´åŽé›‡ä½£çš„所有工人的信æ¯ä¿å˜åœ¨p3ä¸ã€‚
RANGE分区在如下场åˆç‰¹åˆ«æœ‰ç”¨ï¼š
· 当需è¦åˆ 除“旧的â€æ•°æ®æ—¶ã€‚å¦‚æžœä½ ä½¿ç”¨ä¸Šé¢æœ€è¿‘的那个例åç»™å‡ºçš„åˆ†åŒºæ–¹æ¡ˆï¼Œä½ åªéœ€ç®€å•åœ°ä½¿ç”¨ “ALTER TABLE employees DROP PARTITION p0ï¼›â€æ¥åˆ 除所有在1991å¹´å‰å°±å·²ç»åœæ¢å·¥ä½œçš„雇员相对应的所有行。(更多信æ¯è¯·å‚è§13.1.2节,“ALTER TABLEè¯æ³•â€ å’Œ 18.3节,“分区管ç†â€ï¼‰ã€‚对于有大é‡è¡Œçš„表,这比è¿è¡Œä¸€ä¸ªå¦‚“DELETE FROM employees WHERE YEAR(separated) <= 1990ï¼›â€è¿™æ ·çš„一个DELETE查询è¦æœ‰æ•ˆå¾—多。
· 想è¦ä½¿ç”¨ä¸€ä¸ªåŒ…å«æœ‰æ—¥æœŸæˆ–时间值,或包å«æœ‰ä»Žä¸€äº›å…¶ä»–级数开始增长的值的列。
· ç»å¸¸è¿è¡Œç›´æŽ¥ä¾èµ–于用于分割表的列的查询。例如,当执行一个如“SELECT COUNT(*) FROM employees WHERE YEAR(separated) = 2000 GROUP BY store_idï¼›â€è¿™æ ·çš„查询时,MySQLå¯ä»¥å¾ˆè¿…速地确定åªæœ‰åˆ†åŒºp2需è¦æ‰«æï¼Œè¿™æ˜¯å› ä¸ºä½™ä¸‹çš„åˆ†åŒºä¸å¯èƒ½åŒ…å«æœ‰ç¬¦åˆè¯¥WHEREåå¥çš„任何记录。注释:这ç§ä¼˜åŒ–还没有在MySQL 5.1æºç¨‹åºä¸å¯ç”¨ï¼Œä½†æ˜¯ï¼Œæœ‰å…³å·¥ä½œæ£åœ¨è¿›è¡Œä¸ã€‚
MySQLä¸çš„LIST分区在很多方é¢ç±»ä¼¼äºŽRANGE分区。和按照RANGEåˆ†åŒºä¸€æ ·ï¼Œæ¯ä¸ªåˆ†åŒºå¿…须明确定义。它们的主è¦åŒºåˆ«åœ¨äºŽï¼ŒLIST分区ä¸æ¯ä¸ªåˆ†åŒºçš„定义和选择是基于æŸåˆ—的值从属于一个值列表集ä¸çš„一个值,而RANGE分区是从属于一个连ç»åŒºé—´å€¼çš„集åˆã€‚LIST分区通过使用“PARTITION BY LIST(expr)â€æ¥å®žçŽ°ï¼Œå…¶ä¸â€œexpr†是æŸåˆ—值或一个基于æŸä¸ªåˆ—值ã€å¹¶è¿”回一个整数值的表达å¼ï¼Œç„¶åŽé€šè¿‡â€œVALUES IN (value_list)â€çš„æ–¹å¼æ¥å®šä¹‰æ¯ä¸ªåˆ†åŒºï¼Œå…¶ä¸â€œvalue_listâ€æ˜¯ä¸€ä¸ªé€šè¿‡é€—å·åˆ†éš”的整数列表。
注释:在MySQL 5.1ä¸ï¼Œå½“使用LIST分区时,有å¯èƒ½åªèƒ½åŒ¹é…整数列表。
ä¸åƒæŒ‰ç…§RANGE定义分区的情形,LIST分区ä¸å¿…声明任何特定的顺åºã€‚关于LIST分区更详细的è¯æ³•ä¿¡æ¯ï¼Œè¯·å‚考13.1.5节,“CREATE TABLEè¯æ³•â€ 。
对于下é¢ç»™å‡ºçš„例å,我们å‡å®šå°†è¦è¢«åˆ†åŒºçš„表的基本定义是通过下é¢çš„“CREATE TABLEâ€è¯å¥æ供的:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)ï¼›
(这和18.2.1节,“RANGE分区†ä¸çš„例åä¸ä½¿ç”¨çš„是åŒä¸€ä¸ªè¡¨ï¼‰ã€‚
å‡å®šæœ‰20个音åƒåº—,分布在4个有ç»é”€æƒçš„地区,如下表所示:
地区 |
商店ID å· |
北区 |
3, 5, 6, 9, 17 |
东区 |
1, 2, 10, 11, 19, 20 |
西区 |
4, 12, 13, 14, 18 |
ä¸å¿ƒåŒº |
7, 8, 15, 16 |
è¦æŒ‰ç…§å±žäºŽåŒä¸€ä¸ªåœ°åŒºå•†åº—çš„è¡Œä¿å˜åœ¨åŒä¸€ä¸ªåˆ†åŒºä¸çš„æ–¹å¼æ¥åˆ†å‰²è¡¨ï¼Œå¯ä»¥ä½¿ç”¨ä¸‹é¢çš„“CREATE TABLEâ€è¯å¥ï¼š
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LIST(store_id)
PARTITION pNorth VALUES IN (3,5,6,9,17),
PARTITION pEast VALUES IN (1,2,10,11,19,20),
PARTITION pWest VALUES IN (4,12,13,14,18),
PARTITION pCentral VALUES IN (7,8,15,16)
)ï¼›
这使得在表ä¸å¢žåŠ æˆ–åˆ é™¤æŒ‡å®šåœ°åŒºçš„é›‡å‘˜è®°å½•å˜å¾—容易起æ¥ã€‚例如,å‡å®šè¥¿åŒºçš„所有音åƒåº—都å–给了其他公å¸ã€‚那么与在西区音åƒåº—工作雇员相关的所有记录(行)å¯ä»¥ä½¿ç”¨æŸ¥è¯¢â€œALTER TABLE employees DROP PARTITION pWestï¼›â€æ¥è¿›è¡Œåˆ 除,它与具有åŒæ ·ä½œç”¨çš„DELETE ï¼ˆåˆ é™¤ï¼‰æŸ¥è¯¢â€œDELETE query DELETE FROM employees WHERE store_id IN (4,12,13,14,18)ï¼›â€æ¯”èµ·æ¥ï¼Œè¦æœ‰æ•ˆå¾—多。
è¦ç‚¹ï¼šå¦‚果试图æ’入列值(或分区表达å¼çš„返回值)ä¸åœ¨åˆ†åŒºå€¼åˆ—表ä¸çš„一行时,那么“INSERTâ€æŸ¥è¯¢å°†å¤±è´¥å¹¶æŠ¥é”™ã€‚例如,å‡å®šLIST分区的采用上é¢çš„方案,下é¢çš„查询将失败:
INSERT INTO employees VALUES
(224, 'Linus', 'Torvalds', '2002-05-01', '2004-10-12', 42, 21);
è¿™æ˜¯å› ä¸ºâ€œstore_idâ€åˆ—值21ä¸èƒ½åœ¨ç”¨äºŽå®šä¹‰åˆ†åŒºpNorth, pEast, pWest,或pCentral的值列表ä¸æ‰¾åˆ°ã€‚è¦é‡ç‚¹æ³¨æ„的是,LIST分区没有类似如“VALUES LESS THAN MAXVALUEâ€è¿™æ ·çš„包å«å…¶ä»–值在内的定义。将è¦åŒ¹é…的任何值都必须在值列表ä¸æ‰¾åˆ°ã€‚
LIST分区除了能和RANGE分区结åˆèµ·æ¥ç”Ÿæˆä¸€ä¸ªå¤åˆçš„å分区,与HASHå’ŒKEY分区结åˆèµ·æ¥ç”Ÿæˆå¤åˆçš„å分区也是å¯èƒ½çš„。 关于这方é¢çš„讨论,请å‚考18.2.5节,“å分区â€ã€‚
HASH分区主è¦ç”¨æ¥ç¡®ä¿æ•°æ®åœ¨é¢„先确定数目的分区ä¸å¹³å‡åˆ†å¸ƒã€‚在RANGEå’ŒLIST分区ä¸ï¼Œå¿…须明确指定一个给定的列值或列值集åˆåº”该ä¿å˜åœ¨å“ªä¸ªåˆ†åŒºä¸ï¼›è€Œåœ¨HASH分区ä¸ï¼ŒMySQL 自动完æˆè¿™äº›å·¥ä½œï¼Œä½ 所è¦åšçš„åªæ˜¯åŸºäºŽå°†è¦è¢«å“ˆå¸Œçš„列值指定一个列值或表达å¼ï¼Œä»¥åŠæŒ‡å®šè¢«åˆ†åŒºçš„表将è¦è¢«åˆ†å‰²æˆçš„分区数é‡ã€‚
è¦ä½¿ç”¨HASH分区æ¥åˆ†å‰²ä¸€ä¸ªè¡¨ï¼Œè¦åœ¨CREATE TABLE è¯å¥ä¸Šæ·»åŠ 一个“PARTITION BY HASH (expr)â€åå¥ï¼Œå…¶ä¸â€œexprâ€æ˜¯ä¸€ä¸ªè¿”回一个整数的表达å¼ã€‚它å¯ä»¥ä»…仅是å—段类型为MySQL 整型的一列的åå—。æ¤å¤–ï¼Œä½ å¾ˆå¯èƒ½éœ€è¦åœ¨åŽé¢å†æ·»åŠ 一个“PARTITIONS numâ€åå¥ï¼Œå…¶ä¸num 是一个éžè´Ÿçš„整数,它表示表将è¦è¢«åˆ†å‰²æˆåˆ†åŒºçš„æ•°é‡ã€‚
例如,下é¢çš„è¯å¥åˆ›å»ºäº†ä¸€ä¸ªä½¿ç”¨åŸºäºŽâ€œstore_idâ€åˆ—进行 哈希处ç†çš„表,该表被分æˆäº†4个分区:
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH(store_id)
PARTITIONS 4ï¼›
如果没有包括一个PARTITIONSåå¥ï¼Œé‚£ä¹ˆåˆ†åŒºçš„æ•°é‡å°†é»˜è®¤ä¸º1。 例外: 对于NDB Cluster(簇)表,默认的分区数é‡å°†ä¸Žç°‡æ•°æ®èŠ‚点的数é‡ç›¸åŒï¼Œè¿™ç§ä¿®æ£å¯èƒ½æ˜¯è€ƒè™‘任何MAX_ROWS 设置,以便确ä¿æ‰€æœ‰çš„行都能åˆé€‚地æ’入到分区ä¸ã€‚(å‚è§ç¬¬17ç« ï¼šMySQL簇)。
如果在关键å—“PARTITIONSâ€åŽé¢æ²¡æœ‰åŠ 上分区的数é‡ï¼Œå°†ä¼šå‡ºçŽ°è¯æ³•é”™è¯¯ã€‚
“exprâ€è¿˜å¯ä»¥æ˜¯ä¸€ä¸ªè¿”回一个整数的SQL表达å¼ã€‚ä¾‹å¦‚ï¼Œä¹Ÿè®¸ä½ æƒ³åŸºäºŽé›‡ç”¨é›‡å‘˜çš„å¹´ä»½æ¥è¿›è¡Œåˆ†åŒºã€‚è¿™å¯ä»¥é€šè¿‡ä¸‹é¢çš„è¯å¥æ¥å®žçŽ°ï¼š
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY HASH(YEAR(hired))
PARTITIONS 4ï¼›
“exprâ€è¿˜å¯ä»¥æ˜¯MySQL ä¸æœ‰æ•ˆçš„任何函数或其他表达å¼ï¼Œåªè¦å®ƒä»¬è¿”回一个既éžå¸¸æ•°ã€ä¹Ÿéžéšæœºæ•°çš„整数。(æ¢å¥è¯è¯´ï¼Œå®ƒæ—¢æ˜¯å˜åŒ–的但åˆæ˜¯ç¡®å®šçš„)。但是应当记ä½ï¼Œæ¯å½“æ’入或更新(或者å¯èƒ½åˆ 除)一行,这个表达å¼éƒ½è¦è®¡ç®—一次;这æ„味ç€éžå¸¸å¤æ‚的表达å¼å¯èƒ½ä¼šå¼•èµ·æ€§èƒ½é—®é¢˜ï¼Œå°¤å…¶æ˜¯åœ¨æ‰§è¡ŒåŒæ—¶å½±å“大é‡è¡Œçš„è¿ç®—(例如批é‡æ’入)的时候。
最有效率的哈希函数是åªå¯¹å•ä¸ªè¡¨åˆ—进行计算,并且它的值éšåˆ—值进行一致地增大或å‡å°ï¼Œå› 为这考虑了在分区范围上的“修剪â€ã€‚也就是说,表达å¼å€¼å’Œå®ƒæ‰€åŸºäºŽçš„列的值å˜åŒ–越接近,MySQLå°±å¯ä»¥è¶Šæœ‰æ•ˆåœ°ä½¿ç”¨è¯¥è¡¨è¾¾å¼æ¥è¿›è¡ŒHASH分区。
例如,“date_col†是一个DATE(日期)类型的列,那么表达å¼TO_DAYS(date_col)å°±å¯ä»¥è¯´æ˜¯éšåˆ—“date_colâ€å€¼çš„å˜åŒ–而å‘生直接的å˜åŒ–ï¼Œå› ä¸ºåˆ—â€œdate_colâ€å€¼çš„æ¯ä¸ªå˜åŒ–,表达å¼çš„值也将å‘生与之一致的å˜åŒ–。而表达å¼YEAR(date_col)çš„å˜åŒ–就没有表达å¼TO_DAYS(date_col)é‚£ä¹ˆç›´æŽ¥ï¼Œå› ä¸ºä¸æ˜¯åˆ—“date_colâ€æ¯æ¬¡å¯èƒ½çš„改å˜éƒ½èƒ½ä½¿è¡¨è¾¾å¼YEAR(date_col)å‘生åŒç‰çš„改å˜ã€‚å³ä¾¿å¦‚æ¤ï¼Œè¡¨è¾¾å¼YEAR(date_col)也还是一个用于 哈希函数的ã€å¥½çš„候选表达å¼ï¼Œå› 为它éšåˆ—date_col的一部分å‘生直接å˜åŒ–,并且列date_colçš„å˜åŒ–ä¸å¯èƒ½å¼•èµ·è¡¨è¾¾å¼YEAR(date_col)ä¸æˆæ¯”例的å˜åŒ–。
作为对照,å‡å®šæœ‰ä¸€ä¸ªç±»åž‹ä¸ºæ•´åž‹ï¼ˆINT)的ã€åˆ—å为“int_colâ€çš„列。现在考虑表达å¼â€œPOW(5-int_col,3) + 6â€ã€‚这对于哈希函数就是一个ä¸å¥½çš„é€‰æ‹©ï¼Œå› ä¸ºâ€œint_colâ€å€¼çš„å˜åŒ–并ä¸èƒ½ä¿è¯è¡¨è¾¾å¼äº§ç”Ÿæˆæ¯”例的å˜åŒ–。列 “int_colâ€çš„值å‘生一个给定数目的å˜åŒ–,å¯èƒ½ä¼šå¼•èµ·è¡¨è¾¾å¼çš„值产生一个很大ä¸åŒçš„å˜åŒ–。例如,把列“int_colâ€çš„值从5å˜ä¸º6,表达å¼çš„值将产生“ï¼1â€çš„改å˜ï¼Œä½†æ˜¯æŠŠåˆ—“int_colâ€çš„值从6å˜ä¸º7时,表达å¼çš„值将产生“ï¼7â€çš„å˜åŒ–。
æ¢å¥è¯è¯´ï¼Œå¦‚果列值与表达å¼å€¼ä¹‹æ¯”的曲线图越接近由ç‰å¼â€œy=nx(其ä¸n为éžé›¶çš„常数)æ绘出的直线,则该表达å¼è¶Šé€‚åˆäºŽ å“ˆå¸Œã€‚è¿™æ˜¯å› ä¸ºï¼Œè¡¨è¾¾å¼çš„éžçº¿æ€§è¶Šä¸¥é‡ï¼Œåˆ†åŒºä¸æ•°æ®äº§ç”Ÿéžå‡è¡¡åˆ†å¸ƒçš„趋势也将越严é‡ã€‚
ç†è®ºä¸Šè®²ï¼Œå¯¹äºŽæ¶‰åŠåˆ°å¤šåˆ—的表达å¼ï¼Œâ€œä¿®å‰ªï¼ˆpruning)â€ä¹Ÿæ˜¯å¯èƒ½çš„,但是è¦ç¡®å®šå“ªäº›é€‚于 哈希是éžå¸¸å›°éš¾å’Œè€—æ—¶çš„ã€‚åŸºäºŽè¿™ä¸ªåŽŸå› ï¼Œå®žé™…ä¸Šä¸æŽ¨è使用涉åŠåˆ°å¤šåˆ—的哈希表达å¼ã€‚
当使用了“PARTITION BY HASHâ€æ—¶ï¼ŒMySQL将基于用户函数结果的模数æ¥ç¡®å®šä½¿ç”¨å“ªä¸ªç¼–å·çš„分区。æ¢å¥è¯ï¼Œå¯¹äºŽä¸€ä¸ªè¡¨è¾¾å¼â€œexprâ€ï¼Œå°†è¦ä¿å˜è®°å½•çš„分区编å·ä¸ºN ,其ä¸â€œN = MOD(expr, num)â€ã€‚例如,å‡å®šè¡¨t1 定义如下,它有4个分区:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY HASH( YEAR(col3) )
PARTITIONS 4ï¼›
如果æ’入一个col3列值为'2005-09-15'的记录到表t1ä¸ï¼Œé‚£ä¹ˆä¿å˜è¯¥æ¡è®°å½•çš„分区确定如下:
MOD(YEAR('2005-09-01'),4)
= MOD(2005,4)
= 1
MySQL 5.1 还支æŒä¸€ä¸ªè¢«ç§°ä¸ºâ€œlinear hashing(线性哈希功能)â€çš„å˜é‡ï¼Œå®ƒä½¿ç”¨ä¸€ä¸ªæ›´åŠ å¤æ‚的算法æ¥ç¡®å®šæ–°è¡Œæ’入到已ç»åˆ†åŒºäº†çš„表ä¸çš„ä½ç½®ã€‚关于这ç§ç®—法的æ述,请å‚è§18.2.3.1节,“LINEAR HASH分区†。
æ¯å½“æ’入或更新一æ¡è®°å½•ï¼Œç”¨æˆ·å‡½æ•°éƒ½è¦è®¡ç®—ä¸€æ¬¡ã€‚å½“åˆ é™¤è®°å½•æ—¶ï¼Œç”¨æˆ·å‡½æ•°ä¹Ÿå¯èƒ½è¦è¿›è¡Œè®¡ç®—,这å–决于所处的环境。
注释:如果将è¦åˆ†åŒºçš„表有一个唯一的键,那么用æ¥ä½œä¸ºHASH用户函数的自å˜æ•°æˆ–者主键的column_list的自å˜æ•°çš„ä»»æ„列都必须是那个键的一部分。
MySQL还支æŒçº¿æ€§å“ˆå¸ŒåŠŸèƒ½ï¼Œå®ƒä¸Žå¸¸è§„哈希的区别在于,线性哈希功能使用的一个线性的2的幂(powers-of-two)è¿ç®—法则,而常规 哈希使用的是求哈希函数值的模数。
线性哈希分区和常规哈希分区在è¯æ³•ä¸Šçš„唯一区别在于,在“PARTITION BY†åå¥ä¸æ·»åŠ “LINEARâ€å…³é”®å—,如下é¢æ‰€ç¤ºï¼š
CREATE TABLE employees (
id INT NOT NULL,
fname VARCHAR(30),
lname VARCHAR(30),
hired DATE NOT NULL DEFAULT '1970-01-01',
separated DATE NOT NULL DEFAULT '9999-12-31',
job_code INT,
store_id INT
)
PARTITION BY LINEAR HASH(YEAR(hired))
PARTITIONS 4ï¼›
å‡è®¾ä¸€ä¸ªè¡¨è¾¾å¼expr, 当使用线性哈希功能时,记录将è¦ä¿å˜åˆ°çš„分区是num 个分区ä¸çš„分区N,其ä¸Næ˜¯æ ¹æ®ä¸‹é¢çš„算法得到:
1. 找到下一个大于num.çš„ã€2的幂,我们把这个值称为V ,它å¯ä»¥é€šè¿‡ä¸‹é¢çš„å…¬å¼å¾—到:
2. V = POWER(2, CEILING(LOG(2, num)))
(例如,å‡å®šnum是13。那么LOG(2,13)就是3.7004397181411。 CEILING(3.7004397181411)就是4,则V = POWER(2,4), å³ç‰äºŽ16)。
3. 设置 N = F(column_list) & (V - 1).
4. 当 N >= num:
· 设置 V = CEIL(V / 2)
· 设置 N = N & (V - 1)
例如,å‡è®¾è¡¨t1,使用线性哈希分区且有4个分区,是通过下é¢çš„è¯å¥åˆ›å»ºçš„:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE)
PARTITION BY LINEAR HASH( YEAR(col3) )
PARTITIONS 6;
现在å‡è®¾è¦æ’入两行记录到表t1ä¸ï¼Œå…¶ä¸ä¸€æ¡è®°å½•col3列值为'2003-04-14',å¦ä¸€æ¡è®°å½•col3列值为'1998-10-19'。第一æ¡è®°å½•å°†è¦ä¿å˜åˆ°çš„分区确定如下:
V = POWER(2, CEILING(LOG(2,7))) = 8
N = YEAR('2003-04-14') & (8 - 1)
= 2003 & 7
= 3
(3 >= 6 为å‡ï¼ˆFALSE): 记录将被ä¿å˜åˆ°#3å·åˆ†åŒºä¸)
第二æ¡è®°å½•å°†è¦ä¿å˜åˆ°çš„分区åºå·è®¡ç®—如下:
V = 8
N = YEAR('1998-10-19') & (8-1)
= 1998 & 7
= 6
(6 >= 4 为真(TRUE): 还需è¦é™„åŠ çš„æ¥éª¤)
N = 6 & CEILING(5 / 2)
= 6 & 3
= 2
(2 >= 4 为å‡ï¼ˆFALSE): 记录将被ä¿å˜åˆ°#2分区ä¸)
æŒ‰ç…§çº¿æ€§å“ˆå¸Œåˆ†åŒºçš„ä¼˜ç‚¹åœ¨äºŽå¢žåŠ ã€åˆ 除ã€åˆå¹¶å’Œæ‹†åˆ†åˆ†åŒºå°†å˜å¾—æ›´åŠ å¿«æ·ï¼Œæœ‰åˆ©äºŽå¤„ç†å«æœ‰æžå…¶å¤§é‡ï¼ˆ1000å‰ï¼‰æ•°æ®çš„表。它的缺点在于,与使用常规HASH分区得到的数æ®åˆ†å¸ƒç›¸æ¯”,å„个分区间数æ®çš„分布ä¸å¤§å¯èƒ½å‡è¡¡ã€‚
按照KEY进行分区类似于按照HASH分区,除了HASH分区使用的用户定义的表达å¼ï¼Œè€ŒKEY分区的 哈希函数是由MySQL æœåŠ¡å™¨æ供。MySQL 簇(Cluster)使用函数MD5()æ¥å®žçŽ°KEY分区;对于使用其他å˜å‚¨å¼•æ“Žçš„表,æœåŠ¡å™¨ä½¿ç”¨å…¶è‡ªå·±å†…部的 哈希函数,这些函数是基于与PASSWORD()ä¸€æ ·çš„è¿ç®—法则。
“CREATE TABLE ... PARTITION BY KEYâ€çš„è¯æ³•è§„则类似于创建一个通过HASH分区的表的规则。它们唯一的区别在于使用的关键å—是KEY而ä¸æ˜¯HASH,并且KEY分区åªé‡‡ç”¨ä¸€ä¸ªæˆ–多个列å的一个列表。
通过线性KEY分割一个表也是å¯èƒ½çš„。下é¢æ˜¯ä¸€ä¸ªç®€å•çš„例å:
CREATE TABLE tk (
col1 INT NOT NULL,
col2 CHAR(5),
col3 DATE
)
PARTITION BY LINEAR KEY (col1)
PARTITIONS 3;
在KEY分区ä¸ä½¿ç”¨å…³é”®å—LINEAR和在HASH分区ä¸ä½¿ç”¨å…·æœ‰åŒæ ·çš„作用,分区的编å·æ˜¯é€šè¿‡2的幂(powers-of-two)算法得到,而ä¸æ˜¯é€šè¿‡æ¨¡æ•°ç®—法。关于该算法åŠå…¶è•´æ¶µå¼çš„æ述请å‚考 18.2.3.1节,“LINEAR HASH分区†。
å分区是分区表ä¸æ¯ä¸ªåˆ†åŒºçš„å†æ¬¡åˆ†å‰²ã€‚例如,考虑下é¢çš„CREATE TABLE è¯å¥ï¼š
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH(TO_DAYS(purchased))
SUBPARTITIONS 2
(
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
)ï¼›
表ts 有3个RANGE分区。这3个分区ä¸çš„æ¯ä¸€ä¸ªåˆ†åŒºâ€”—p0, p1, å’Œ p2 ——åˆè¢«è¿›ä¸€æ¥åˆ†æˆäº†2个å分区。实际上,整个表被分æˆäº†3 * 2 = 6个分区。但是,由于PARTITION BY RANGEåå¥çš„作用,这些分区的头2个åªä¿å˜â€œpurchasedâ€åˆ—ä¸å€¼å°äºŽ1990的那些记录。
在MySQL 5.1ä¸ï¼Œå¯¹äºŽå·²ç»é€šè¿‡RANGE或LIST分区了的表å†è¿›è¡Œå分区是å¯èƒ½çš„。å分区既å¯ä»¥ä½¿ç”¨HASH希分区,也å¯ä»¥ä½¿ç”¨KEY分区。这也被称为å¤åˆåˆ†åŒºï¼ˆcomposite partitioning)。
为了对个别的å分区指定选项,使用SUBPARTITION åå¥æ¥æ˜Žç¡®å®šä¹‰å分区也是å¯èƒ½çš„。例如,创建在å‰é¢ä¾‹åä¸ç»™å‡ºçš„åŒä¸€ä¸ªè¡¨çš„ã€ä¸€ä¸ªæ›´åŠ 详细的方å¼å¦‚下:
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH(TO_DAYS(purchased))
(
PARTITION p0 VALUES LESS THAN (1990)
(
SUBPARTITION s0,
SUBPARTITION s1
),
PARTITION p1 VALUES LESS THAN (2000)
(
SUBPARTITION s2,
SUBPARTITION s3
),
PARTITION p2 VALUES LESS THAN MAXVALUE
(
SUBPARTITION s4,
SUBPARTITION s5
)
);
å‡ ç‚¹è¦æ³¨æ„çš„è¯æ³•é¡¹ï¼š
· æ¯ä¸ªåˆ†åŒºå¿…须有相åŒæ•°é‡çš„å分区。
· 如果在一个分区表上的任何分区上使用SUBPARTITION æ¥æ˜Žç¡®å®šä¹‰ä»»ä½•å分区,那么就必须定义所有的å分区。æ¢å¥è¯è¯´ï¼Œä¸‹é¢çš„è¯å¥å°†æ‰§è¡Œå¤±è´¥ï¼š
· CREATE TABLE ts (id INT, purchased DATE)
· PARTITION BY RANGE(YEAR(purchased))
· SUBPARTITION BY HASH(TO_DAYS(purchased))
· (
· PARTITION p0 VALUES LESS THAN (1990)
· (
· SUBPARTITION s0,
· SUBPARTITION s1
· ),
· PARTITION p1 VALUES LESS THAN (2000),
· PARTITION p2 VALUES LESS THAN MAXVALUE
· (
· SUBPARTITION s2,
· SUBPARTITION s3
· )
· );
å³ä¾¿è¿™ä¸ªè¯å¥åŒ…å«äº†ä¸€ä¸ªSUBPARTITIONS 2åå¥ï¼Œä½†æ˜¯å®ƒä»ç„¶ä¼šæ‰§è¡Œå¤±è´¥ã€‚
· æ¯ä¸ªSUBPARTITION åå¥å¿…须包括 (至少)å分区的一个åå—。å¦åˆ™ï¼Œä½ å¯èƒ½è¦å¯¹è¯¥ååˆ†åŒºè®¾ç½®ä»»ä½•ä½ æ‰€éœ€è¦çš„选项,或者å…许该å分区对那些选项采用其默认的设置。
· 在æ¯ä¸ªåˆ†åŒºå†…,å分区的åå—必须是唯一的,但是在整个表ä¸ï¼Œæ²¡æœ‰å¿…è¦ä¿æŒå”¯ä¸€ã€‚例如,下é¢çš„CREATE TABLE è¯å¥æ˜¯æœ‰æ•ˆçš„:
· CREATE TABLE ts (id INT, purchased DATE)
· PARTITION BY RANGE(YEAR(purchased))
· SUBPARTITION BY HASH(TO_DAYS(purchased))
· (
· PARTITION p0 VALUES LESS THAN (1990)
· (
· SUBPARTITION s0,
· SUBPARTITION s1
· ),
· PARTITION p1 VALUES LESS THAN (2000)
· (
· SUBPARTITION s0,
· SUBPARTITION s1
· ),
· PARTITION p2 VALUES LESS THAN MAXVALUE
· (
· SUBPARTITION s0,
· SUBPARTITION s1
· )
· );
å分区å¯ä»¥ç”¨äºŽç‰¹åˆ«å¤§çš„表,在多个ç£ç›˜é—´åˆ†é…æ•°æ®å’Œç´¢å¼•ã€‚å‡è®¾æœ‰6个ç£ç›˜ï¼Œåˆ†åˆ«ä¸º/disk0, /disk1, /disk2ç‰ã€‚现在考虑下é¢çš„例å:
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH(TO_DAYS(purchased))
(
PARTITION p0 VALUES LESS THAN (1990)
(
SUBPARTITION s0
DATA DIRECTORY = '/disk0/data'
INDEX DIRECTORY = '/disk0/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk1/data'
INDEX DIRECTORY = '/disk1/idx'
),
PARTITION p1 VALUES LESS THAN (2000)
(
SUBPARTITION s0
DATA DIRECTORY = '/disk2/data'
INDEX DIRECTORY = '/disk2/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk3/data'
INDEX DIRECTORY = '/disk3/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE
(
SUBPARTITION s0
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s1
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
)
)ï¼›
在这个例åä¸ï¼Œæ¯ä¸ªRANGE分区的数æ®å’Œç´¢å¼•éƒ½ä½¿ç”¨ä¸€ä¸ªå•ç‹¬çš„ç£ç›˜ã€‚还å¯èƒ½æœ‰è®¸å¤šå…¶ä»–çš„å˜åŒ–;下é¢æ˜¯å¦å¤–一个å¯èƒ½çš„例å:
CREATE TABLE ts (id INT, purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH(TO_DAYS(purchased))
(
PARTITION p0 VALUES LESS THAN (1990)
(
SUBPARTITION s0a
DATA DIRECTORY = '/disk0'
INDEX DIRECTORY = '/disk1',
SUBPARTITION s0b
DATA DIRECTORY = '/disk2'
INDEX DIRECTORY = '/disk3'
),
PARTITION p1 VALUES LESS THAN (2000)
(
SUBPARTITION s1a
DATA DIRECTORY = '/disk4/data'
INDEX DIRECTORY = '/disk4/idx',
SUBPARTITION s1b
DATA DIRECTORY = '/disk5/data'
INDEX DIRECTORY = '/disk5/idx'
),
PARTITION p2 VALUES LESS THAN MAXVALUE
(
SUBPARTITION s2a,
SUBPARTITION s2b
)
)ï¼›
在这个例åä¸ï¼Œå˜å‚¨çš„分é…如下:
· è´ä¹°æ—¥æœŸåœ¨1990å¹´å‰çš„记录å 了大é‡çš„å˜å‚¨ç©ºé—´ï¼Œæ‰€ä»¥æŠŠå®ƒåˆ†ä¸ºäº†å››ä¸ªéƒ¨åˆ†è¿›è¡Œå˜å‚¨ï¼Œç»„æˆp0分区的两个å分区(s0a å’Œs0b)的数æ®å’Œç´¢å¼•éƒ½åˆ†åˆ«ç”¨ä¸€ä¸ªå•ç‹¬çš„ç£ç›˜è¿›è¡Œå˜å‚¨ã€‚æ¢å¥è¯è¯´ï¼š
o å分区s0a çš„æ•°æ®ä¿å˜åœ¨ç£ç›˜/disk0ä¸ã€‚
o å分区s0a 的索引ä¿å˜åœ¨ç£ç›˜/disk1ä¸ã€‚
o å分区s0b çš„æ•°æ®ä¿å˜åœ¨ç£ç›˜/disk2ä¸ã€‚
o å分区s0b 的索引ä¿å˜åœ¨ç£ç›˜/disk3ä¸ã€‚
· ä¿å˜è´ä¹°æ—¥æœŸä»Ž1990年到1999年间的记录(分区p1)ä¸éœ€è¦ä¿å˜è´ä¹°æ—¥æœŸåœ¨1990年之å‰çš„记录那么大的å˜å‚¨ç©ºé—´ã€‚这些记录分在2个ç£ç›˜ï¼ˆ/disk4å’Œ/disk5)上ä¿å˜ï¼Œè€Œä¸æ˜¯4个ç£ç›˜ï¼š
o 属于分区p1的第一个å分区(s1a)的数æ®å’Œç´¢å¼•ä¿å˜åœ¨ç£ç›˜/disk4上 — å…¶ä¸æ•°æ®ä¿å˜åœ¨è·¯å¾„/disk4/data下,索引ä¿å˜åœ¨/disk4/idx下。
o 属于分区p1的第二个å分区(s1b)的数æ®å’Œç´¢å¼•ä¿å˜åœ¨ç£ç›˜/disk5上 — å…¶ä¸æ•°æ®ä¿å˜åœ¨è·¯å¾„/disk5/data下,索引ä¿å˜åœ¨/disk5/idx下。
· ä¿å˜è´ä¹°æ—¥æœŸä»Ž2000年到现在的记录(分区p2)ä¸éœ€è¦å‰é¢ä¸¤ä¸ªRANGE分区那么大的空间。当å‰ï¼Œåœ¨é»˜è®¤çš„ä½ç½®èƒ½å¤Ÿè¶³å¤Ÿä¿å˜æ‰€æœ‰è¿™äº›è®°å½•ã€‚
å°†æ¥ï¼Œå¦‚果从2000年开始åŽåå¹´è´ä¹°çš„æ•°é‡å·²ç»è¾¾åˆ°äº†é»˜è®¤çš„ä½ç½®ä¸èƒ½å¤Ÿæ供足够的ä¿å˜ç©ºé—´æ—¶ï¼Œç›¸åº”的记录(行)å¯ä»¥é€šè¿‡ä½¿ç”¨â€œALTER TABLE ... REORGANIZE PARTITIONâ€è¯å¥ç§»åŠ¨åˆ°å…¶ä»–çš„ä½ç½®ã€‚关于如何实现的说明,请å‚è§18.3节,“分区管ç†â€ 。
MySQL ä¸çš„分区在ç¦æ¢ç©ºå€¼ï¼ˆNULL)上没有进行处ç†ï¼Œæ— 论它是一个列值还是一个用户定义表达å¼çš„值。一般而言,在这ç§æƒ…况下MySQL 把NULL视为0ã€‚å¦‚æžœä½ å¸Œæœ›å›žé¿è¿™ç§åšæ³•ï¼Œä½ 应该在设计表时ä¸å…许空值;最å¯èƒ½çš„方法是,通过声明列“NOT NULLâ€æ¥å®žçŽ°è¿™ä¸€ç‚¹ã€‚
在本节ä¸ï¼Œæˆ‘们æ供了一些例å,æ¥è¯´æ˜Žå½“决定一个行应该ä¿å˜åˆ°å“ªä¸ªåˆ†åŒºæ—¶ï¼ŒMySQL 是如何处ç†NULL值的。
如果æ’入一行到按照RANGE或LIST分区的表,该行用æ¥ç¡®å®šåˆ†åŒºçš„列值为NULL,分区将把该NULL值视为0。例如,考虑下é¢çš„两个表,表的创建和æ’入记录如下:
mysql> CREATE TABLE tnlist (
-> id INT,
-> name VARCHAR(5)
-> )
-> PARTITION BY LIST(id) (
-> PARTITION p1 VALUES IN (0),
-> PARTITION p2 VALUES IN (1)
-> );
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE TABLE tnrange (
-> id INT,
-> name VARCHAR(5)
-> )
-> PARTITION BY RANGE(id) (
-> PARTITION p1 VALUES LESS THAN (1),
-> PARTITION p2 VALUES LESS THAN MAXVALUE
-> );
Query OK, 0 rows affected (0.09 sec)
mysql> INSERT INTO tnlist VALUES (NULL, 'bob');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO tnrange VALUES (NULL, 'jim');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM tnlist;
+------+------+
| id | name |
+------+------+
| NULL | bob |
+------+------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tnrange;
+------+------+
| id | name |
+------+------+
| NULL | jim |
+------+------+
1 row in set (0.00 sec)
在两个表ä¸ï¼Œid列没有声明为“NOT NULLâ€ï¼Œè¿™æ„味ç€å®ƒä»¬å…许Null值。å¯ä»¥é€šè¿‡åˆ 除这些分区,然åŽé‡æ–°è¿è¡ŒSELECT è¯å¥ï¼Œæ¥éªŒè¯è¿™äº›è¡Œè¢«ä¿å˜åœ¨æ¯ä¸ªè¡¨çš„p1分区ä¸ï¼š
mysql> ALTER TABLE tnlist DROP PARTITION p1;
Query OK, 0 rows affected (0.16 sec)
mysql> ALTER TABLE tnrange DROP PARTITION p1;
Query OK, 0 rows affected (0.16 sec)
mysql> SELECT * FROM tnlist;
Empty set (0.00 sec)
mysql> SELECT * FROM tnrange;
Empty set (0.00 sec)
在按HASHå’ŒKEY分区的情况下,任何产生NULL值的表达å¼éƒ½è§†åŒå¥½åƒå®ƒçš„返回值为0。我们å¯ä»¥é€šè¿‡å…ˆåˆ›å»ºä¸€ä¸ªæŒ‰HASH分区的表,然åŽæ’入一个包å«æœ‰é€‚当值的记录,å†æ£€æŸ¥å¯¹æ–‡ä»¶ç³»ç»Ÿçš„作用,æ¥éªŒè¯è¿™ä¸€ç‚¹ã€‚å‡å®šæœ‰ä½¿ç”¨ä¸‹é¢çš„è¯å¥åœ¨æµ‹è¯•æ•°æ®åº“ä¸åˆ›å»ºäº†ä¸€ä¸ªè¡¨tnhash:
CREATE TABLE tnhash (
id INT,
name VARCHAR(5)
)
PARTITION BY HASH(id)
PARTITIONS 2ï¼›
å‡å¦‚Linux 上的MySQL 的一个RPM安装,这个è¯å¥åœ¨ç›®å½•/var/lib/mysql/test下创建了两个.MYD文件,这两个文件å¯ä»¥åœ¨bash shellä¸æŸ¥çœ‹ï¼Œç»“果如下:
/var/lib/mysql/test> ls *.MYD -l
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash_p0.MYD
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash_p1.MYD
注æ„:æ¯ä¸ªæ–‡ä»¶çš„大å°ä¸º0å—节。现在在表tnhash ä¸æ’入一行id列值为NULL的行,然åŽéªŒè¯è¯¥è¡Œå·²ç»è¢«æ’入:
mysql> INSERT INTO tnhash VALUES (NULL, 'sam');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM tnhash;
+------+------+
| id | name |
+------+------+
| NULL | sam |
+------+------+
1 row in set (0.01 sec)
回想一下,对于任æ„çš„æ•´æ•°N,NULL MOD N 的值总是ç‰äºŽNULL。这个结果在确定æ£ç¡®çš„分区方é¢è¢«è®¤ä¸ºæ˜¯0。回到系统shell(ä»ç„¶å‡å®šbash用于这个目的) ,通过å†æ¬¡åˆ—出数æ®æ–‡ä»¶ï¼Œå¯ä»¥çœ‹å‡ºå€¼è¢«æˆåŠŸåœ°æ’入到第一个分区(默认å称为p0)ä¸ï¼š
var/lib/mysql/test> ls *.MYD -l
-rw-rw---- 1 mysql mysql 20 2005-11-04 18:44 tnhash_p0.MYD
-rw-rw---- 1 mysql mysql 0 2005-11-04 18:41 tnhash_p1.MYD
å¯ä»¥çœ‹å‡ºINSERTè¯å¥åªä¿®æ”¹äº†æ–‡ä»¶tnhash_p0.MYD,它在ç£ç›˜ä¸Šçš„å°ºå¯¸å¢žåŠ äº†ï¼Œè€Œæ²¡æœ‰å½±å“其他的文件。
å‡å®šæœ‰ä¸‹é¢çš„一个表:
CREATE TABLE tndate (
id INT,
dt DATE
)
PARTITION BY RANGE( YEAR(dt) ) (
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (2000),
PARTITION p2 VALUES LESS THAN MAXVALUE
)ï¼›
åƒå…¶ä»–çš„MySQLå‡½æ•°ä¸€æ ·ï¼ŒYEAR(NULL)返回NULL值。一个dt列值为NULL的行,其分区表达å¼çš„计算结果被视为0,该行被æ’入到分区p0ä¸ã€‚
MySQL 5.1 æ供了许多修改分区表的方å¼ã€‚æ·»åŠ ã€åˆ 除ã€é‡æ–°å®šä¹‰ã€åˆå¹¶æˆ–拆分已ç»å˜åœ¨çš„分区是å¯èƒ½çš„。所有这些æ“作都å¯ä»¥é€šè¿‡ä½¿ç”¨ALTER TABLE 命令的分区扩展æ¥å®žçŽ°(关于è¯æ³•çš„定义,请å‚è§13.1.2节,“ALTER TABLEè¯æ³•â€ )。也有获得分区表和分区信æ¯çš„æ–¹å¼ã€‚在本节,我们讨论下é¢è¿™äº›ä¸»é¢˜ï¼š
· 按RANGE或LIST分区的表的分区管ç†çš„有关信æ¯ï¼Œè¯·å‚è§18.3.1节,“RANGEå’ŒLIST分区的管ç†â€ã€‚
·
关于HASHå’ŒKEY分区管ç†çš„讨论,请å‚è§18.3.2节,“HASHå’ŒKEY分区的管ç†â€ã€‚
· MySQL 5.1ä¸æ供的ã€èŽ·å¾—关于分区表和分区信æ¯çš„机制的讨论,请å‚è§18.3.4节,“获å–关于分区的信æ¯â€ 。
· 关于执行分区维护æ“作的讨论,请å‚è§18.3.3节,“分区维护â€ã€‚
注释:在MySQL 5.1ä¸ï¼Œä¸€ä¸ªåˆ†åŒºè¡¨çš„所有分区都必须有å分区åŒæ ·çš„åå—,并且一旦表已ç»åˆ›å»ºï¼Œå†æ”¹å˜å分区是ä¸å¯èƒ½çš„。
è¦ç‚¹ï¼šå½“å‰ï¼Œä»Ž5.1系列起建立的MySQL æœåŠ¡å™¨å°±æŠŠâ€œALTER TABLE ... PARTITION BY ...â€ä½œä¸ºæœ‰æ•ˆçš„è¯æ³•ï¼Œä½†æ˜¯è¿™ä¸ªè¯å¥ç›®å‰è¿˜ä¸èµ·ä½œç”¨ã€‚我们期望MySQL 5.1达到生产状æ€æ—¶ï¼Œèƒ½å¤ŸæŒ‰ç…§ä¸‹é¢çš„æ述实现该è¯å¥çš„功能。
è¦æ”¹å˜ä¸€ä¸ªè¡¨çš„分区模å¼ï¼Œåªéœ€è¦ä½¿ç”¨å¸¦æœ‰ä¸€ä¸ªâ€œpartition_optionsâ€åå¥çš„ALTER TABLE 的命令。这个åå¥å’Œä¸Žåˆ›å»ºä¸€ä¸ªåˆ†åŒºè¡¨çš„CREATE TABLE命令一åŒä½¿ç”¨çš„åå¥æœ‰ç›¸åŒçš„è¯æ³•ï¼Œå¹¶ä¸”总是以关键å—PARTITION BY 开头。例如,å‡è®¾æœ‰ä¸€ä¸ªä½¿ç”¨ä¸‹é¢CREATE TABLEè¯å¥å»ºç«‹çš„按照RANGE分区的表:
CREATE TABLE trb3 (id INT, name VARCHAR(50), purchased DATE)
PARTITION BY RANGE(YEAR(purchased))
(
PARTITION p0 VALUES LESS THAN (1990),
PARTITION p1 VALUES LESS THAN (1995),
PARTITION p2 VALUES LESS THAN (2000),
PARTITION p3 VALUES LESS THAN (2005)
)ï¼›
现在,è¦æŠŠè¿™ä¸ªè¡¨æŒ‰ç…§ä½¿ç”¨id列值作为键的基础,通过KEY分区把它é‡æ–°åˆ†æˆä¸¤ä¸ªåˆ†åŒºï¼Œå¯ä»¥ä½¿ç”¨ä¸‹é¢çš„è¯å¥ï¼š
ALTER TABLE trb3 PARTITION BY KEY(id) PARTITIONS 2ï¼›
è¿™å’Œå…ˆåˆ é™¤è¿™ä¸ªè¡¨ã€ç„¶åŽä½¿ç”¨â€œCREATE TABLE trb3 PARTITION BY KEY(id) PARTITIONS 2ï¼›â€é‡æ–°åˆ›å»ºè¿™ä¸ªè¡¨å…·æœ‰åŒæ ·çš„效果。
å…³äºŽå¦‚ä½•æ·»åŠ å’Œåˆ é™¤åˆ†åŒºçš„å¤„ç†ï¼ŒRANGEå’ŒLIST分区éžå¸¸ç›¸ä¼¼ã€‚åŸºäºŽè¿™ä¸ªåŽŸå› ï¼Œæˆ‘ä»¬åœ¨æœ¬èŠ‚è®¨è®ºè¿™ä¸¤ç§åˆ†åŒºçš„管ç†ã€‚关于HASHå’ŒKEY分区管ç†çš„ä¿¡æ¯ï¼Œè¯·å‚è§18.3.2节,“HASHå’ŒKEY分区的管ç†â€ã€‚åˆ é™¤ä¸€ä¸ªRANGE或LISTåˆ†åŒºæ¯”å¢žåŠ ä¸€ä¸ªåˆ†åŒºè¦æ›´åŠ 简å•æ˜“懂,所以我们先讨论å‰è€…。
从一个按照RANGE或LIST分区的表ä¸åˆ 除一个分区,å¯ä»¥ä½¿ç”¨å¸¦ä¸€ä¸ªDROP PARTITIONåå¥çš„ALTER TABLE命令æ¥å®žçŽ°ã€‚这里有一个éžå¸¸åŸºæœ¬çš„例å,å‡è®¾å·²ç»ä½¿ç”¨ä¸‹é¢çš„CREATE TABLEå’ŒINSERTè¯å¥åˆ›å»ºäº†ä¸€ä¸ªæŒ‰ç…§RANGE分区的表,并且已ç»æ’入了10æ¡è®°å½•ï¼š
mysql> CREATE TABLE tr (id INT, name VARCHAR(50), purchased DATE)
-> PARTITION BY RANGE(YEAR(purchased))
-> (
-> PARTITION p0 VALUES LESS THAN (1990),
-> PARTITION p1 VALUES LESS THAN (1995),
-> PARTITION p2 VALUES LESS THAN (2000),
-> PARTITION p3 VALUES LESS THAN (2005)
-> );
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO tr VALUES
-> (1, 'desk organiser', '2003-10-15'),
-> (2, 'CD player', '1993-11-05'),
-> (3, 'TV set', '1996-03-10'),
-> (4, 'bookcase', '1982-01-10'),
-> (5, 'exercise bike', '2004-05-09'),
-> (6, 'sofa', '1987-06-05'),
-> (7, 'popcorn maker', '2001-11-22'),
-> (8, 'aquarium', '1992-08-04'),
-> (9, 'study desk', '1984-09-16'),
-> (10, 'lava lamp', '1998-12-25');
Query OK, 10 rows affected (0.01 sec)
å¯ä»¥é€šè¿‡ä½¿ç”¨ä¸‹é¢çš„命令查看那些记录已ç»æ’入到了分区p2ä¸ï¼š
mysql> SELECT * FROM tr
-> WHERE purchased BETWEEN '1995-01-01' AND '1999-12-31';
+------+-----------+------------+
| id | name | purchased |
+------+-----------+------------+
| 3 | TV set | 1996-03-10 |
| 10 | lava lamp | 1998-12-25 |
+------+-----------+------------+
2 rows in set (0.00 sec)
è¦åˆ 除åå—为p2的分区,执行下é¢çš„命令:
mysql> ALTER TABLE tr DROP PARTITION p2;
Query OK, 0 rows affected (0.03 sec)
è®°ä½ä¸‹é¢ä¸€ç‚¹éžå¸¸é‡è¦ï¼šå½“åˆ é™¤äº†ä¸€ä¸ªåˆ†åŒºï¼Œä¹ŸåŒæ—¶åˆ 除了该分区ä¸æ‰€æœ‰çš„æ•°æ®ã€‚å¯ä»¥é€šè¿‡é‡æ–°è¿è¡Œå‰é¢çš„SELECT查询æ¥éªŒè¯è¿™ä¸€ç‚¹ï¼š
mysql> SELECT * FROM tr WHERE purchased
-> BETWEEN '1995-01-01' AND '1999-12-31';
Empty set (0.00 sec)
å¦‚æžœå¸Œæœ›ä»Žæ‰€æœ‰åˆ†åŒºåˆ é™¤æ‰€æœ‰çš„æ•°æ®ï¼Œä½†æ˜¯åˆä¿ç•™è¡¨çš„定义和表的分区模å¼ï¼Œä½¿ç”¨TRUNCATE TABLE命令。(请å‚è§13.2.9节,“TRUNCATEè¯æ³•â€ï¼‰ã€‚
如果希望改å˜è¡¨çš„分区而åˆä¸ä¸¢å¤±æ•°æ®ï¼Œä½¿ç”¨â€œALTER TABLE ... REORGANIZE PARTITIONâ€è¯å¥ã€‚å‚è§ä¸‹é¢çš„内容,或者在13.1.2节,“ALTER TABLEè¯æ³•â€ ä¸å‚考关于REORGANIZE PARTITIONçš„ä¿¡æ¯ã€‚
如果现在执行一个SHOW CREATE TABLE命令,å¯ä»¥è§‚察到表的分区结构是如何被改å˜çš„:
mysql> SHOW CREATE TABLE tr\G
*************************** 1. row ***************************
Table: tr
Create Table: CREATE TABLE `tr` (
`id` int(11) default NULL,
`name` varchar(50) default NULL,
`purchased` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(purchased)) (
PARTITION p0 VALUES LESS THAN (1990) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1995) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = MyISAM
)
1 row in set (0.01 sec)
如果æ’å…¥è´ä¹°æ—¥æœŸåˆ—的值在'1995-01-01'å’Œ '2004-12-31'之间(å«ï¼‰çš„新行到已ç»ä¿®æ”¹åŽçš„表ä¸æ—¶ï¼Œè¿™äº›è¡Œå°†è¢«ä¿å˜åœ¨åˆ†åŒºp3ä¸ã€‚å¯ä»¥é€šè¿‡ä¸‹é¢çš„æ–¹å¼æ¥éªŒè¯è¿™ä¸€ç‚¹ï¼š
mysql> INSERT INTO tr VALUES (11, 'pencil holder', '1995-07-12');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM tr WHERE purchased
-> BETWEEN '1995-01-01' AND '2004-12-31';
+------+----------------+------------+
| id | name | purchased |
+------+----------------+------------+
| 11 | pencil holder | 1995-07-12 |
| 1 | desk organiser | 2003-10-15 |
| 5 | exercise bike | 2004-05-09 |
| 7 | popcorn maker | 2001-11-22 |
+------+----------------+------------+
4 rows in set (0.00 sec)
mysql> ALTER TABLE tr DROP PARTITION p3;
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT * FROM tr WHERE purchased
-> BETWEEN '1995-01-01' AND '2004-12-31';
Empty set (0.00 sec)
注æ„:由“ALTER TABLE ... DROP PARTITIONâ€è¯å¥å¼•èµ·çš„ã€ä»Žè¡¨ä¸åˆ 除的行数并没有被æœåŠ¡å™¨æŠ¥å‘Šå‡ºæ¥ï¼Œå°±å¥½åƒé€šè¿‡åŒç‰çš„DELETE查询æ“ä½œä¸€æ ·ã€‚
åˆ é™¤LISTåˆ†åŒºä½¿ç”¨å’Œåˆ é™¤RANGE分区完全相åŒçš„“ALTER TABLE ... DROP PARTITIONâ€è¯æ³•ã€‚但是,在对其åŽä½¿ç”¨è¿™ä¸ªè¡¨çš„å½±å“æ–¹é¢ï¼Œè¿˜æ˜¯æœ‰é‡å¤§çš„区别:在这个表ä¸ï¼Œå†ä¹Ÿä¸èƒ½æ’入这么一些行,这些行的列值包å«åœ¨å®šä¹‰å·²ç»åˆ é™¤äº†çš„åˆ†åŒºçš„å€¼åˆ—è¡¨ä¸ (有关示例,请å‚è§18.2.2节,“LIST分区†)。
è¦å¢žåŠ 一个新的RANGE或LIST分区到一个å‰é¢å·²ç»åˆ†åŒºäº†çš„表,使用“ALTER TABLE ... ADD PARTITIONâ€è¯å¥ã€‚对于使用RANGE分区的表,å¯ä»¥ç”¨è¿™ä¸ªè¯å¥æ·»åŠ 新的区间到已有分区的åºåˆ—çš„å‰é¢æˆ–åŽé¢ã€‚例如,å‡è®¾æœ‰ä¸€ä¸ªåŒ…å«ä½ 所在组织的全体æˆå‘˜æ•°æ®çš„分区表,该表的定义如下:
CREATE TABLE members (
id INT,
fname VARCHAR(25),
lname VARCHAR(25),
dob DATE
)
PARTITION BY RANGE(YEAR(dob)) (
PARTITION p0 VALUES LESS THAN (1970),
PARTITION p1 VALUES LESS THAN (1980),
PARTITION p2 VALUES LESS THAN (1990)
);
进一æ¥å‡è®¾æˆå‘˜çš„最å°å¹´çºªæ˜¯16å²ã€‚éšç€æ—¥åŽ†æŽ¥è¿‘2005å¹´å¹´åº•ï¼Œä½ ä¼šè®¤è¯†åˆ°ä¸ä¹…å°†è¦æŽ¥çº³1990年(以åŠä»¥åŽå¹´ä»½ï¼‰å‡ºç”Ÿçš„æˆå‘˜ã€‚å¯ä»¥æŒ‰ç…§ä¸‹é¢çš„æ–¹å¼ï¼Œä¿®æ”¹æˆå‘˜è¡¨æ¥å®¹çº³å‡ºç”Ÿåœ¨1990ï¼1999年之间的æˆå‘˜ï¼š
ALTER TABLE ADD PARTITION (PARTITION p3 VALUES LESS THAN (2000));
è¦ç‚¹ï¼šå¯¹äºŽé€šè¿‡RANGE分区的表,åªå¯ä»¥ä½¿ç”¨ADD PARTITIONæ·»åŠ æ–°çš„åˆ†åŒºåˆ°åˆ†åŒºåˆ—è¡¨çš„é«˜ç«¯ã€‚è®¾æ³•é€šè¿‡è¿™ç§æ–¹å¼åœ¨çŽ°æœ‰åˆ†åŒºçš„å‰é¢æˆ–ä¹‹é—´å¢žåŠ ä¸€ä¸ªæ–°çš„åˆ†åŒºï¼Œå°†ä¼šå¯¼è‡´ä¸‹é¢çš„一个错误:
mysql> ALTER TABLE members ADD PARTITION (PARTITION p3 VALUES LESS THAN (1960));
错误1463 (HY000): 对æ¯ä¸ªåˆ†åŒºï¼ŒVALUES LESS THAN å€¼å¿…é¡»ä¸¥æ ¼å¢žé•¿
采用一个类似的方å¼ï¼Œå¯ä»¥å¢žåŠ 新的分区到已ç»é€šè¿‡LIST分区的表。例如,å‡å®šæœ‰å¦‚下定义的一个表:
CREATE TABLE tt (
id INT,
data INT
)
PARTITION BY LIST(data) (
PARTITION p0 VALUES IN (5, 10, 15),
PARTITION p1 VALUES IN (6, 12, 18)
)ï¼›
å¯ä»¥é€šè¿‡ä¸‹é¢çš„æ–¹æ³•æ·»åŠ ä¸€ä¸ªæ–°çš„åˆ†åŒºï¼Œç”¨æ¥ä¿å˜æ‹¥æœ‰æ•°æ®åˆ—值7,14å’Œ21的行:
ALTER TABLE tt ADD PARTITION (PARTITION p2 VALUES IN (7, 14, 21))ï¼›
注æ„:ä¸èƒ½æ·»åŠ è¿™æ ·ä¸€ä¸ªæ–°çš„LIST分区,该分区包å«æœ‰å·²ç»åŒ…å«åœ¨çŽ°æœ‰åˆ†åŒºå€¼åˆ—表ä¸çš„ä»»æ„å€¼ã€‚å¦‚æžœè¯•å›¾è¿™æ ·åšï¼Œå°†ä¼šå¯¼è‡´é”™è¯¯ï¼š
mysql> ALTER TABLE tt ADD PARTITION (PARTITION np VALUES IN (4, 8, 12));
错误1465 (HY000): 在LIST分区ä¸ï¼ŒåŒä¸€ä¸ªå¸¸æ•°çš„多次定义
å› ä¸ºå¸¦æœ‰æ•°æ®åˆ—值12的任何行都已ç»åˆ†é…给了分区p1,所以ä¸èƒ½åœ¨è¡¨tt上å†åˆ›å»ºä¸€ä¸ªå…¶å€¼åˆ—表包括12的新分区。为了实现这一点,å¯ä»¥å…ˆåˆ 除分区p1ï¼Œæ·»åŠ åˆ†åŒºnp,然åŽä½¿ç”¨ä¿®æ£åŽçš„å®šä¹‰æ·»åŠ ä¸€ä¸ªæ–°çš„åˆ†åŒºp1。但是,æ£å¦‚我们å‰é¢è®¨è®ºè¿‡çš„,这将导致ä¿å˜åœ¨åˆ†åŒºp1ä¸çš„所有数æ®ä¸¢å¤±â€”—而这往往并ä¸æ˜¯ä½ 所真æ£æƒ³è¦åšçš„。å¦å¤–一ç§è§£å†³æ–¹æ³•å¯èƒ½æ˜¯ï¼Œå»ºç«‹ä¸€ä¸ªå¸¦æœ‰æ–°åˆ†åŒºçš„表的副本,然åŽä½¿ç”¨â€œCREATE TABLE ... SELECT ...â€æŠŠæ•°æ®æ‹·è´åˆ°è¯¥æ–°è¡¨ä¸ï¼Œç„¶åŽåˆ 除旧表,é‡æ–°å‘½å新表,但是,当需è¦å¤„ç†å¤§é‡çš„æ•°æ®æ—¶ï¼Œè¿™å¯èƒ½æ˜¯éžå¸¸è€—时的。在需è¦é«˜å¯ç”¨æ€§çš„场åˆï¼Œè¿™ä¹Ÿå¯èƒ½æ˜¯ä¸å¯è¡Œçš„。
幸è¿åœ°æ˜¯ï¼ŒMySQL 的分区实现æ供了在ä¸ä¸¢å¤±æ•°æ®çš„æ¡ä»¶ä¸‹é‡æ–°å®šä¹‰åˆ†åŒºçš„æ–¹å¼ã€‚让我们首先看两个涉åŠåˆ°RANGE分区的简å•ä¾‹å。回想一下现在定义如下的æˆå‘˜è¡¨ï¼š
mysql> SHOW CREATE TABLE members\G
*************************** 1. row ***************************
Table: members
Create Table: CREATE TABLE `members` (
`id` int(11) default NULL,
`fname` varchar(25) default NULL,
`lname` varchar(25) default NULL,
`dob` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(dob)) (
PARTITION p0 VALUES LESS THAN (1970) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1980) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (1990) ENGINE = MyISAM.
PARTITION p3 VALUES LESS THAN (2000) ENGINE = MyISAM
)
å‡å®šæƒ³è¦æŠŠè¡¨ç¤ºå‡ºç”Ÿåœ¨1960å¹´å‰æˆå‘˜çš„所有行移入到一个分开的分区ä¸ã€‚æ£å¦‚我们å‰é¢çœ‹åˆ°çš„,ä¸èƒ½é€šè¿‡ä½¿ç”¨â€œALTER TABLE ... ADD PARTITIONâ€æ¥å®žçŽ°è¿™ä¸€ç‚¹ã€‚但是,è¦å®žçŽ°è¿™ä¸€ç‚¹ï¼Œå¯ä»¥ä½¿ç”¨ALTER TABLE上的å¦å¤–一个与分区有关的扩展,具体实现如下:
ALTER TABLE members REORGANIZE PARTITION p0 INTO (
PARTITION s0 VALUES LESS THAN (1960),
PARTITION s1 VALUES LESS THAN (1970)
)ï¼›
实际上,这个命令把分区p0分æˆäº†ä¸¤ä¸ªæ–°çš„分区s0å’Œs1。åŒæ—¶ï¼Œå®ƒè¿˜æ ¹æ®åŒ…å«åœ¨ä¸¤ä¸ªâ€œPARTITION ... VALUES ...â€åå¥ä¸çš„规则,把ä¿å˜åœ¨åˆ†åŒºp0ä¸çš„æ•°æ®ç§»å…¥åˆ°ä¸¤ä¸ªæ–°çš„分区ä¸ï¼Œæ‰€ä»¥åˆ†åŒºs0ä¸åªåŒ…å«YEAR(dob)å°äºŽ1960的那些行,s1ä¸åŒ…å«é‚£äº›YEAR(dob)大于或ç‰äºŽ1960但是å°äºŽ1970的行。
一个REORGANIZE PARTITIONè¯å¥ä¹Ÿå¯ä»¥ç”¨æ¥åˆå¹¶ç›¸é‚»çš„分区。å¯ä»¥ä½¿ç”¨å¦‚下的è¯å¥æ¢å¤æˆå‘˜è¡¨åˆ°å®ƒä»¥å‰çš„分区:
ALTER TABLE members REORGANIZE PARTITION s0,s1 INTO (
PARTITION p0 VALUES LESS THAN (1970)
)ï¼›
使用“REORGANIZE PARTITIONâ€æ‹†åˆ†æˆ–åˆå¹¶åˆ†åŒºï¼Œæ²¡æœ‰æ•°æ®ä¸¢å¤±ã€‚在执行上é¢çš„è¯å¥ä¸ï¼ŒMySQL 把ä¿å˜åœ¨åˆ†åŒºs0å’Œs1ä¸çš„所有数æ®éƒ½ç§»åˆ°åˆ†åŒºp0ä¸ã€‚
“REORGANIZE PARTITIONâ€çš„基本è¯æ³•æ˜¯ï¼š
ALTER TABLE tbl_name REORGANIZE PARTITION partition_list INTO (partition_definitions)ï¼›
å…¶ä¸ï¼Œtbl_name 是分区表的å称,partition_list 是通过逗å·åˆ†å¼€çš„ã€ä¸€ä¸ªæˆ–多个将è¦è¢«æ”¹å˜çš„现有分区的列表。partition_definitions 是一个是通过逗å·åˆ†å¼€çš„ã€æ–°åˆ†åŒºå®šä¹‰çš„列表,它éµå¾ªä¸Žç”¨åœ¨â€œCREATE TABLEâ€ä¸çš„partition_definitions 相åŒçš„规则 (请å‚è§13.1.5节,“CREATE TABLEè¯æ³•â€)。应当注æ„到,在把多少个分区åˆå¹¶åˆ°ä¸€ä¸ªåˆ†åŒºæˆ–把一个分区拆分æˆå¤šå°‘个分区方é¢ï¼Œæ²¡æœ‰é™åˆ¶ã€‚例如,å¯ä»¥é‡æ–°ç»„织æˆå‘˜è¡¨çš„四个分区æˆä¸¤ä¸ªåˆ†åŒºï¼Œå…·ä½“实现如下:
ALTER TABLE members REORGANIZE PARTITION p0,p1,p2,p3 INTO (
PARTITION m0 VALUES LESS THAN (1980),
PARTITION m1 VALUES LESS THAN (2000)
)ï¼›
åŒæ ·ï¼Œå¯¹äºŽæŒ‰LIST分区的表,也å¯ä»¥ä½¿ç”¨REORGANIZE PARTITION。让我们回到那个问题,å³å¢žåŠ 一个新的分区到已ç»æŒ‰ç…§LIST分区的表ttä¸ï¼Œä½†æ˜¯å› 为该新分区有一个值已ç»å˜åœ¨äºŽçŽ°æœ‰åˆ†åŒºçš„值列表ä¸ï¼Œæ·»åŠ 新的分区失败。我们å¯ä»¥é€šè¿‡å…ˆæ·»åŠ åªåŒ…å«éžå†²çªå€¼çš„分区,然åŽé‡æ–°ç»„织该新分区和现有的那个分区,以便ä¿å˜åœ¨çŽ°æœ‰çš„那个分区ä¸çš„值现在移到了新的分区ä¸ï¼Œæ¥å¤„ç†è¿™ä¸ªé—®é¢˜ï¼š
ALTER TABLE tt ADD PARTITION (PARTITION np VALUES IN (4, 8));
ALTER TABLE tt REORGANIZE PARTITION p1,np INTO (
PARTITION p1 VALUES IN (6, 18),
PARTITION np VALUES in (4, 8, 12)
)ï¼›
当使用“ALTER TABLE ... REORGANIZE PARTITIONâ€æ¥å¯¹å·²ç»æŒ‰ç…§RANGEå’ŒLIST分区表进行é‡æ–°åˆ†åŒºæ—¶ï¼Œä¸‹é¢æ˜¯ä¸€äº›è¦è®°ä½çš„关键点:
· 用æ¥ç¡®å®šæ–°åˆ†åŒºæ¨¡å¼çš„PARTITIONåå¥ä½¿ç”¨ä¸Žç”¨åœ¨CREATE TABLEä¸ç¡®å®šåˆ†åŒºæ¨¡å¼çš„PARTITIONåå¥ç›¸åŒçš„规则。
最é‡è¦çš„是,应该记ä½ï¼šæ–°åˆ†åŒºæ¨¡å¼ä¸èƒ½æœ‰ä»»ä½•é‡å 的区间(适用于按照RANGE分区的表)或值集åˆï¼ˆé€‚用于é‡æ–°ç»„织按照LIST分区的表)。
· partition_definitions 列表ä¸åˆ†åŒºçš„åˆé›†åº”该与在partition_list ä¸å‘½å分区的åˆé›†å 有相åŒçš„区间或值集åˆã€‚
例如,在本节ä¸ç”¨ä½œä¾‹åçš„æˆå‘˜è¡¨ä¸ï¼Œåˆ†åŒºp1å’Œp2总共覆盖了1980到1999çš„è¿™äº›å¹´ã€‚å› æ¤ï¼Œå¯¹è¿™ä¸¤ä¸ªåˆ†åŒºçš„é‡æ–°ç»„织都应该覆盖相åŒèŒƒå›´çš„年份。
· 对于按照RANGE分区的表,åªèƒ½é‡æ–°ç»„织相邻的分区;ä¸èƒ½è·³è¿‡RANGE分区。
例如,ä¸èƒ½ä½¿ç”¨ä»¥â€œALTER TABLE members REORGANIZE PARTITION p0,p2 INTO ...â€å¼€å¤´çš„è¯å¥ï¼Œæ¥é‡æ–°ç»„织本节ä¸ç”¨ä½œä¾‹åçš„æˆå‘˜è¡¨ã€‚å› ä¸ºï¼Œp0覆盖了1970年以å‰çš„年份,而p2覆盖了从1990到1999(包括1990å’Œ1999ï¼‰ä¹‹é—´çš„å¹´ä»½ï¼Œå› è€Œè¿™ä¸¤ä¸ªåˆ†åŒºä¸æ˜¯ç›¸é‚»çš„分区。
· ä¸èƒ½ä½¿ç”¨REORGANIZE PARTITIONæ¥æ”¹å˜è¡¨çš„分区类型;也就是说,例如,ä¸èƒ½æŠŠRANGE分区å˜ä¸ºHASH分区,å之亦然。也ä¸èƒ½ä½¿ç”¨è¯¥å‘½ä»¤æ¥æ”¹å˜åˆ†åŒºè¡¨è¾¾å¼æˆ–列。如果想在ä¸åˆ 除和é‡å»ºè¡¨çš„æ¡ä»¶ä¸‹å®žçŽ°è¿™ä¸¤ä¸ªä»»åŠ¡ï¼Œå¯ä»¥ä½¿ç”¨â€œALTER TABLE ... PARTITION BY ....â€ï¼Œä¾‹å¦‚:
· ALTER TABLE members
· PARTITION BY HASH(YEAR(dob))
· PARTITIONS 8;
注释:在MySQL 5.1å‘布å‰çš„版本ä¸ï¼Œâ€œALTER TABLE ... PARTITION BY ...â€è¿˜æ²¡æœ‰å®žçŽ°ã€‚作为替代,è¦ä¹ˆä½¿ç”¨å…ˆåˆ 除表,然åŽä½¿ç”¨æƒ³è¦çš„分区é‡å»ºè¡¨ï¼Œæˆ–者——如果需è¦ä¿ç•™å·²ç»å˜å‚¨åœ¨è¡¨ä¸çš„æ•°æ®â€”—å¯ä»¥ä½¿ç”¨â€œCREATE TABLE ... SELECT ...â€æ¥åˆ›å»ºæ–°çš„表,然åŽä»Žæ—§è¡¨ä¸æŠŠæ•°æ®æ‹·è´åˆ°æ–°è¡¨ä¸ï¼Œå†åˆ 除旧表,如有必è¦ï¼Œæœ€åŽé‡æ–°å‘½å新表。
在改å˜åˆ†åŒºè®¾ç½®æ–¹é¢ï¼ŒæŒ‰ç…§HASH分区或KEY分区的表彼æ¤éžå¸¸ç›¸ä¼¼ï¼Œä½†æ˜¯å®ƒä»¬åˆä¸ŽæŒ‰ç…§RANGE或LIST分区的表在很多方é¢æœ‰å·®åˆ«ã€‚所以,本节åªè®¨è®ºæŒ‰ç…§HASH或KEYåˆ†åŒºè¡¨çš„ä¿®æ”¹ã€‚å…³äºŽæ·»åŠ å’Œåˆ é™¤æŒ‰ç…§RANGE或LIST进行分区的表的分区的讨论,å‚è§18.3.1节,“RANGEå’ŒLIST分区的管ç†â€ã€‚
ä¸èƒ½ä½¿ç”¨ä¸Žä»ŽæŒ‰ç…§RANGE或LIST分区的表ä¸åˆ 除分区相åŒçš„æ–¹å¼ï¼Œæ¥ä»ŽHASH或KEY分区的表ä¸åˆ 除分区。但是,å¯ä»¥ä½¿ç”¨â€œALTER TABLE ... COALESCE PARTITIONâ€å‘½ä»¤æ¥åˆå¹¶HASH或KEY分区。例如,å‡å®šæœ‰ä¸€ä¸ªåŒ…å«é¡¾å®¢ä¿¡æ¯æ•°æ®çš„表,它被分æˆäº†12个分区。该顾客表的定义如下:
CREATE TABLE clients (
id INT,
fname VARCHAR(30),
lname VARCHAR(30),
signed DATE
)
PARTITION BY HASH( MONTH(signed) )
PARTITIONS 12ï¼›
è¦å‡å°‘分区的数é‡ä»Ž12到6,执行下é¢çš„ALTER TABLE命令:
mysql> ALTER TABLE clients COALESCE PARTITION 6ï¼›
Query OK, 0 rows affected (0.02 sec)
对于按照HASH,KEY,LINEAR HASH,或LINEAR KEY分区的表, COALESCE能起到åŒæ ·çš„作用。下é¢æ˜¯ä¸€ä¸ªç±»ä¼¼äºŽå‰é¢ä¾‹åçš„å¦å¤–一个例å,它们的区别åªæ˜¯åœ¨äºŽè¡¨æ˜¯æŒ‰ç…§LINEAR KEY 进行分区:
mysql> CREATE TABLE clients_lk (
-> id INT,
-> fname VARCHAR(30),
-> lname VARCHAR(30),
-> signed DATE
-> )
-> PARTITION BY LINEAR KEY(signed)
-> PARTITIONS 12ï¼›
Query OK, 0 rows affected (0.03 sec)
mysql> ALTER TABLE clients_lk COALESCE PARTITION 6ï¼›
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0
COALESCEä¸èƒ½ç”¨æ¥å¢žåŠ 分区的数é‡ï¼Œå¦‚æžœä½ å°è¯•è¿™ä¹ˆåšï¼Œç»“果会出现类似于下é¢çš„错误:
mysql> ALTER TABLE clients COALESCE PARTITION 18;
错误1478 (HY000): ä¸èƒ½ç§»åŠ¨æ‰€æœ‰åˆ†åŒºï¼Œä½¿ç”¨DROP TABLE代替
è¦å¢žåŠ 顾客表的分区数é‡ä»Ž12到18,使用“ALTER TABLE ... ADD PARTITIONâ€,具体如下:
ALTER TABLE clients ADD PARTITION PARTITIONS 18ï¼›
注释:“ALTER TABLE ... REORGANIZE PARTITIONâ€ä¸èƒ½ç”¨äºŽæŒ‰ç…§HASH或HASH分区的表。
注释:实际上,本节讨论的命令还没有在MySQL 5.1ä¸å®žçŽ°ï¼Œ 在这里æ出的目的,是为了在5.1版投产å‰çš„å¼€å‘周期期间,引出æ¥è‡ªç”¨æˆ·æµ‹è¯•è¯¥è½¯ä»¶çš„å馈æ„è§ã€‚(æ¢å¥è¯è¯´ï¼Œå°±æ˜¯â€œè¯·ä¸è¦åé¦ˆè¿™æ ·çš„ç¼ºé™·ï¼Œè¯´è¿™äº›å‘½ä»¤ä¸èµ·ä½œç”¨â€ï¼‰ã€‚éšç€MySQL5.1版开å‘的继ç»ï¼Œè¿™äº›ä¿¡æ¯å¾ˆæœ‰å¯èƒ½å‘生å˜åŒ–。éšç€åˆ†åŒºåŠŸèƒ½çš„实现和æ高,我们将更新本节的内容。
MySQL 5.1ä¸å¯ä»¥æ‰§è¡Œè®¸å¤šåˆ†åŒºç»´æŠ¤çš„任务。对于分区表,MySQLä¸æ”¯æŒå‘½ä»¤CHECK TABLE,OPTIMIZE TABLE,ANALYZE TABLE,或REPAIR TABLE。作为替代,å¯ä»¥ä½¿ç”¨ALTER TABLE 的许多扩展æ¥åœ¨ä¸€ä¸ªæˆ–多个分区上直接地执行这些æ“作,如下é¢åˆ—å‡ºçš„é‚£æ ·ï¼š
· é‡å»ºåˆ†åŒº: è¿™å’Œå…ˆåˆ é™¤ä¿å˜åœ¨åˆ†åŒºä¸çš„所有记录,然åŽé‡æ–°æ’入它们,具有åŒæ ·çš„效果。它å¯ç”¨äºŽæ•´ç†åˆ†åŒºç¢Žç‰‡ã€‚
示例:
ALTER TABLE t1 REBUILD PARTITION (p0, p1)ï¼›
· 优化分区:如果从分区ä¸åˆ 除了大é‡çš„行,或者对一个带有å¯å˜é•¿åº¦çš„行(也就是说,有VARCHAR,BLOB,或TEXT类型的列)作了许多修改,å¯ä»¥ä½¿ç”¨â€œALTER TABLE ... OPTIMIZE PARTITIONâ€æ¥æ”¶å›žæ²¡æœ‰ä½¿ç”¨çš„空间,并整ç†åˆ†åŒºæ•°æ®æ–‡ä»¶çš„碎片。
示例:
ALTER TABLE t1 OPTIMIZE PARTITION (p0, p1)ï¼›
在一个给定的分区表上使用“OPTIMIZE PARTITIONâ€ç‰åŒäºŽåœ¨é‚£ä¸ªåˆ†åŒºä¸Šè¿è¡ŒCHECK PARTITION,ANALYZE PARTITION,和REPAIR PARTITION。
· 分æžåˆ†åŒºï¼šè¯»å–并ä¿å˜åˆ†åŒºçš„键分布。
示例:
ALTER TABLE t1 ANALYZE PARTITION (p3)ï¼›
· 修补分区: ä¿®è¡¥è¢«ç ´å的分区。
示例:
ALTER TABLE t1 REPAIR PARTITION (p0,p1);
· 检查分区: å¯ä»¥ä½¿ç”¨å‡ 乎与对éžåˆ†åŒºè¡¨ä½¿ç”¨CHECK TABLE 相åŒçš„æ–¹å¼æ£€æŸ¥åˆ†åŒºã€‚
示例:
ALTER TABLE trb3 CHECK PARTITION (p1)ï¼›
这个命令å¯ä»¥å‘Šè¯‰ä½ 表t1的分区p1ä¸çš„æ•°æ®æˆ–索引是å¦å·²ç»è¢«ç ´å。如果å‘生了这ç§æƒ…况,使用“ALTER TABLE ... REPAIR PARTITIONâ€æ¥ä¿®è¡¥è¯¥åˆ†åŒºã€‚
还å¯ä»¥ä½¿ç”¨mysqlcheck或myisamchk 应用程åºï¼Œåœ¨å¯¹è¡¨è¿›è¡Œåˆ†åŒºæ—¶æ‰€äº§ç”Ÿçš„ã€å•ç‹¬çš„MYI文件上进行æ“作,æ¥å®Œæˆè¿™äº›ä»»åŠ¡ã€‚请å‚è§8.7节,“mysqlcheck:表维护和维修程åºâ€ã€‚(在pre-alphaç¼–ç ä¸ï¼Œè¿™ä¸ªåŠŸèƒ½å·²ç»å¯ä»¥ä½¿ç”¨ï¼‰ã€‚
本节讨论获å–关于现有分区的信æ¯ã€‚这个功能ä»ç„¶å¤„于计划阶段,所以现阶段在这里æ述的,实际上是我们想è¦åœ¨MySQL 5.1ä¸å®žçŽ°çš„一个概观。
å¦‚åœ¨æœ¬ç« ä¸åˆ«å¤„è®¨è®ºçš„ä¸€æ ·ï¼Œåœ¨SHOW CREATE TABLE的输出ä¸åŒ…å«äº†ç”¨äºŽåˆ›å»ºåˆ†åŒºè¡¨çš„PARTITION BYåå¥ã€‚例如:
mysql> SHOW CREATE TABLE trb3\G
*************************** 1. row ***************************
Table: trb3
Create Table: CREATE TABLE `trb3` (
`id` int(11) default NULL,
`name` varchar(50) default NULL,
`purchased` date default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(purchased)) (
PARTITION p0 VALUES LESS THAN (1990) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1995) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (2000) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = MyISAM
)
1 row in set (0.00 sec)
注释:当å‰ï¼Œå¯¹äºŽæŒ‰HASH或KEY分区的表,PARTITIONSåå¥å¹¶ä¸æ˜¾ç¤ºã€‚ (Bug #14327)
SHOW TABLE STATUS用于分区表,它的输出与用于éžåˆ†åŒºè¡¨çš„输出相åŒï¼Œé™¤äº†å¼•æ“Žï¼ˆEngine)列总是包å«'PARTITION'值。(关于这个命令的更多信æ¯ï¼Œå‚è§13.5.4.18节,“SHOW TABLE STATUSè¯æ³•â€ï¼‰ã€‚è¦èŽ·å–å•ä¸ªåˆ†åŒºçš„状æ€ä¿¡æ¯ï¼Œæˆ‘们计划实现一个SHOW PARTITION STATUS命令(请å‚è§ä¸‹é¢)。
计划用于分区表的ã€ä¸¤ä¸ªé™„åŠ çš„SHOW命令是:
· SHOW PARTITIONS
这个命令预期其功能类似于SHOW TABLESå’ŒSHOW DATABASES,除了该命令将列出的是分区而ä¸æ˜¯è¡¨æˆ–æ•°æ®åº“。这个命令的输出å¯èƒ½åŒ…å«å•ä¸ªç§°ä¸ºPartitions_in_tbl_name 的列,其ä¸tbl_name 是分区表的åå—。对于SHOW TABLES命令而言,如果一旦选择了一个数æ®åº“,éšåŽè¯¥æ•°æ®åº“将作为SHOW TABLES命令的默认数æ®åº“。但是由于SHOW PARTITIONS命令ä¸å¯èƒ½ç”¨è¿™æ ·çš„æ–¹å¼æ¥â€œé€‰æ‹©â€ä¸€ä¸ªè¡¨ï¼Œå®ƒå¾ˆå¯èƒ½éœ€è¦ä½¿ç”¨FROMåå¥ï¼Œä»¥ä¾¿MySQL知é“è¦æ˜¾ç¤ºçš„是哪个表的分区信æ¯ã€‚
· SHOW PARTITION STATUS
这个命令将æ供关于一个或多个分区的详细状æ€ä¿¡æ¯ã€‚它的输出很å¯èƒ½åŒ…å«æœ‰ä¸ŽSHOW TABLE STATUS 的输出相åŒæˆ–类似的列,æ¤å¤–,还包括显示用于分区的数æ®å’Œç´¢å¼•è·¯å¾„çš„é™„åŠ åˆ—ã€‚è¿™ä¸ªå‘½ä»¤å¯èƒ½æ”¯æŒLIKEå’ŒFROMåå¥ï¼Œè¿™æ ·ä½¿å¾—通过åå—获得关于一个给定分区的信æ¯ï¼Œæˆ–者获得关于属于指定表或数æ®åº“的分区的信æ¯ï¼Œæˆä¸ºå¯èƒ½ã€‚
扩展INFORMATION_SCHEMA æ•°æ®åº“的计划也在进行ä¸ï¼Œä»¥ä¾¿æ供关于分区表和分区的信æ¯ã€‚这个计划当å‰è¿˜å¤„一个在éžå¸¸æ—©çš„阶段;éšç€è¡¥å……çš„ä¿¡æ¯å˜å¾—å¯ç”¨ï¼Œä»¥åŠä»»ä½•æ–°çš„ã€ä¸Žåˆ†åŒºæœ‰å…³çš„INFORMATION_SCHEMA扩展得以实现,我们将更新手册相关部分的内容。
这是MySQLå‚考手册的翻译版本,关于MySQLå‚考手册,请访问dev.mysql.com。原始å‚考手册为英文版,与英文版å‚考手册相比,本翻译版å¯èƒ½ä¸æ˜¯æœ€æ–°çš„。