删除数据

此页面包含使用SQL语句从 hubble中删除数据行的说明。

准备工作

在阅读本页之前,请执行以下操作:

  • 创建hubble无服务器集群或启动本地集群。
  • 安装驱动程序或 ORM框架。
  • 连接到数据库。
  • 创建数据库架构。
  • 插入要删除的数据。

在本页的示例中,我们使用通过命令导入的示例数据。

使用DELETE

要删除表中的行,请使用带有WHERE子句的DELETE语句,该子句过滤标识要删除的行的列。

SQL语法

在 SQL中,DELETE语句一般采用以下形式:

DELETE FROM {table} WHERE {filter_column} {comparison_operator} {filter_value}

参数说明:

  • {table}是包含要删除的行的表。
  • {filter_column}是要过滤的列。
  • {comparison_operator}是一个比较运算符,解析为TRUEFALSE(例如,=)。
  • {filter_value}是过滤器的匹配值。

最佳实践

以下是删除行时要遵循的一些最佳做法:

  • 限制DELETE您执行的语句数量。使用单个语句删除多行比执行多个DELETE语句删除单个行更有效。
  • 始终在查询中指定WHERE子句。DELETE如果没有WHERE指定子句,hubble将删除指定表中的所有行。
  • 要删除表中的所有行,请使用TRUNCATE语句而不是DELETE语句。
  • 要删除大量行,请使用批量删除循环。
  • 从应用程序执行DELETE语句时,请确保将 SQL执行函数包装在重试循环中,以处理可能在争用下发生的事务错误。
  • 查看下面的性能注意事项。

示例1

删除在非唯一列上过滤的行

假设要删除一定范围编号的历史数据,empno要删除表中介于两个值(1-1000)之间的所有行。

sql语言

delete from emp where  empno BETWEEN 1 AND 1000;

go语言

// 'db' is an open database connection

tsOne := 1
tsTwo := 1000

if _, err := db.Exec("delete from emp where  empno BETWEEN $1 AND $2", tsOne, tsTwo); err != nil {
  return err
}
return nil

JAVA语言

// ds is an org.postgresql.ds.PGSimpleDataSource

int tsOne = 1;
int tsTwo = 1000;

try (Connection connection = ds.getConnection()) {
    PreparedStatement p = connection.prepareStatement("delete from emp where  empno BETWEEN ? AND ?");
    p.setInt(1, tsOne);
    p.setInt(2, tsTwo);
    p.executeUpdate();

} catch (SQLException e) {
    System.out.printf("sql state = [%s]\ncause = [%s]\nmessage = [%s]\n", e.getSQLState(), e.getCause(),
            e.getMessage());
}

PYTHON语言

# conn is a psycopg2 connection

tsOne = 1
tsTwo = 1000

with conn.cursor() as cur:
    cur.execute(
        "delete from emp where  empno BETWEEN %s AND %s", (tsOne, tsTwo))

示例2

删除在唯一列上过滤的行

假设要删除特定编号的历史数据。

sql语言

delete from emp where  empno in (1001,7369,3256);

go语言


// 'db' is an open database connection

codeOne := 1001
codeTwo := 7369
codeThree := 3256

if _, err := db.Exec("delete from emp where  empno in ($1, $2, $3)", codeOne, codeTwo, codeThree); err != nil {
  return err
}
return nil

JAVA语言


// ds is an org.postgresql.ds.PGSimpleDataSource

int codeOne = 1001;
int codeTwo = 7369;
int codeThree = 3256;

try (Connection connection = ds.getConnection()) {
    PreparedStatement p = connection.prepareStatement("delete from emp where  empno in (?, ?, ?)");
    p.setInt(1, codeOne);
    p.setInt(2, codeTwo);
    p.setInt(3, codeThree);
    p.executeUpdate();

} catch (SQLException e) {
    System.out.printf("sql state = [%s]\ncause = [%s]\nmessage = [%s]\n", e.getSQLState(), e.getCause(),
            e.getMessage());
}

PYTHON语言


# conn is a psycopg2 connection

codeOne = 1001
codeTwo = 7369
codeThree = 3256

with conn.cursor() as cur:
    cur.execute("delete from emp where  empno in (%s, %s, %s)", (codeOne, codeTwo, codeThree)),

性能注意事项

由于hubble在后台工作的方式,从数据库中删除数据不会立即减少磁盘使用量。相反,记录被标记为'已删除'并由后台垃圾收集进程异步处理。默认情况下,此过程每25小时运行一次。 以便有足够的时间使用AS OF SYSTEM TIME, 垃圾收集间隔由gc.ttlseconds设置控制。

上述的实际意义是:

  • 删除数据不会立即减少磁盘使用量。
  • 如果DELETE按顺序发出多条语句,每条语句都删除大量数据,那么后续的每条DELETE语句都会运行得更慢。

为了保持迭代DELETE查询的性能,我们建议采用以下方法之一:

  • 在每次迭代中,更新WHERE子句以仅过滤尚未标记为删除的行。例如,请参阅索引过滤器上的批量删除。
  • 在每次迭代中,首先使用SELECT语句返回尚未删除的行的主键值。标记为删除的行将不会被返回。然后,在较小的批量大小上使用嵌套DELETE循环,过滤主键值。有关示例,请参阅对非索引列进行批量删除。
  • 要在恒定时间内迭代删除行,使用一个简单的DELETE循环,您可以更改区域配置并将其更改gc.ttlseconds为5分钟即值为300,然后在DELETE每个GC间隔运行一次语句。

磁盘的释放为表级别的,通过以下命令,对需要经常大批量删除的表进行设置。比如:

alter table test_a CONFIGURE ZONE using gc.ttlseconds = 1800;

通过监控页面,会发现半个小时候后,仪表盘的存储情况,存储空间得以释放,且删除的数据量越大释放情况会很明显。