Mysql按时间进行表分区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql按时间进行表分区相关的知识,希望对你有一定的参考价值。

参考技术A 以下是创建一张测试表TEST并且按照时间CREATE_TIME创建RANGE分区,并使用ID创建hash分区,组成复合分区。
CREATE TABLE TEST (
CREATE_TIME DATETIME DEFAULT NULL, ID BIGINT(15) DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8
PARTITION BY RANGE(TO_DAYS(CREATE_TIME)) PARTITIONS 7 SUBPARTITION BY HASH(ID) SUBPARTITIONS 16
(PARTITION P1710 VALUES LESS THAN (TO_DAYS ('2017-10-01'))
(SUBPARTITION P1710sp0 ,SUBPARTITION P1710sp1 ,
SUBPARTITION P1710sp2 ,SUBPARTITION P1710sp3 ,
SUBPARTITION P1710sp4 ,SUBPARTITION P1710sp5 ,
SUBPARTITION P1710sp6 ,SUBPARTITION P1710sp7 ,
SUBPARTITION P1710sp8 ,SUBPARTITION P1710sp9 ,
SUBPARTITION P1710sp10 ,SUBPARTITION P1710sp11 ,
SUBPARTITION P1710sp12 ,SUBPARTITION P1710sp13 ,
SUBPARTITION P1710sp14 ,SUBPARTITION P1710sp15 ),
PARTITION P1711 VALUES LESS THAN (TO_DAYS ('2017-11-01'))
(SUBPARTITION P1711sp0 ,SUBPARTITION P1711sp1 ,
SUBPARTITION P1711sp2 , SUBPARTITION P1711sp3 ,
SUBPARTITION P1711sp4 , SUBPARTITION P1711sp5 ,
SUBPARTITION P1711sp6 , SUBPARTITION P1711sp7 ,
SUBPARTITION P1711sp8 , SUBPARTITION P1711sp9 ,
SUBPARTITION P1711sp10 , SUBPARTITION P1711sp11 ,
SUBPARTITION P1711sp12 , SUBPARTITION P1711sp13 ,
SUBPARTITION P1711sp14 , SUBPARTITION P1711sp15 ),

按任意开始和结束日期对订单表进行分区

【中文标题】按任意开始和结束日期对订单表进行分区【英文标题】:Partition Orders table by arbitrary start and end day-of-month 【发布时间】:2020-08-12 05:25:14 【问题描述】:

鉴于以下相当标准的订单表:

CREATE TABLE [dbo].[orders](
    [bill_product_id] [int] IDENTITY(1,1) NOT NULL,
    [Bill_date] [datetime] NULL,
    [TenantId] [int] NULL,
    [Product_type] [int] NULL,
    [Quantity] [int] NULL,
    [Customer_cost] [numeric](18, 10)
)

以下查询为我提供表orders 中有记录的每个月的开始日期和结束日期

SELECT distinct DATEADD(DAY,1,EOMONTH(bill_date,-1)) as start_date,
       EOMONTH(bill_date) as end_date
    FROM orders

示例结果集:

开始日期结束日期


2020-07-01 2020-07-31

2020-08-01 2020-08-31

现在我们需要更改“结算周期”,因此我们需要从每月 26 日开始结算周期,而不是从每月 1 日开始,到每月最后一天结束,月底是下个月的第 25 天(不要问)。

我确定我可以根据开始日期确定 end_date,但我不确定将数据划分为月份的 26 日至 25 日的最佳方式。请提出一个有效的方法来做到这一点。

【问题讨论】:

【参考方案1】:

也许你可以使用DATEFROMPARTS

DECLARE @bill_date DATE = '2020-08-12'

SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date), 26)
      ,DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) + 1, 25)

但你的方式也是有效的,可以加强。


正如你所指出的,它应该是:

SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end) , 26);

为了确保小于26 的日期保持在当前间隔内,而不是像我原来的解决方案中那样的下一个。

【讨论】:

这给出了从 8 月 26 日开始的 next 间隔。我尝试从两个“月份”部分中减去 1,但如果给出的日期是“2020-”,这将不起作用07-30' - 计算到 6 月 26 日,应该是 7 月 26 日 对于2020-07-30,我得到2020-07-262020-08-25。这不是你需要的吗? 是的,但如果给定 '2020-08-12',相同的函数会返回未来的日期 - 而不是当前的时间间隔。但是 DATEFROMPARTS 帮我找到了真正的解决方案: SELECT DATEFROMPARTS(YEAR(@bill_date), MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end) , 26); @Black 我现在明白逻辑了 :-)【参考方案2】:

感谢@gotqn,我可以按如下方式使用 DATEFROMPARTS

 SELECT DATEFROMPARTS(YEAR(@bill_date),  
         MONTH(@bill_date) - (CASE WHEN DAY(@bill_date) >= 26 then 0 else 1 end), 
         26) as start_date
        ,DATEFROMPARTS(YEAR(@bill_date),  
         MONTH(@bill_date) + (CASE WHEN DAY(@bill_date) >= 26 then 1 else 0 end),
         25) as end_date

【讨论】:

【参考方案3】:

您可以减去 26 天并使用 datefromparts():

SELECT DISTINCT DATEFROMPARTS(YEAR(yyyymm_start), MONTH(yyyymm_start), 26) as start_date,
       DATEFROMPARTS(YEAR(yyyymm_end), MONTH(yyymm_end), 25) as end_date
FROM orders o CROSS APPLY
     (VALUES (DATEADD(DAY, -26, BILL_DATE),
              DATEADD(MONTH, 1, DATEADD(DAY, -26, BILL_DATE))
             )
     ) as v(yyyymm_start, yyyymm_end)

【讨论】:

【参考方案4】:

只需使用 dateadd 即可“移动”您的计费周期。

我假设然后你查询

  declare @billDate date = '2020-07-16'
 SELECT distinct DATEADD(DAY,1,EOMONTH(@billDate)) as start_date,
       EOMONTH(@billDate) as end_date, 'Original' as query
    --FROM orders


 SELECT distinct DATEADD(DAY,26,EOMONTH(@billDate,-1)) as start_date,
       dateadd(day,25,EOMONTH(@billDate) )as end_date, 'Modified' as query
    --FROM orders

会导致

start_date end_date   query
---------- ---------- -------- 
2020-07-01 2020-07-31 Original
         
start_date end_date   query
---------- ---------- -------- 
2020-07-26 2020-08-25 Modified

【讨论】:

这与@gotqn 的原始答案有相同的问题,即对于 '2020-08-10' 它返回 future 间隔 2020-08-26 到 2020-09- 25 已修复,在 eomonth 函数中添加了 -1 没有。现在它返回值“2020-07-30”的错误(先前)间隔 请张贴给定账单日期的预计开始/结束日期 这一切都在原始帖子中,也在@gotqn 的答案中。不用担心,它已经被正确回答了

以上是关于Mysql按时间进行表分区的主要内容,如果未能解决你的问题,请参考以下文章

mysql之表分区

mysql进行分区之后所占的空间是否会变更大?

MySQL分区表-按月份归类

数据库 之 Mysql的表分区

oracle按时间创建分区表

sql 分区表操作