按范围列分区意外行为
Partitioning by range columns unexpected behavior
我有 MySQL table 按范围列分区(c_id 和 created_at)
我创建了 2 个分区:
logs_1_2020(c_id 小于 2 且创建时间小于 2021-01-01 00:00:00)
logs_1_2021(c_id 小于 2 且创建时间小于 2022-01-01 00:00:00)
当我运行
INSERT INTO example_log_table (c_id, data, created)
VALUES (1, 'test', '2021-10-24 18:16:08')
我应该找到存储在 logs_1_2021 中的结果,但当我在 logs_1_2020 中找到她时,我感到震惊。
有人对此有解释吗?
此 table SQL 生成器:
CREATE TABLE example_log_table (
id int auto_increment ,
c_id int,
data TEXT NOT NULL,
created DATETIME NOT NULL,
primary key (id,c_id,created)
) PARTITION BY RANGE columns (c_id,created)(
PARTITION logs_1_2020 VALUES LESS THAN (2,'2021-01-01 00:00:00'),
PARTITION logs_1_2021 VALUES LESS THAN (2,'2022-01-01 00:00:00')
);
当您使用多列作为分区键时,放置基于元组比较。您可以通过这种方式测试一个元组是否小于另一个元组 (MySQL 8.0):
select row(1, '2021-10-24 18:16:08') < row(2, '2021-01-01 00:00:00');
+---------------------------------------------------------------+
| row(1, '2021-10-24 18:16:08') < row(2, '2021-01-01 00:00:00') |
+---------------------------------------------------------------+
| 1 |
+---------------------------------------------------------------+
元组不等式比较的规则很棘手。我建议你仔细阅读https://dev.mysql.com/doc/refman/8.0/en/partitioning-columns-range.html and https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than。
For row comparisons, (a, b) < (x, y)
is equivalent to:
(a < x) OR ((a = x) AND (b < y))
在这种情况下,1
小于2
,因此您插入的元组小于定义分区上限的元组logs_1_2020
。
您还可以考虑如果要使用 ORDER BY c_id,created
查询一组行,数据将如何排序。它会首先按 c_id
排序,然后只有在 c_id
上有平局的情况下,它才会按 created
.
对平局排序
除非你有充分的理由进行分区,否则将其删除并将索引更改为
PRIMARY KEY(c_id, created, id),
INDEX(id)
如果您希望拥有大量数据并希望删除“旧数据”,则 PARTITION BY RANGE
超过 created
;这有助于周期性 DROP PARTITION
。并且上面的两个索引仍然有效和有用。
经过大量搜索有没有办法让Mysql根据列值而不是元组比较将数据插入分区
我决定像这样制作我的分区:
PARTITION logs_1_2020 VALUES LESS THAN (1,'2021-01-01'),
PARTITION logs_2_2020 VALUES LESS THAN (2,'2021-01-01'),
PARTITION logs_2_2021 VALUES LESS THAN (2,'2022-01-01')
并且在插入时,我插入了第一个参数,以使 Mysql 比较第二个参数是否更少。
所以当 运行 :
INSERT INTO example_log_table (c_id, created) VALUES (2, '2021-10-21')
将在 logs_2_2021 处插入,因为 c_id 匹配并且创建的小于第二行创建的
我有 MySQL table 按范围列分区(c_id 和 created_at) 我创建了 2 个分区:
logs_1_2020(c_id 小于 2 且创建时间小于 2021-01-01 00:00:00)
logs_1_2021(c_id 小于 2 且创建时间小于 2022-01-01 00:00:00)
当我运行
INSERT INTO example_log_table (c_id, data, created)
VALUES (1, 'test', '2021-10-24 18:16:08')
我应该找到存储在 logs_1_2021 中的结果,但当我在 logs_1_2020 中找到她时,我感到震惊。
有人对此有解释吗?
此 table SQL 生成器:
CREATE TABLE example_log_table (
id int auto_increment ,
c_id int,
data TEXT NOT NULL,
created DATETIME NOT NULL,
primary key (id,c_id,created)
) PARTITION BY RANGE columns (c_id,created)(
PARTITION logs_1_2020 VALUES LESS THAN (2,'2021-01-01 00:00:00'),
PARTITION logs_1_2021 VALUES LESS THAN (2,'2022-01-01 00:00:00')
);
当您使用多列作为分区键时,放置基于元组比较。您可以通过这种方式测试一个元组是否小于另一个元组 (MySQL 8.0):
select row(1, '2021-10-24 18:16:08') < row(2, '2021-01-01 00:00:00');
+---------------------------------------------------------------+
| row(1, '2021-10-24 18:16:08') < row(2, '2021-01-01 00:00:00') |
+---------------------------------------------------------------+
| 1 |
+---------------------------------------------------------------+
元组不等式比较的规则很棘手。我建议你仔细阅读https://dev.mysql.com/doc/refman/8.0/en/partitioning-columns-range.html and https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#operator_less-than。
For row comparisons,
(a, b) < (x, y)
is equivalent to:(a < x) OR ((a = x) AND (b < y))
在这种情况下,1
小于2
,因此您插入的元组小于定义分区上限的元组logs_1_2020
。
您还可以考虑如果要使用 ORDER BY c_id,created
查询一组行,数据将如何排序。它会首先按 c_id
排序,然后只有在 c_id
上有平局的情况下,它才会按 created
.
除非你有充分的理由进行分区,否则将其删除并将索引更改为
PRIMARY KEY(c_id, created, id),
INDEX(id)
如果您希望拥有大量数据并希望删除“旧数据”,则 PARTITION BY RANGE
超过 created
;这有助于周期性 DROP PARTITION
。并且上面的两个索引仍然有效和有用。
经过大量搜索有没有办法让Mysql根据列值而不是元组比较将数据插入分区 我决定像这样制作我的分区:
PARTITION logs_1_2020 VALUES LESS THAN (1,'2021-01-01'),
PARTITION logs_2_2020 VALUES LESS THAN (2,'2021-01-01'),
PARTITION logs_2_2021 VALUES LESS THAN (2,'2022-01-01')
并且在插入时,我插入了第一个参数,以使 Mysql 比较第二个参数是否更少。
所以当 运行 :
INSERT INTO example_log_table (c_id, created) VALUES (2, '2021-10-21')
将在 logs_2_2021 处插入,因为 c_id 匹配并且创建的小于第二行创建的