Maison  >  Article  >  base de données  >  Modifiez le champ de partition en ligne dans la partition de la table de partition MySQL, puis apprenez-en plus sur la partition (2) -> les sous-partitions et le traitement de la saisie des valeurs nulles.

Modifiez le champ de partition en ligne dans la partition de la table de partition MySQL, puis apprenez-en plus sur la partition (2) -> les sous-partitions et le traitement de la saisie des valeurs nulles.

黄舟
黄舟original
2017-02-17 11:58:182115parcourir

-- MySQL分区, 以及对录入Null值的处理情况. 看完官方文档做的笔记.

-- Partitionnement par clé
Le partitionnement par clé est similaire au partitionnement par hachage, sauf que le partitionnement par hachage utilise un partitionnement défini par l'utilisateur. expression, la fonction de hachage pour le partitionnement des clés est fournie par le serveur MySQL. Cette fonction de hachage interne est basée sur le même algorithme que PASSWORD().
KEY est utilisé plutôt que HASH.
KEY prend uniquement une liste d'un ou plusieurs noms de colonnes. La ou les colonnes utilisées comme clé de partitionnement doivent comprendre une partie ou la totalité de la clé primaire de la table, si la table en a une.
KEY prend une liste de zéro ou plusieurs noms de colonnes. Lorsqu'aucun nom de colonne n'est spécifié comme clé de partitionnement, la clé primaire de la table est utilisée, le cas échéant. Par exemple, l'instruction CREATE TABLE suivante est valide dans MySQL 5.5 : 

 mysql> CREATE TABLE k1 (
  ->     id INT NOT NULL PRIMARY KEY,
  ->     name VARCHAR(20)
  -> )
  -> PARTITION BY KEY()
  -> PARTITIONS 2;
 Query OK, 0 rows affected (0.06 sec)

 If there is no primary key but there is a unique key, then the unique key is used for the partitioning key:
 mysql> CREATE TABLE k2 (
  ->     id INT NOT NULL,
  ->     name VARCHAR(20),
  ->     UNIQUE KEY (id)
  -> )
  -> PARTITION BY KEY()
  -> PARTITIONS 2;
 Query OK, 0 rows affected (0.02 sec)



Cependant, si la colonne de clé unique n'était pas définie comme NOT NULL, alors l'instruction précédente échouerait.

Dans ces deux cas, la clé de partitionnement est la colonne id, même si elle n'est pas affichée dans la sortie de SHOW CREATE TABLE ou dans la colonne PARTITION_EXPRESSION de INFORMATION_SCHEMA Table .PARTITIONS.
Comme ci-dessous :

mysql>  SELECT t.TABLE_NAME, t.PARTITION_NAME,t.TABLE_ROWS  FROM INFORMATION_SCHEMA.PARTITIONS t WHERE table_name='k2';
+------------+----------------+------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+------------+----------------+------------+
| k2         | p0             |          3 |
| k2         | p1             |          4 |
+------------+----------------+------------+
2 rows in set (0.01 sec)

Contrairement au cas des autres types de partitionnement, les colonnes utilisées pour le partitionnement par KEY ne sont pas limitées aux valeurs entières ou NULL.
Par exemple , l'instruction CREATE TABLE suivante est valide :
没有clé primaire,没有在定义时候指定分区字段,会抱错:

mysql> CREATE TABLE tm3 (
    ->     s1 CHAR(32) 
    -> )
    -> PARTITION BY KEY()
    -> PARTITIONS 10;
ERROR 1488 (HY000): Field in list of fields for partition function not found in table
在定义中加入分区字段,add the column in define , it is ok
mysql> CREATE TABLE tm3 (
    ->     s1 CHAR(32) 
    -> )
    -> PARTITION BY KEY(s1)
    -> PARTITIONS 10;
Query OK, 0 rows affected (0.07 sec)

mysql>

 

子分区 Sous-partitionnement
Le sous-partitionnement, également appelé partitionnement composite, est la pision supplémentaire de chaque partition dans une table partitionnée.
Par exemple, considérons l'instruction CREATE TABLE suivante :

mysql> 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
    ->         )
    ->     );

Query OK, 0 rows affected (0.04 sec)


CREATE TABLE ts3 (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
        )
    );

 

