mysql分区

e0bqpujr  于 2021-06-25  发布在  Mysql
关注(0)|答案(2)|浏览(245)

我有一个表,这将随着时间的推移增长很大,而且我只需要少量的数据说,过去7天。
我想把它配置成7天的数据放在一个分区中,然后放在下一个分区中。这样我将只保留两个分区,并将其他分区存档。
我在这里读过关于mysql分区的文章,但是在文章中创建分区的方法是,我们在只创建表时指定所有分区。
我不确定这是不是最好的方法来做它,我们添加分区逻辑很长一段时间。
有什么想法吗?

o7jaxewo

o7jaxewo1#

mysql中没有“自动”分区管理。我们必须运行一些特定的sql语句来从分区表中添加和删除分区。
我们使用cron作业自动化了任务,该作业运行我们编写的mysql过程来删除(交换)旧分区,并运行另一个过程来添加新分区。这些步骤是特定于特定表的。
我们的table是用 RANGETIMESTAMP 列。分区表达式如下 UNIX_TIMESTAMP(col) .
为了添加一个新的分区,我们重新组织 MAXVALUE 分区,它总是(或者应该总是)空的,所以操作非常快。我们动态地准备并执行以下形式的语句:

ALTER TABLE ourtable REORGANIZE PARTITION pmax 
 INTO ( PARTITION pn_name VALUES LESS THAN (UNIX_TIMESTAMP(pn_date))
      , PARTITION pmax    VALUES LESS THAN MAXVALUE)

要为新分区(pn\u name)获取新的日期值,我们采用 partition_description 从第二个分区到最后一个分区的值(最后一个分区是maxvalue分区),并向其添加7天以获得 pn_date 要使用的字符串。我们使用相同的值为新分区生成pnu名称(我们按照如下模式命名分区: p20161030 基于分区描述中的日期值,例如。 UNIX_TIMESTAMP('2016-10-30') .
(这些信息是从一个相当复杂的查询中获得的,其中有几个 information_schema.partitions 查看。
在另一个删除旧分区的过程中,我们实际上将旧分区“交换”到一个存档表中(存档表稍后会备份,并由其他任务删除。)
该过程基本上运行一系列如下语句:

DROP TABLE IF EXISTS `_et` ;
CREATE TABLE `_et` LIKE `rdg_point_value` ;
ALTER TABLE `_et` REMOVE PARTITIONING ;
ALTER TABLE `ourtable` EXCHANGE PARTITION `oldest_partition` WITH TABLE `_et` ;
ALTER TABLE `ourtable` DROP PARTITION `oldest_partition` ;
RENAME TABLE `et` TO `archive_oldest_partition` ;

(我希望有一种更干净的方法,可以在一条语句中创建一个新的未分区表,例如 CREATE TABLE ... LIKE ... WITHOUT PARTITIONING ,但没有这一点,我们决定在两个单独的声明。)
删除最旧的分区将是一个更简单的过程。
为了获得关于最旧分区的信息,我们的查询可能是过度的。但这是大部分“魔法”发生的地方。只是想让你知道这个查询是什么样的。。。

FROM information_schema.partitions p1
 JOIN information_schema.partitions px
   ON px.table_schema               = 'ourdatabase'
  AND px.table_name                 = 'ourtable'
  AND px.partition_method           = 'RANGE'
  AND px.partition_expression       = 'UNIX_TIMESTAMP(ourcol)'
  AND px.partition_description      = 'MAXVALUE'
WHERE p1.table_schema               = 'ourdatabase'
  AND p1.table_name                 = 'ourtable'
  AND p1.partition_method           = 'RANGE'
  AND p1.partition_expression       = 'UNIX_TIMESTAMP(ourcol)'
  AND p1.partition_description     <> 'MAXVALUE'
  AND p1.partition_description + 0 <= UNIX_TIMESTAMP(DATE(NOW()) + INTERVAL -187 DAY)
  AND p1.partition_ordinal_position = 1

你也许可以用一个简单的查询来解决问题(我们的查询被设计成仅当“最旧”分区中的所有时间戳值都至少有六个月大,并且仅当定义了maxvalue分区时,才返回“最旧”分区。
每个过程都使用当前日期来查看添加或删除分区的“时间”(向前和向后的时间量被硬编码到过程中的查询中。。。如果还没有到时间,查询将返回0行。
这些过程每周只需要执行一次,我们将它们设计为任何“额外”运行都不会在指定的时间范围之外添加或删除分区。
我们计划每天执行这些过程,在大多数情况下,该过程运行一个返回零行的查询,然后退出。只有当查询返回一行时,才有工作要做。

shstlldc

shstlldc2#

不幸的是,这将是一个相当手工的过程。最好的办法是每周提前创建分区,然后定期运行一个作业,将旧数据归档到“catchall”分区中。
e、 g.带:

PARTITION BY RANGE ( TO_DAYS(date) ) (
    PARTITION pmin VALUES LESS THAN ( TO_DAYS('2016-10-02 00:00:00') ),
    PARTITION p1 VALUES LESS THAN ( TO_DAYS('2016-10-09 00:00:00') ),
    PARTITION p2 VALUES LESS THAN ( TO_DAYS('2016-10-16 00:00:00') ),
    PARTITION p3 VALUES LESS THAN ( TO_DAYS('2016-10-23 00:00:00') ),
    PARTITION pmax VALUES LESS THAN (MAXVALUE)
);

有几个空的分区和更高的日期坐在那里,然后每周做一次“轮班”没有什么坏处。只要在更改分区定义时,数据窗口按分区大小移动,就足够快了。
你的工作会像

ALTER TABLE x REORGANIZE PARTITION pmin,p1 INTO (
    PARTITION pmin VALUES LESS THAN ('2016-10-09 00:00:00')
);

ALTER TABLE x 
    ADD PARTITION px VALUES LESS THAN ( TO_DAYS('2016-10-30 00:00:00') )
);

相关问题