草庐IT

MySQL分区表对NULL值的处理

GreatSQL 2023-03-28 原文
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者:王权富贵

1.概述

MySQL的分区表没有禁止NULL值作为分区表达式的值,无论它是列值还是用户提供的表达式的值,需要记住NULL值不是数字。MySQL的分区实现中将NULL视为小于任何非NULL值,与order by类似。

2.range分区表处理NULL

1.创建range分区表

CREATE TABLE t_range (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY RANGE(c1) (
  PARTITION p0 VALUES LESS THAN (0),
  PARTITION p1 VALUES LESS THAN (10),
  PARTITION p2 VALUES LESS THAN MAXVALUE
);

2.插入2条分区列为null值的数据

insert into t_range values (NULL,'a'),(NULL,'b');

3.查看数据的分布情况

mysql> SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = 'test1' AND TABLE_NAME = 't_range';
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t_range    | p0             |          2 |           8192 |       16384 |
| t_range    | p1             |          0 |              0 |       16384 |
| t_range    | p2             |          0 |              0 |       16384 |
+------------+----------------+------------+----------------+-------------+
3 rows in set (0.01 sec)

mysql> select * from t1 partition(p0);
+------+------+
| c1   | c2   |
+------+------+
| NULL | a    |
| NULL | b    |
+------+------+
2 rows in set (0.00 sec)

可以看到分区列包含null值的2条数据都分布在p0分区上。

3.list分区表处理NULL

1.创建2张list分区表,t_list1分区列包含null值,t_list2分区列中不包含null值

CREATE TABLE t_list1 (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY LIST(c1) (
    PARTITION p0 VALUES IN (0, 3, 6),
    PARTITION p1 VALUES IN (1, 4, 7),
    PARTITION p2 VALUES IN (2, 5, 8),
    PARTITION p3 VALUES IN (NULL)
);

CREATE TABLE t_list2 (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY LIST(c1) (
    PARTITION p0 VALUES IN (0, 3, 6),
    PARTITION p1 VALUES IN (1, 4, 7),
    PARTITION p2 VALUES IN (2, 5, 8)
);

2.分别向2张表中插入2条分区列为null值的数据

mysql> insert into t_list1 values (NULL,'a'),(NULL,'b');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into t_list2 values (NULL,'a'),(NULL,'b');
ERROR 1526 (HY000): Table has no partition for value NULL

可以看到 t_list2 表的分区列中不包含null值,所以数据插入失败。

3.查看数据的分布情况

mysql> SELECT TABLE_NAME, PARTITION_NAME, TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_SCHEMA = 'test1' AND TABLE_NAME = 't_list1';
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t_list1    | p0             |          0 |              0 |       16384 |
| t_list1    | p1             |          0 |              0 |       16384 |
| t_list1    | p2             |          0 |              0 |       16384 |
| t_list1    | p3             |          2 |           8192 |       16384 |
+------------+----------------+------------+----------------+-------------+
4 rows in set (0.00 sec)

可以看到 t_list1 表中插入的2条包含null值的数据,由于p3分区包含null值列,所以2条数据分布在p3分区中。

4.hash/key分区表处理NULL

1.创建2张测试表,一张hash分区表,一张key分区表

CREATE TABLE t_hash (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY HASH(c1)
PARTITIONS 2;

CREATE TABLE t_key (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY key(c1)
PARTITIONS 2;

2.分别向2张表中插入3条分区列为null值的数据

mysql> insert into t_hash values (NULL,'a'),(0,'b'),(1,'c');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into t_key values (NULL,'a'),(0,'b'),(1,'c');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

3.查看数据的分布情况

mysql> SELECT TABLE_NAME,PARTITION_NAME,TABLE_ROWS,AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test1' AND TABLE_NAME in ('t_hash','t_key');
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t_hash     | p0             |          2 |           8192 |       16384 |
| t_hash     | p1             |          1 |          16384 |       16384 |
| t_key      | p0             |          2 |           8192 |       16384 |
| t_key      | p1             |          1 |          16384 |       16384 |
+------------+----------------+------------+----------------+-------------+
4 rows in set (0.00 sec)

mysql> select * from t_hash partition(p0);
+------+------+
| c1   | c2   |
+------+------+
| NULL | a    |
|    0 | b    |
+------+------+
2 rows in set (0.00 sec)

mysql> select * from t_key partition(p0);
+------+------+
| c1   | c2   |
+------+------+
| NULL | a    |
|    1 | c    |
+------+------+
2 rows in set (0.00 sec)

可以看到分区列中包含null值的记录都在p0分区。

4.如果我们增加hash/key分区表的分区数,分区列为null值的记录会分布到其他分区

# 创建hash/key分区表,分区数为3
CREATE TABLE t_hash1 (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY HASH(c1)
PARTITIONS 3;

CREATE TABLE t_key1 (
c1 INT,
c2 VARCHAR(20)
)
PARTITION BY key(c1)
PARTITIONS 3;


# 插入数据
insert into t_hash1 values (NULL,'a'),(0,'b'),(1,'c');
insert into t_key1 values (NULL,'a'),(0,'b'),(1,'c');


# 查看数据的分布情况
mysql> SELECT TABLE_NAME,PARTITION_NAME,TABLE_ROWS,AVG_ROW_LENGTH,DATA_LENGTH FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA = 'test1' AND TABLE_NAME in ('t_hash1','t_key1');
+------------+----------------+------------+----------------+-------------+
| TABLE_NAME | PARTITION_NAME | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH |
+------------+----------------+------------+----------------+-------------+
| t_hash1    | p0             |          1 |          16384 |       16384 |
| t_hash1    | p1             |          1 |          16384 |       16384 |
| t_hash1    | p2             |          1 |          16384 |       16384 |
| t_key1     | p0             |          0 |              0 |       16384 |
| t_key1     | p1             |          2 |           8192 |       16384 |
| t_key1     | p2             |          1 |          16384 |       16384 |
+------------+----------------+------------+----------------+-------------+
6 rows in set (0.00 sec)

mysql> select * from t_hash1 partition(p2);
+------+------+
| c1   | c2   |
+------+------+
| NULL | a    |
+------+------+
1 row in set (0.00 sec)

mysql> select * from t_key1 partition(p2);
+------+------+
| c1   | c2   |
+------+------+
| NULL | a    |
+------+------+
1 row in set (0.00 sec)

可以看到,当hash/key分区表的分区数为3时,分区列为null值的记录分布在了p2分区。

5.总结

range分区表:如果插入记录的分区列值为NULL,则将该行记录插入到最小的分区中。

list分区表:对NULL值的处理有2种方式:

(1)当且仅当只有一个分区使用包含NULL的值做分区表达式时(例如:PARTITION p3 VALUES IN (NULL)),允许插入分区列为NULL的值。

(2)当表中没有显示使用包含NULL的值做分区表达式时,会拒绝插入分区列为NULL的值。

hash/key分区表:对NULL的处理略有不同,不同的分区数,会导致分区列为NULL值的记录分布到不同的分区。


Enjoy GreatSQL ?

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

捉虫活动详情:https://greatsql.cn/thread-97-1-1.html

社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

技术交流群:

微信:扫码添加GreatSQL社区助手微信好友,发送验证信息加群

)

有关MySQL分区表对NULL值的处理的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. Ruby rpartition 与分区? - 2

    rpartition和partition有什么区别?我已经阅读了文档,但我认为它们是一样的。只是那些出现在后来的ruby​​版本中吗? 最佳答案 以下示例将有助于识别差异:"abccba".partition("b")#=>["a","b","ccba"]"abccba".rpartition("b")#=>["abcc","b","a"]所以区别在于rpartition搜索最右边的匹配项,而不是最左边的匹配项。 关于Rubyrpartition与分区?,我们在StackOverflow

  3. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  4. "\0"null 的 Ruby 测试? - 2

    我在破坏脚本的字符串中出现了一些奇怪的字符。据我所知,通过putbadstring到控制台,它们是"\0\0\0\0"。我想对此进行测试,以便我可以忽略它们...但是如何呢?以为这就是blank?和empty?的用途?!?:>badstring="\0"=>"\u0000">badstring.blank?NoMethodError:undefinedmethod`blank?'for"\u0000":Stringfrom(irb):97from/Users/meltemi/.rvm/rubies/ruby-2.0.0-p195/bin/irb:16:in`'>badstring.em

  5. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  6. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  7. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  8. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

  9. ruby-on-rails - Sunspot:如何对具有不同值的多个字段进行全文查询? - 2

    我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使

  10. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

随机推荐