(轉)Mysql分區表侷限性總結

Mysql5.1已經發行很久了,本文根據官方文檔的翻譯和自己的一些測試,對Mysql分區表的侷限性做了一些總結,因爲個人能力以及測試環境的原因,有可能有錯誤的地方,還請大家看到能及時指出,當然有興趣的朋友可以去官方網站查閱。

本文測試的版本

mysql> select version();
+------------+
| version() |
+------------+
| 5.1.33-log |
+------------+
1 row in set (0.00 sec)

一、關於Partitioning Keys, Primary Keys, and Unique Keys的限制

在5.1中分區表對唯一約束有明確的規定,每一個唯一約束必須包含在分區表的分區鍵(也包括主鍵約束)。
這句話也許不好理解,我們做幾個實驗:

CREATE TABLE t1
( id INT NOT NULL,
uid INT NOT NULL,
PRIMARY KEY (id)
)
PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN(5) ENGINE = INNODB,
PARTITION p1 VALUES LESS THAN(10) ENGINE = INNODB
);

CREATE TABLE t1
( id INT NOT NULL,
uid INT NOT NULL,
PRIMARY KEY (id)
)
PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp',
PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp'
);

mysql> CREATE TABLE t1
-> ( id INT NOT NULL,
-> uid INT NOT NULL,
-> PRIMARY KEY (id),
-> UNIQUE KEY (uid)
-> )
-> PARTITION BY RANGE (id)
-> (PARTITION p0 VALUES LESS THAN(5),
-> PARTITION p1 VALUES LESS THAN(10)
-> );
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function

二、關於存儲引擎的限制
2.1 MERGE引擎不支持分區,分區表也不支持merge。
2.2 FEDERATED引擎不支持分區。這限制可能會在以後的版本去掉。
2.3 CSV引擎不支持分區
2.4 BLACKHOLE引擎不支持分區
2.5 在NDBCLUSTER引擎上使用分區表,分區類型只能是KEY(or LINEAR KEY) 分區。
2.6 當升級MYSQL的時候,如果你有使用了KEY分區的表(不管是什麼引擎,NDBCLUSTER除外),那麼你需要把這個表dumped在reloaded。
2.7 分區表的所有分區或者子分區的存儲引擎必須相同,這個限制也許會在以後的版本取消。
不指定任何引擎(使用默認引擎)。
所有分區或者子分區指定相同引擎。

三、關於函數的限制
在mysql5.1中建立分區表的語句中,只能包含下列函數:
ABS()
CEILING() and FLOOR() (在使用這2個函數的建立分區表的前提是使用函數的分區鍵是INT類型),例如

mysql> CREATE TABLE t (c FLOAT) PARTITION BY LIST( FLOOR(c) )(
-> PARTITION p0 VALUES IN (1,3,5),
-> PARTITION p1 VALUES IN (2,4,6)
-> );;
ERROR 1491 (HY000): The PARTITION function returns the wrong type

mysql> CREATE TABLE t (c int) PARTITION BY LIST( FLOOR(c) )(
-> PARTITION p0 VALUES IN (1,3,5),
-> PARTITION p1 VALUES IN (2,4,6)
-> );
Query OK, 0 rows affected (0.01 sec)

DAY()
DAYOFMONTH()
DAYOFWEEK()
DAYOFYEAR()
DATEDIFF()
EXTRACT()
HOUR()
MICROSECOND()
MINUTE()
MOD()
MONTH()
QUARTER()
SECOND()
TIME_TO_SEC()
TO_DAYS()
WEEKDAY()
YEAR()
YEARWEEK()

四、其他限制

4.1 對象限制
下面這些對象在不能出現在分區表達式
Stored functions, stored procedures, UDFs, or plugins.
Declared variables or user variables.

4.2 運算限制
支持加減乘等運算出現在分區表達式,但是運算後的結果必須是一個INT或者NULL。 |, &, ^, <<, >>, , ~ 等不允許出現在分區表達式。

4.3 sql_mode限制
官方強烈建議你在創建分區表後,永遠別改變mysql的sql_mode。因爲在不同的模式下,某些函數或者運算返回的結果可能會不一樣。

4.4 Performance considerations.(省略)

4.5 最多支持1024個分區,包括子分區。
當你建立分區表包含很多分區但沒有超過1024限制的時候,如果報錯 Got error 24 from storage engine,那意味着你需要增大open_files_limit參數。

4.6 不支持外鍵。MYSQL中,INNODB引擎才支持外鍵。

4.7 不支持FULLTEXT indexes(全文索引),包括MYISAM引擎。

mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> )
-> PARTITION BY HASH(id)
-> PARTITIONS 4;
ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes

4.8 不支持spatial column types。
4.9 臨時表不能被分區。

mysql> CREATE Temporary TABLE t1
-> ( id INT NOT NULL,
-> uid INT NOT NULL,
-> PRIMARY KEY (id)
-> )
-> PARTITION BY RANGE (id)
-> (PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM,
-> PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM
-> );
ERROR 1562 (HY000): Cannot create temporary table with partitions

4.10 log table不支持分區。

mysql> alter table mysql.slow_log PARTITION BY KEY(start_time) PARTITIONS 2;
ERROR 1221 (HY000): Incorrect usage of PARTITION and log table

5.11 分區鍵必須是INT類型,或者通過表達式返回INT類型,可以爲NULL。唯一的例外是當分區類型爲KEY分區的時候,可以使用其他類型的列作爲分區鍵( BLOB or TEXT 列除外)。

