【问题标题】:mysql partitioning with unix_timestamp from variablemysql分区与变量中的unix_timestamp
【发布时间】:2012-06-22 19:56:50
【问题描述】:

鉴于此:

delimiter //
create procedure setup()
begin
  declare d datetime;
  set d = rounddate(now());

  create table s_time (req_id int not null,
                       ser_id int not null,
                       hel_id int not null,
                       posted int unsigned not null,
                       completed int unsigned not null default 0
                      )
  partition by range (completed) (partition p0 values less than ( unix_timestamp(d) ),
                                  partition p1 values less than ( unix_timestamp(d + interval 1 day) )
                                 );
end//

我明白了:

ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function are not allowed

有没有办法让它工作,或者我必须使用硬编码字符串作为输入。即使用:unix_timestamp('2012-07-07 00:00:00')

【问题讨论】:

  • 您的s_time 表应该在您的程序结束后继续存在吗?另外,您是否希望自动重组分区?换句话说:现在,p0 分区包含到目前为止的所有记录。从现在起的 24 小时内,p0 是否会包含截至“从现在起 24 小时内”的所有记录?
  • 这个过程只是为了自动设置表格。该表将用作滚动分区。 24 小时后,第一个分区将被删除并添加另一个分区。我想知道是否有办法不对前两个分区进行硬编码。我想我可以创建另一个程序来执行前两个初始滚动,并在创建具有硬编码值的表之后调用它。

标签: mysql database-partitioning


【解决方案1】:

为了将解决方案保留在完整的 sql 中,这是我发现的。

delimiter //
create procedure setup()
begin
  declare d, d2 int;
  set d = unix_timestamp();
  set d2 = unix_timestamp(now() + interval 1 day);

  create table s_time (req_id int not null,
                       ser_id int not null,
                       hel_id int not null,
                       posted int unsigned not null,
                       completed int unsigned not null default 0
                      );

  SET @stmt = concat('alter table s_time PARTITION BY RANGE (completed) (
                      partition p0 values less than (', d, '),
                      partition p1 values less than (', d2, '))');
  PREPARE pStmt FROM @stmt;
  EXECUTE pStmt;
  DEALLOCATE PREPARE pStmt;

end//
delimiter ;
call setup();

【讨论】:

    【解决方案2】:

    这不起作用的原因不是很清楚,我怀疑文档或错误消息中存在错误。在我看来,您收到的错误是不恰当的。

    根据the manual:

    在分区中不允许以下构造 表达式:

    • 存储过程、存储函数、UDF 或插件。
    • 声明的变量或用户变量。

    这解释了您的表定义失败的原因。

    现在,如何摆脱你的变量?如果您尝试从分区定义中删除声明的变量:

    CREATE TABLE s_time (
        completed INT UNSIGNED NOT NULL DEFAULT 0
    )
    PARTITION BY RANGE ( completed  ) (
        PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP() )
    );
    

    你会得到同样的错误。但是,MySQL manual 声明:

    也可以在 VALUES LESS THAN 子句中使用表达式。 但是,MySQL 必须能够评估表达式的返回值 作为 LESS THAN (。

    根据这个定义,UNIX_TIMESTAMP() 应该是一个有效的表达式。手册中的这句话至少可以说是不准确的。我很想知道其他人是否可以提供另一种理解。

    现在,查看错误消息,如果您将LESS THAN 子句视为“分区函数”的一部分,那么错误消息开始有意义:

    ERROR 1064 (42000):常量、随机或依赖于时区的表达式 (子)分区函数或在 LESS THAN 子句中是不允许的

    “随机”也表示非确定性UNIX_TIMESTAMP() 函数就是根据定义。

    为了实现您想要做的事情,除了使用外部脚本生成合适的ALTER TABLE 命令之外,我没有看到其他解决方案。

    1) 创建您的初始表:

    CREATE TABLE s_time (
        req_id INT NOT NULL,
        ser_id INT NOT NULL,
        hel_id INT NOT NULL,
        posted INT UNSIGNED NOT NULL,
        completed INT UNSIGNED NOT NULL DEFAULT 0
    ) PARTITION BY RANGE (completed) (
        PARTITION p0 VALUES LESS THAN (0),
        PARTITION p1 VALUES LESS THAN (1)
    );
    

    2) Reorganise the partitions 时不时地(例如使用 PHP):

    <?php
        $query = 
            "ALTER TABLE s_time REORGANIZE PARTITION p0, p1 INTO (
                PARTITION p0 VALUES LESS THAN ($today),
                PARTITION p1 VALUES LESS THAN ($tomorrow)
            )";
    

    请参阅proof of concept here

    【讨论】:

      猜你喜欢
      • 2013-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      • 2011-08-17
      • 1970-01-01
      相关资源
      最近更新 更多