Apache Phoenix 删除亿级数据心得

Phoenix最早是saleforce的一个开源项目,后来成为Apache基金的顶级项目。

Phoenix是构建在HBase上的一个SQL层,能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表,插入数据和对HBase数据进行查询。

Phoenix完全使用Java编写,作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫描,并编排执行以生成标准的JDBC结果集。直接使用HBase API、协同处理器与自定义过滤器,对于简单查询来说,其性能量级是毫秒,对于百万级别的行数来说,其性能量级是秒。


上面是Phoenix的整体介绍。由于项目中运用了phoenix,一直在增量的导入数据。导致Phoenix的空间不足。但是项目中只用到一个月以内的数据。所以,要进行冗余数据的删除的。

第一次实现:

DruidDataSource的数据源,导致报错MutationState size of 512000 isbigger than max allowed size of 500000 代码如下


 
    
    
    
    
    

    
    
    
    

    
    

    
    

    
    

    
    
    
    

    
    
    

    
    
 
 @Resource(name = "phoenixDataSource")
 private DruidDataSource phoenixDataSource;
	
 public Integer delete(String sql, Object... params) throws Exception {
            Connection conn = null;
            PreparedStatement statement = null;
            try {

                conn = phoenixDataSource.getConnection();
                conn.setAutoCommit(false);
                statement = conn.prepareStatement(sql);
                fillParameter(statement, params);
                Integer number = statement.executeUpdate();
                conn.commit();
                return number;
            } catch (Exception e) {
                throw new Exception("查询phoenix出错", e);
            } finally {
                if (statement != null) {
                    statement.close();
                }

                if (conn != null) {
                    conn.close();
                }
            }
    }



报错查询资料得知是由于内存中的Phoenix限制只能查询50W条的数据,于是想到修改配置文件。有了第二次尝试:使用DriverManager类修改配置文件属性,将默认的50W条数据,增加到1000W。

第二次实现:

 public Integer delete(String sql, Object... params) throws Exception {
            Connection conn = null;
            PreparedStatement statement = null;
            try {

                   Properties connectionProperties = new Properties();
                //默认的500000
                connectionProperties.setProperty(QueryServices.MAX_MUTATION_SIZE_ATTRIB,"10000000");
                // 默认的500000 改成1000000
                connectionProperties.setProperty(QueryServices.IMMUTABLE_ROWS_ATTRIB,"10000000");
                connectionProperties.setProperty("user",instanceNumber);
                connectionProperties.setProperty("password",accessKey);
				
		StringBuilder url = new StringBuilder("jdbc:phoenix:thin:url=http://").append(address).append(";serialization=PROTOBUF");
                conn = DriverManager.getConnection(url.toString(), connectionProperties);
				
                conn.setAutoCommit(false);
                statement = conn.prepareStatement(sql);
                fillParameter(statement, params);
                Integer number = statement.executeUpdate();
                conn.commit();
                return number;
            } catch (Exception e) {
                throw new Exception("查询phoenix出错", e);
            } finally {
                if (statement != null) {
                    statement.close();
                }

                if (conn != null) {
                    conn.close();
                }
            }
    }

删除结果还是报错:mutationstate size is bigger than maximum allowed number of bytes.

明明已经修改配置文件了,看来是配置文件没有起作用。于是继续找资料,进行验证。在阅读phoenix官方文档的时候,查看delete命令的时候,看到了关键的一句话

DELETE

DELETE
     
 
/ * + hint * /
 
FROM tableName
     
 
WHERE expression
 

 

     
 
ORDER BY order
     
  , ...  
 
     
 
LIMIT
  bindParameter  
  number  
 

删除where子句选择的行。如果启用了自动提交,则完全在服务器端执行删除

例:DELETE FROM TEST;
DELETE FROM TEST WHERE ID=123;
DELETE FROM TEST WHERE NAME LIKE 'foo%';

如果启用了自动提交,则完全在服务器端执行删除这句话很重要,在我们程序中设置把自动提交设置为false,也就是说我们是在客户端的内存进行删除的,而内存是有限的,所以就导致了报错。于是有了最终版本的删除实现。

正常实现:

public Integer delete(String sql, Object... params) throws Exception {
            Connection conn = null;
            PreparedStatement statement = null;
            try {

                Properties connectionProperties = new Properties();
     
                connectionProperties.setProperty(QueryServices.MAX_MUTATION_SIZE_ATTRIB,"10000000");
           
                connectionProperties.setProperty(QueryServices.IMMUTABLE_ROWS_ATTRIB,"10000000");
                connectionProperties.setProperty("user",instanceNumber);
                connectionProperties.setProperty("password",accessKey);


                StringBuilder url = new StringBuilder("jdbc:phoenix:thin:url=http://").append(address).append(";serialization=PROTOBUF");
                conn = DriverManager.getConnection(url.toString(), connectionProperties);
                conn.setAutoCommit(true);
                statement = conn.prepareStatement(sql);
                fillParameter(statement, params);
                Integer number = statement.executeUpdate();
                conn.commit();
                return number;
            } catch (Exception e) {
                throw new Exception("查询phoenix出错", e);
            } finally {
                if (statement != null) {
                    statement.close();
                }

                if (conn != null) {
                    conn.close();
                }
            }
    }
设置conn.setAutoCommit(true);让删除语句在服务端进行删除,就不会报:java.sql.SQLException: ERROR 730 (LIM02): MutationState size is bigger than maximum allowed number of bytes
和
MutationState size of 512000 is bigger than max allowed size of 500000。并且删除成功。在删除数据时,会返回前端超时,但是delete语句还在服务端执行。

删除数据量时效以及问题:

9000W数据删除用时 43分钟。删除实现成功,但是没有删除干净,在6000W条删除时,留下600多条数据未删除,9000W时留下1400多条数据。这是由于删除中有数据报错导致,对于这个问题,就是在执行一下删除。可以看到能正确返回删除的数据条数。

 

 

phoenix官网链接:http://phoenix.apache.org/

你可能感兴趣的:(开发,个人知识库)