mysql> CREATE TABLE tkc (c1 CHAR)
-> PARTITION BY KEY(c1)
-> PARTITIONS 4;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE tkc2 (c1 CHAR)
-> PARTITION BY HASH(c1)
-> PARTITIONS 4;
ERROR 1491 (HY000): The PARTITION function returns the wrong type

mysql> CREATE TABLE tkc3 (c1 INT)
-> PARTITION BY HASH(c1)
-> PARTITIONS 4;
Query OK, 0 rows affected (0.00 sec)

5.12 分區鍵不能是一個子查詢。 A partitioning key may not be a subquery, even if that subquery resolves to an integer value or NULL

5.13 只有RANG和LIST分區能進行子分區。HASH和KEY分區不能進行子分區。

5.14 分區表不支持Key caches。

mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CACHE INDEX login,user_msg,user_msg_p IN keycache1;
+-----------------+--------------------+----------+---------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+-----------------+--------------------+----------+---------------------------------------------------------------------+
| test.login | assign_to_keycache | status | OK |
| test.user_msg | assign_to_keycache | status | OK |
| test.user_msg_p | assign_to_keycache | note | The storage engine for the table doesn't support assign_to_keycache |
+-----------------+--------------------+----------+---------------------------------------------------------------------+
3 rows in set (0.00 sec)

5.15 分區表不支持INSERT DELAYED.

mysql> insert DELAYED into user_msg_p values(18156629,0,0,0,0,0,0,0,0,0);
ERROR 1616 (HY000): DELAYED option not supported for table 'user_msg_p'

5.16 DATA DIRECTORY 和 INDEX DIRECTORY 參數在分區表將被忽略。
這個限制應該不存在了:
[color=red]注:在創建InnoDB引擎的情況下,還是會忽略,即使已經打開innodb_file_per_table,還是需要手動做符號連接。
例如:
drop table if exists ts ;
CREATE TABLE ts (id INT, purchased DATE)
ENGINE=innodb
PARTITION BY RANGE(YEAR(purchased))
SUBPARTITION BY HASH(id)
(
PARTITION p0 VALUES LESS THAN (1990)
(
SUBPARTITION s0
DATA DIRECTORY='/usr/local/mysql/data0'
INDEX DIRECTORY='/usr/local/mysql/index0',
SUBPARTITION s1
DATA DIRECTORY='/usr/local/mysql/data1'
INDEX DIRECTORY='/usr/local/mysql/index1'
),
PARTITION p1 VALUES LESS THAN (MAXVALUE)
(
SUBPARTITION s2
DATA DIRECTORY='/usr/local/mysql/data1'
INDEX DIRECTORY='/usr/local/mysql/index1',
SUBPARTITION s3
DATA DIRECTORY='/usr/local/mysql/data2'
INDEX DIRECTORY='/usr/local/mysql/index2'
)
);
手動做完符號連接後如下:
-rw-rw---- 1 mysql mysql 8596 02-28 22:07 ts.frm
-rw-rw---- 1 mysql mysql 56 02-28 22:07 ts.par
lrwxrwxrwx 1 mysql mysql 40 02-28 22:30 ts#P#p0#SP#s0.ibd -> /usr/local/mysql/data0/ts#P#p0#SP#s0.ibd
lrwxrwxrwx 1 mysql mysql 40 02-28 22:31 ts#P#p0#SP#s1.ibd -> /usr/local/mysql/data0/ts#P#p0#SP#s1.ibd
lrwxrwxrwx 1 mysql mysql 40 02-28 22:31 ts#P#p1#SP#s2.ibd -> /usr/local/mysql/data0/ts#P#p1#SP#s2.ibd
lrwxrwxrwx 1 mysql mysql 40 02-28 22:31 ts#P#p1#SP#s3.ibd -> /usr/local/mysql/data0/ts#P#p1#SP#s3.ibd
[/color]
mysql> CREATE TABLE t1
-> ( id INT NOT NULL,
-> uid INT NOT NULL,
-> PRIMARY KEY (id)
-> )
-> PARTITION BY RANGE (id)
-> (PARTITION p0 VALUES LESS THAN(5) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp',
-> PARTITION p1 VALUES LESS THAN(10) ENGINE = MyISAM DATA DIRECTORY='/tmp' INDEX DIRECTORY='/tmp'
-> );
Query OK, 0 rows affected (0.01 sec)

5.17 分區表不支持mysqlcheck和myisamchk
在5.1.33版本中已經支持mysqlcheck和myisamchk

./mysqlcheck -u -p -r test user_msg_p;
test.user_msg_p OK

./myisamchk -i /u01/data/test/user_msg_p#P#p0.MYI
Checking MyISAM file: /u01/data/test/user_msg_p#P#p0.MYI
Data records: 4423615 Deleted blocks: 0
- check file-size
- check record delete-chain
- check key delete-chain
- check index reference
- check data record references index: 1
Key: 1: Keyblocks used: 98% Packed: 0% Max levels: 4
Total: Keyblocks used: 98% Packed: 0%

User time 0.97, System time 0.02
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 324, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 1, Involuntary context switches 5

5.18 分區表的分區鍵創建索引,那麼這個索引也將被分區。分區鍵沒有全局索引一說。
5.19 在分區表使用ALTER TABLE … ORDER BY,只能在每個分區內進行order by。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章