mysql table 分区问题
mysql table partition issue
我正在尝试理解 mysql table 分区,以下是我尝试过的详细信息和示例。
mysql 版本 - 8.0.27
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
)
ENGINE=INNODB
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
);
示例插入语句。
insert into employees values (1,'ron', 'nath', '2019-10-10', '2021-10-12',123,123);
insert into employees values (2,'ram', 'nath', '1991-10-10', '1999-10-12',123,123);
已验证数据加载到分区中。
SELECT PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='employees';
这显示了两个分区 p2 和 p3 中的数据。但是当我在 select 语句下面 运行 并进行解释时,我看到所有分区都被引用了。
EXPLAIN select * from employees where year(separated)='1999';
如您在两个屏幕截图中所见,所有分区都被引用,不知道为什么?当 where 子句过滤器应用于从特定分区获取数据时,我预计只会引用特定分区。
WHERE 中的函数不允许使用分区修剪。不考虑WHERE中的表达式匹配分区表达式。
使用
select * from employees where separated BETWEEN '1999-01-01' AND '1999-12-31';
更新
您可以创建生成的列来存储提取的年份值并按它进行分区。
where year(separated)='1999';
separated
隐藏在函数调用中,因此不是 sargable 。 Akina 对此进行了详细说明。
我建议
WHERE separated >= '1999-01-01'
AND separated < '1999-01-01' + INTERVAL 1 YEAR
但是...非分区等价物 table 会让 Select 运行 一样快。 (需要INDEX(separated)
。)那么,请问您希望通过分区获得什么?
对时间序列进行分区的一个常见原因是为了更快地删除 'old' 数据。这可以通过 DROP PARTITION
完成。 details
数据仓库
对于快速增长的“事实”table,分区 仅 作为删除“旧”行的一种方式。 DROP PARTITION
比 DELETE
快得多,侵入性也小得多。 SELECT
来自事实 table 仅 用于个别行。 Fact table 上的索引应该很少。 DW blog
为大多数报告、图表等构建和维护“摘要 Table”。这通常是 table 和 'date' 以及一个或多个维度,加上计数和每个日期的小计。 这 给你你想要的速度。 Summary blog
如果您要突破插入速度的极限,请考虑批处理、ping-pong 等。Ingestion blog
我正在尝试理解 mysql table 分区,以下是我尝试过的详细信息和示例。
mysql 版本 - 8.0.27
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
)
ENGINE=INNODB
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
);
示例插入语句。
insert into employees values (1,'ron', 'nath', '2019-10-10', '2021-10-12',123,123);
insert into employees values (2,'ram', 'nath', '1991-10-10', '1999-10-12',123,123);
已验证数据加载到分区中。
SELECT PARTITION_NAME, TABLE_ROWS
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE TABLE_NAME='employees';
这显示了两个分区 p2 和 p3 中的数据。但是当我在 select 语句下面 运行 并进行解释时,我看到所有分区都被引用了。
EXPLAIN select * from employees where year(separated)='1999';
如您在两个屏幕截图中所见,所有分区都被引用,不知道为什么?当 where 子句过滤器应用于从特定分区获取数据时,我预计只会引用特定分区。
WHERE 中的函数不允许使用分区修剪。不考虑WHERE中的表达式匹配分区表达式。
使用
select * from employees where separated BETWEEN '1999-01-01' AND '1999-12-31';
更新
您可以创建生成的列来存储提取的年份值并按它进行分区。
where year(separated)='1999';
separated
隐藏在函数调用中,因此不是 sargable 。 Akina 对此进行了详细说明。
我建议
WHERE separated >= '1999-01-01'
AND separated < '1999-01-01' + INTERVAL 1 YEAR
但是...非分区等价物 table 会让 Select 运行 一样快。 (需要INDEX(separated)
。)那么,请问您希望通过分区获得什么?
对时间序列进行分区的一个常见原因是为了更快地删除 'old' 数据。这可以通过 DROP PARTITION
完成。 details
数据仓库
对于快速增长的“事实”table,分区 仅 作为删除“旧”行的一种方式。 DROP PARTITION
比 DELETE
快得多,侵入性也小得多。 SELECT
来自事实 table 仅 用于个别行。 Fact table 上的索引应该很少。 DW blog
为大多数报告、图表等构建和维护“摘要 Table”。这通常是 table 和 'date' 以及一个或多个维度,加上计数和每个日期的小计。 这 给你你想要的速度。 Summary blog
如果您要突破插入速度的极限,请考虑批处理、ping-pong 等。Ingestion blog