假设表my_table被划分为 1000 个分区,如下例所示:
P1, P2, P3, ... , P997, P998, P999, P1000
分区按日期组织,主要是每天一个分区。例如:
P0 < 01/01/2000 => Contains around 472M records
P1 = 01/01/2000 => Contains around 15k records
P2 = 02/01/2000 => Contains around 15k records
P3 = 03/01/2000 => Contains around 15k records
... = ../../.... => Contains around ... records
P997 = 07/04/2000 => Contains around 15k records
P998 = 08/04/2000 => Contains around 15k records
P999 = 09/04/2000 => Contains around 15k records
P1000 = 10/04/2000 => Contains around 15k records
请注意,P0 是<01/01/2000,不是=
现在的情况:
在不知道日期的情况下查找特定记录时,我正在执行以下操作:
SELECT * FROM my_schema.my_table WHERE ... ;
但这需要太多时间,因为它确实包括P0(30 秒)。
不可能的解决方案:
所以最好的办法是执行一个 SQL 查询,例如:
SELECT * FROM my_schema.my_table FROM PARTITION(P42) WHERE ... ;
但是我们永远不知道记录在哪个分区中。我们也不知道与分区关联的日期。当然,我们不会逐个循环遍历所有分区
糟糕的解决方案:
我可以通过 5 x 5 变得聪明:
SELECT * FROM my_schema.my_table FROM PARTITION(P40,P41,P42,P43,P44) WHERE ... ;
但是与上述相同的问题,我不会循环遍历所有分区,即使是 5 x 5
不那么糟糕的解决方案:
我不会运行任何一个(不包括P0在列表中):
SELECT * FROM my_schema.my_table FROM PARTITION(P1,P2,...,P99,P100) WHERE ... ;
查询太长,我必须为每个请求计算分区名称列表,因为它不能总是开始P1或结束P100(每天都有一些分区是丢弃,一些被创建)
聪明的解决方案(但它存在吗?):
我怎么能做这样的事情?
SELECT * FROM my_schema.my_table NOT IN PARTITION(P0) WHERE ... ;
或
SELECT * FROM my_schema.my_table PARTITION(*,-P0) WHERE ... ;
或
SELECT * FROM my_schema.my_table LESS PARTITION(P0) WHERE ... ;
或
SELECT * FROM my_schema.my_table EXCLUDE PARTITION(P0) WHERE ... ;
有没有办法做到这一点?
我的意思是一种选择所有分区的方法,期望其中一个或一些?注意:我事先不知道 dateofSale 的值。在桌子里面,我们有类似的东西
CREATE TABLE my_table
(
recordID NUMBER(16) NOT NULL, --not primary
dateOfSale DATE NOT NULL, --unknown
....
<other fields>
)
在回答之前,请阅读以下内容:
- 索引使用:是的,已经优化过了,但是请记住,我们不知道分区日期
- 不,我们不会在 P0 中删除记录,我们需要将它们保留至少几年(根据每个国家/地区的法律,保留 3、5 甚至 10 年)
- 我们可以将 P0 “拆分”为多个分区,但这并不能解决全局 SELECT 的问题
- 我们无法将该数据移动到新表中,我们需要将它们保存在此表中,因为我们有多个服务和软件在其中执行选择。我们将不得不编辑大量代码来为每个服务和后端的第二个表添加查询。
- 由于多种原因,我们不能使用 aka
WHERE date > 2019子句和索引日期字段,这将花费太多时间来解释。