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';

DEMO


更新

您可以创建生成的列来存储提取的年份值并按它进行分区。

DEMO

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 PARTITIONDELETE 快得多,侵入性也小得多。 SELECT 来自事实 table 用于个别行。 Fact table 上的索引应该很少。 DW blog

为大多数报告、图表等构建和维护“摘要 Table”。这通常是 table 和 'date' 以及一个或多个维度,加上计数和每个日期的小计。 给你你想要的速度。 Summary blog

如果您要突破插入速度的极限,请考虑批处理、ping-pong 等。Ingestion blog