(1) Chaque partition doit avoir le même nombre de sous-partitions. sinon, échouez

 mysql> CREATE TABLE ts3 (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
  ->         )
  ->     );
 ERROR 1064 (42000): Wrong number of subpartitions defined, mismatch with previous setting near '
   PARTITION p2 VALUES LESS THAN MAXVALUE (
    SUBPARTITION s2,
  ' at line 8
 mysql>



(2) Chaque clause SUBPARTITION doit inclure (au minimum) un nom pour la sous-partition.

Sinon, vous pouvez définir n'importe quelle option souhaitée pour la sous-partition ou lui permettre d'adopter son paramètre par défaut pour cette option.


(3) Les noms de sous-partition doivent être uniques. la table entière.


(4)  Les sous-partitions peuvent être utilisées avec des tables particulièrement volumineuses pour distribuer des données et des index sur plusieurs disques. Supposons que vous ayez 6 disques montés en tant que /disk0, /disk1, /disk2, etc. Considérons maintenant l'exemple suivant :

mysql> CREATE TABLE ts5 (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 s2
    ->                 DATA DIRECTORY = '/disk2/data'
    ->                 INDEX DIRECTORY = '/disk2/idx',
    ->             SUBPARTITION s3
    ->                 DATA DIRECTORY = '/disk3/data'
    ->                 INDEX DIRECTORY = '/disk3/idx'
    ->         ),
    ->         PARTITION p2 VALUES LESS THAN MAXVALUE (
    ->             SUBPARTITION s4
    ->                 DATA DIRECTORY = '/disk4/data'
    ->                 INDEX DIRECTORY = '/disk4/idx',
    ->             SUBPARTITION s5
    ->                 DATA DIRECTORY = '/disk5/data'
    ->                 INDEX DIRECTORY = '/disk5/idx'
    ->         )
    ->     );
Query OK, 0 rows affected (0.04 sec)

In this case, a separate disk is used for the data and for the indexes of each RANGE. Many other variations are possible;
another example might be: 
mysql> CREATE TABLE ts6 (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
    ->         )
    ->     );
Query OK, 0 rows affected (0.04 sec)


 

À l'avenir, lorsque le nombre d'achats pour la décennie commençant par l'an 2000 augmentera jusqu'à un point où le défaut location ne fournit plus suffisamment d'espace, les lignes correspondantes peuvent être déplacées à l'aide d'une instruction ALTER TABLE ... REORGANIZE PARTITION. Voir Section 17.3, « Gestion des partitions » pour une explication de la façon dont cela peut être fait.


Les options DATA DIRECTORY et INDEX DIRECTORY ne sont pas autorisées dans les définitions de partition lorsque le mode SQL du serveur NO_DIR_IN_CREATE est en vigueur. À partir de MySQL 5.5.5, ces options sont également interdites lors de la définition de sous-partitions (bogue n° 42954).

Comment le partitionnement MySQL gère NULL
Partitionnement dans MySQL ne fait rien pour interdire NULL comme valeur d'une expression de partitionnement,
qu'il s'agisse d'une valeur de colonne ou de la valeur d'une expression fournie par l'utilisateur. Même s'il est permis d'utiliser NULL comme valeur d'une expression qui devrait autrement donner un nombre entier, il est important de garder à l'esprit que NULL n'est pas un nombre. Le partitionnement de MySQL l'implémentation traite NULL comme étant inférieur à toute valeur non NULL, tout comme le fait ORDER BY.

 

Cela signifie que le traitement de NULL varie selon le partitionnement de différents types et peut produire un comportement que vous ne vous attendez pas si vous n'y êtes pas préparé.
Cela étant le cas, nous discutons dans cette section de la manière dont chaque type de partitionnement MySQL gère les valeurs NULL lors de la détermination de la partition dans laquelle une ligne doit être stockée,
et fournissons des exemples pour chacun.

 

Gestion de NULL avec le partitionnement RANGE.  Si vous insérez une ligne dans une table partitionnée par RANGE de telle sorte que la valeur de colonne utilisée pour déterminer la partition soit NULL,
la ligne est insérée dans la partition la plus basse. Par exemple, considérons ces deux tables dans une base de données nommée p, créée comme suit :

 

(1) Rang Partition,OK
Vous pouvez voir les partitions créé par ces deux instructions CREATE TABLE à l'aide de la requête suivante sur la table PARTITIONS dans la base de données INFORMATION_SCHEMA :

mysql> SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH
    ->    FROM INFORMATION_SCHEMA.PARTITIONS
    ->     WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_';
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t1         | p0             |          0 |              0 |       16384 |
| t1         | p1             |          0 |              0 |       16384 |
| t1         | p2             |          0 |              0 |       16384 |
| t2         | p0             |          0 |              0 |       16384 |
| t2         | p1             |          0 |              0 |       16384 |
| t2         | p2             |          0 |              0 |       16384 |
| t2         | p3             |          0 |              0 |       16384 |
| ts         | p0             |          0 |              0 |       16384 |
| ts         | p0             |          0 |              0 |       16384 |
| ts         | p1             |          0 |              0 |       16384 |
| ts         | p1             |          0 |              0 |       16384 |
| ts         | p2             |          0 |              0 |       16384 |
| ts         | p2             |          0 |              0 |       16384 |
+------------+----------------+------------+----------------+-------------+
14 rows in set (0.00 sec)

 

Remplissons maintenant chacune de ces tables avec une seule ligne contenant un NULL dans la colonne utilisée comme clé de partitionnement,
et vérifiez que les lignes ont été insérées à l'aide d'une paire d'instructions SELECT :

You can see which partitions are used to store the inserted rows by rerunning the previous query against INFORMATION_SCHEMA.PARTITIONS and inspecting the output:

mysql> INSERT INTO t1 VALUES (NULL, 'mothra');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO t2 VALUES (NULL, 'mothra');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM t1;
+------+--------+
| c1   | c2     |
+------+--------+
| NULL | mothra |
+------+--------+
1 row in set (0.01 sec)

mysql> SELECT * FROM t2;
+------+--------+
| c1   | c2     |
+------+--------+
| NULL | mothra |
+------+--------+
1 row in set (0.00 sec)

mysql> SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH    FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME LIKE 't_';
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t1         | p0             |          1 |          16384 |       16384 |
| t1         | p1             |          0 |              0 |       16384 |
| t1         | p2             |          0 |              0 |       16384 |
| t2         | p0             |          1 |          16384 |       16384 |
| t2         | p1             |          0 |              0 |       16384 |
| t2         | p2             |          0 |              0 |       16384 |
| t2         | p3             |          0 |              0 |       16384 |
| ts         | p0             |          0 |              0 |       16384 |
| ts         | p0             |          0 |              0 |       16384 |
| ts         | p1             |          0 |              0 |       16384 |
| ts         | p1             |          0 |              0 |       16384 |
| ts         | p2             |          0 |              0 |       16384 |
| ts         | p2             |          0 |              0 |       16384 |
+------------+----------------+------------+----------------+-------------+
13 rows in set (0.00 sec)


You can also demonstrate that these rows were stored in the lowest partition of each table by dropping these partitions,
and then re-running the SELECT statements:
 <br/>

(2) Handling of NULL with LIST partitioning. 必须将null在定义中加入才能录入null的分区数据

mysql> CREATE TABLE ts3 (
    ->     c1 INT,
    ->     c2 VARCHAR(20)
    -> )
    -> PARTITION BY LIST(c1) (
    ->     PARTITION p0 VALUES IN (0, 3, 6),
    ->     PARTITION p1 VALUES IN (1, 4, 7, NULL),
    ->     PARTITION p2 VALUES IN (2, 5, 8)
    -> );
Query OK, 0 rows affected (0.01 sec)

否则insert null的分区数据会抱错: ERROR 1504 (HY000): Table has no partition for value NULL

 

(3) Handling of NULL with HASH and KEY partitioning.

mysql> CREATE TABLE th (
    ->     c1 INT,
    ->     c2 VARCHAR(20)
    -> )
    -> PARTITION BY HASH(c1)
    -> PARTITIONS 2;
Query OK, 0 rows affected (0.00 sec)

There is no data record in beginnig.
mysql>   SELECT TABLE_NAME,PARTITION_NAME,TABLE_ROWS,AVG_ROW_LENGTH,DATA_LENGTH
    ->          FROM INFORMATION_SCHEMA.PARTITIONS
    ->          WHERE TABLE_SCHEMA = &#39;test&#39; AND TABLE_NAME =&#39;th&#39;;
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| th         | p0             |          0 |              0 |       16384 |
| th         | p1             |          0 |              0 |       16384 |
+------------+----------------+------------+----------------+-------------+
2 rows in set (0.00 sec)

mysql> INSERT INTO th VALUES (NULL, &#39;mothra&#39;), (0, &#39;gigan&#39;);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM th;
+------+--------+
| c1   | c2     |
+------+--------+
| NULL | mothra |
|    0 | gigan  |
+------+--------+
2 rows in set (0.00 sec)

mysql>   SELECT TABLE_NAME,PARTITION_NAME,TABLE_ROWS,AVG_ROW_LENGTH,DATA_LENGTH
    ->          FROM INFORMATION_SCHEMA.PARTITIONS
    ->          WHERE TABLE_SCHEMA = &#39;test&#39; AND TABLE_NAME =&#39;th&#39;;
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| th         | p0             |          2 |           8192 |       16384 |
| th         | p1             |          0 |              0 |       16384 |
+------------+----------------+------------+----------------+-------------+
2 rows in set (0.00 sec)

Recall that for any integer N, the value of NULL MOD N is always NULL. For tables that are partitioned by HASH or KEY, this result is treated for determining the correct partition as 0. Checking the INFORMATION_SCHEMA.PARTITIONS table once again, we can see that both rows were inserted into partition p0:

 

MySQL对分区中null值得处理, rang,key,以及hash中,都是直接放入min的分区中. list分区中则是放入事先定义好的包含null的分区中,如果list分区事先没有定义包含null值的分区,那么录入的时候会抱错

 以上就是MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (2) --> 子分区以及对录入Null值的处理情况.的内容,更多相关内容请关注PHP中文网(www.php.cn)! 


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn