华为云用户手册

  • JDBC Connector 如果使用mysql jdbc connector来连接Doris,可以使用jdbc的自动重试机制: private static String URL = "jdbc:mysql:loadbalance://" + "cloudtable-2e68-ya-frontend-2-1-M07K7np5.mycloudtable.com:9030,cloudtable-2e68-ya-frontend-1-1-y5R8YNiy.mycloudtable.com:9030,cloudtable-2e68-ya-frontend-3-1-fGg7P4tA.mycloudtable.com:9030/demo?" + "loadBalanceConnectionGroup=first&ha.enableJMX=true"; 样例代码: public class Test { private static String URL = "jdbc:mysql:loadbalance://" + "FE1:9030,FE2:9030,FE3:9030/demo?" + "loadBalanceConnectionGroup=first&ha.enableJMX=true"; static Connection getNewConnection() throws SQLException, ClassNotFoundException { Class.forName("com.mysql.cj.jdbc.Driver"); // 认证用的密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; // 本示例以密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量 String password = System.getenv("USER_PASSWORD"); return DriverManager.getConnection(URL, "admin", password); } public static void main(String[] args) throws Exception { Connection c = getNewConnection(); while (true) { try { String query = "your sqlString"; c.setAutoCommit(false); Statement s = c.createStatement(); ResultSet resultSet = s.executeQuery(query); System.out.println("begin print"); while(resultSet.next()) { int id = resultSet.getInt(1); System.out.println("id is: "+id); } System.out.println("end print"); Thread.sleep(Math.round(100 * Math.random())); } catch (Exception e) { e.printStackTrace(); } } }}
  • 注意事项 注[1]只有在调用disableTable接口后, 再调用deleteTable接口才能将表删除成功。 因此,deleteTable常与disableTable,enableTable,tableExists,isTableEnabled,isTableDisabled结合在一起使用。 注[1]指的是代码样例中的“admin.deleteTable(tableName);//注[1]”。
  • 分桶 根据分桶列的Hash值将数据划分成不同的Bucket。 如果使用了Partition,则DISTRIBUTED ... 语句描述的是数据在各个分区内的划分规则。如果不使用Partition,则描述的是对整个表的数据的划分规则。 分桶列可以是多列,Aggregate和Unique模型必须为Key列,Duplicate模型可以是Key列和Value列。分桶列可以和Partition列相同或不同。 分桶列的选择,是在查询吞吐和查询并发之间的一种权衡: 如果选择多个分桶列,则数据分布更均匀。如果一个查询条件不包含所有分桶列的等值条件,那么该查询会触发所有分桶同时扫描,这样查询的吞吐会增加,单个查询的延迟随之降低。这个方式适合大吞吐低并发的查询场景。 如果仅选择一个或少数分桶列,则对应的点查询可以仅触发一个分桶扫描。此时,当多个点查询并发时,这些查询有较大的概率分别触发不同的分桶扫描,各个查询之间的IO影响较小(尤其当不同桶分布在不同磁盘上时),所以这种方式适合高并发的点查询场景。 AutoBucket: 根据数据量,计算分桶数。 对于分区表,可以根据历史分区的数据量、机器数、盘数,确定一个分桶。 分桶的数量理论上没有上限。 父主题: 数据分区和分桶
  • 准备开发环境 在进行应用开发时,要准备的开发和运行环境如表1所示。 表1 开发环境 准备项 说明 操作系统 开发环境:Windows系统,支持Windows7以上版本。 运行环境:Linux系统。 如需在本地调测程序,运行环境需要和集群业务平面网络互通。 安装JDK 安装JDK,版本为1.8.0_272。 安装和配置IntelliJ IDEA 开发环境的基本配置,建议使用2019.1或其他兼容版本。 说明: 如果使用IBM JDK,请确保IntelliJ IDEA中的JDK配置为IBM JDK。 如果使用Oracle JDK,请确保IntelliJ IDEA中的JDK配置为Oracle JDK。 如果使用Open JDK,请确保IntelliJ IDEA中的JDK配置为Open JDK。 不同的IntelliJ IDEA不要使用相同的workspace和相同路径下的示例工程。 安装Maven 开发环境的基本配置。用于项目管理,贯穿软件开发生命周期。 准备开发用户 准备用于应用开发的ClickHouse集群用户并授予相应权限。 7-zip 用于解压“*.zip”和“*.rar”文件,支持7-Zip 16.04版本。
  • 代码样例 public void testPut() { LOG .info("Entering testPut."); // Specify the column family name. byte[] familyName = Bytes.toBytes("info"); // Specify the column name. byte[][] qualifiers = { Bytes.toBytes("temp"), Bytes.toBytes("hum") }; Table table = null; try { // Instantiate an HTable object. table = conn.getTable(tableName); // Instantiate a Put object. Every Hour insert one data. Put put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 00:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 01:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("53.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 02:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("52.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 03:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); puts.add(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 04:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 05:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 06:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 07:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 08:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 09:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 10:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 11:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 12:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 13:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("33.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 14:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("33.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 15:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 16:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("31.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 17:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 18:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 19:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 20:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("52.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 21:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("53.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 22:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/1 23:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 00:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 01:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("53.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 02:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("52.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 03:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); puts.add(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 04:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 05:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 06:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 07:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("27.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 08:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 09:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("46.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 10:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 11:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("48.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 12:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 13:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("33.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("49.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 14:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("33.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 15:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("32.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("50.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 16:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("31.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 17:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 18:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("30.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); puts.clear(); puts.add(put); table.put(puts); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 19:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("51.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 20:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("52.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 21:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("29.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("53.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 22:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); put = new Put(Bytes.toBytes("Shenzhen#Longgang#2017/7/2 23:00:00")); put.addColumn(familyName, qualifiers[0], Bytes.toBytes("28.0")); put.addColumn(familyName, qualifiers[1], Bytes.toBytes("54.0")); table.put(put); LOG.info("Put successfully."); } catch (IOException e) { LOG.error("Put failed " ,e); } finally { if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testPut.");}
  • 代码样例 下面代码片段在com.huawei.cloudtable.lemonIndex.examples.LemonIndexTestMain包中。 private static void init() throws IOException { // Default load from conf directory conf = HBaseConfiguration.create(); // 注[1] String userdir = System.getProperty("user.dir") + File.separator + "conf" + File.separator; Path hbaseSite = new Path(userdir + "hbase-site.xml"); if (new File(hbaseSite.toString()).exists()) { conf.addResource(hbaseSite); }}
  • 操作步骤 确认CloudTable集群已经安装,并正常运行。 准备Windows弹性云服务器。 具体操作请参见准备弹性云服务器章节。 请在Windows的弹性云服务器上安装JDK1.7及以上版本,强烈推荐使用JDK1.8及以上版本,并且安装Eclipse,Eclipse使用JDK1.7及以上的版本。 如果使用IBM JDK,请确保Eclipse中的JDK配置为IBM JDK。 如果使用Oracle JDK,请确保Eclipse中的JDK配置为Oracle JDK。 不同的Eclipse不要使用相同的workspace和相同路径下的示例工程。
  • 代码样例 public void testScanData() { LOG.info("Entering testScanData."); Table table = null; // Instantiate a ResultScanner object. ResultScanner rScanner = null; try { // Create the Configuration instance. table = conn.getTable(tableName); // Instantiate a Get object. Scan scan = new Scan(); scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name")); // Set the cache size. scan.setCaching(1000); // Submit a scan request. rScanner = table.getScanner(scan); // Print query results. for (Result r = rScanner.next(); r != null; r = rScanner.next()) { for (Cell cell : r.rawCells()) { LOG.info(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + "," + Bytes.toString(CellUtil.cloneQualifier(cell)) + "," + Bytes.toString(CellUtil.cloneValue(cell))); } } LOG.info("Scan data successfully."); } catch (IOException e) { LOG.error("Scan data failed " ,e); } finally { if (rScanner != null) { // Close the scanner object. rScanner.close(); } if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testScanData.");}
  • 代码样例 public void testDelete() { LOG.info("Entering testDelete."); byte[] rowKey = Bytes.toBytes("012005000201"); Table table = null; try { // Instantiate an HTable object. table = conn.getTable(tableName); // Instantiate a Delete object. Delete delete = new Delete(rowKey); // Submit a delete request. table.delete(delete); LOG.info("Delete table successfully."); } catch (IOException e) { LOG.error("Delete table failed " ,e); } finally { if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testDelete.");}
  • 应用背景 CloudTable作为大数据存储服务,提供高效的kv随机查询能力。在此基础上,CloudTable服务引入自研的分布式多维标签索引能力,存储格式与计算基于位图进行。用户可以根据自身业务需求来定义HBase表中的哪些字段需要构建标签索引,用户写入数据时将自动生成标签数据。同时,标签索引基于Lucene的语法,提供高效的多维标签查询接口。可应用于用户画像、推荐系统、人工智能、时空数据等场景。 CloudTable服务支持标签索引能力,您只需要创建CloudTable集群,就可以在弹性云服务器(E CS )上开发客户端应用进行多维标签查询。 父主题: 开发标签索引应用
  • 功能分解 根据上述的业务场景进行功能分解,需要开发的功能点如表1所示。 表1 在HBase中开发的功能 序号 步骤 代码实现 1 根据典型场景说明中的信息创建表。 请参见创建表。 2 导入用户数据。 请参见插入数据。 3 增加“教育信息”列族,在用户信息中新增用户的学历、职称等信息。 请参见修改表。 4 根据用户编号查询用户姓名和地址。 请参见使用Get读取数据。 5 根据用户姓名进行查询。 请参见使用过滤器Filter。 6 用户销户,删除用户信息表中该用户的数据。 请参见删除数据。 7 A业务结束后,删除用户信息表。 请参见删除表。
  • 功能简介 HBase通过org.apache.hadoop.hbase.client.Admin对象的createTable方法来创建表,并指定表名、列族名。创建表有两种方式(强烈建议采用预分Region建表方式): 快速建表,即创建表后整张表只有一个Region,随着数据量的增加会自动分裂成多个Region。 预分Region建表,即创建表时预先分配多个Region,此种方法建表可以提高写入大量数据初期的数据写入速度。 表名以及列族名不能包含特殊字符,可以由字母、数字以及下划线组成。
  • 代码样例 public void testCreateTable() { LOG.info("Entering testCreateTable."); // Specify the table descriptor. HTableDescriptor htd = new HTableDescriptor(tableName); // (1) // Set the column family name to info. HColumnDescriptor hcd = new HColumnDescriptor("info"); // (2) // Set data encoding methods. HBase provides DIFF,FAST_DIFF,PREFIX // and PREFIX_TREE hcd.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF); // 注[1] // Set compression methods, HBase provides two default compression // methods:GZ and SNAPPY // GZ has the highest compression rate,but low compression and // decompression efficiency,fit for cold data // SNAPPY has low compression rate, but high compression and // decompression efficiency,fit for hot data. // it is advised to use SANPPY hcd.setCompressionType(Compression.Algorithm.SNAPPY); htd.addFamily(hcd); // (3) Admin admin = null; try { // Instantiate an Admin object. admin = conn.getAdmin(); // (4) if (!admin.tableExists(tableName)) { LOG.info("Creating table..."); admin.createTable(htd); // 注[2] (5) LOG.info(admin.getClusterStatus()); LOG.info(admin.listNamespaceDescriptors()); LOG.info("Table created successfully."); } else { LOG.warn("table already exists"); } } catch (IOException e) { LOG.error("Create table failed.", e); } finally { if (admin != null) { try { // Close the Admin object. admin.close(); } catch (IOException e) { LOG.error("Failed to close admin ", e); } } } LOG.info("Exiting testCreateTable.");}
  • 注意事项 注[1] 可以设置列族的压缩方式,代码片段如下: //设置编码算法,HBase提供了DIFF,FAST_DIFF,PREFIX和PREFIX_TREE四种编码算法 hcd.setDataBlockEncoding(DataBlockEncoding.FAST_DIFF); //设置文件压缩方式,HBase默认提供了GZ和SNAPPY两种压缩算法 //其中GZ的压缩率高,但压缩和解压性能低,适用于冷数据 //SNAPPY压缩率低,但压缩解压性能高,适用于热数据 //建议默认开启SNAPPY压缩 hcd.setCompressionType(Compression.Algorithm.SNAPPY); 注[2] 可以通过指定起始和结束RowKey,或者通过RowKey数组预分Region两种方式建表,代码片段如下: // 创建一个预划分region的表 byte[][] splits = new byte[4][]; splits[0] = Bytes.toBytes("A"); splits[1] = Bytes.toBytes("H"); splits[2] = Bytes.toBytes("O"); splits[3] = Bytes.toBytes("U"); admin.createTable(htd, splits);
  • 代码样例 public void testModifyTable() { LOG.info("Entering testModifyTable."); // Specify the column family name. byte[] familyName = Bytes.toBytes("education"); Admin admin = null; try { // Instantiate an Admin object. admin = conn.getAdmin(); // Obtain the table descriptor. HTableDescriptor htd = admin.getTableDescriptor(tableName); // Check whether the column family is specified before modification. if (!htd.hasFamily(familyName)) { // Create the column descriptor. HColumnDescriptor hcd = new HColumnDescriptor(familyName); htd.addFamily(hcd); // Disable the table to get the table offline before modifying // the table. admin.disableTable(tableName); // Submit a modifyTable request. admin.modifyTable(tableName, htd); //注[1] // Enable the table to get the table online after modifying the // table. admin.enableTable(tableName); } LOG.info("Modify table successfully."); } catch (IOException e) { LOG.error("Modify table failed " ,e); } finally { if (admin != null) { try { // Close the Admin object. admin.close(); } catch (IOException e) { LOG.error("Close admin failed " ,e); } } } LOG.info("Exiting testModifyTable.");}
  • 数据表 在Doris中,数据以表的形式进行逻辑上的描述。表是具有相同模式的同质数据的集合。 一张表包括行(Row)和列(Column)。Row即用户的一行数据。Column用于描述一行数据中不同的字段,可以根据实际情况采用不同的数据类型(如整型、字符串、布尔型等)。 从OLAP场景看,Column可以分为两大类:Key和Value。Key表示维度列,Value表示指标列。 父主题: Doris数据表和数据模型
  • 代码样例 public void testSingleColumnValueFilter() { LOG.info("Entering testSingleColumnValueFilter."); Table table = null; ResultScanner rScanner = null; try { table = conn.getTable(tableName); Scan scan = new Scan(); scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name")); // Set the filter criteria. SingleColumnValueFilter filter = new SingleColumnValueFilter( Bytes.toBytes("info"), Bytes.toBytes("name"), CompareOp.EQUAL, Bytes.toBytes("I")); scan.setFilter(filter); // Submit a scan request. rScanner = table.getScanner(scan); // Print query results. for (Result r = rScanner.next(); r != null; r = rScanner.next()) { for (Cell cell : r.rawCells()) { LOG.info(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + "," + Bytes.toString(CellUtil.cloneQualifier(cell)) + "," + Bytes.toString(CellUtil.cloneValue(cell))); } } LOG.info("Single column value filter successfully."); } catch (IOException e) { LOG.error("Single column value filter failed " ,e); } finally { if (rScanner != null) { // Close the scanner object. rScanner.close(); } if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testSingleColumnValueFilter.");}
  • 代码样例 下面代码片段在com.huaweicloudtable.hbase.examples包中。 private static void init() throws IOException { // Default load from conf directory conf = HBaseConfiguration.create(); // 注[1] String userdir = System.getProperty("user.dir") + File.separator + "conf" + File.separator; Path hbaseSite = new Path(userdir + "hbase-site.xml"); if (new File(hbaseSite.toString()).exists()) { conf.addResource(hbaseSite); }}
  • JDBC通过ssl方式连接doris(无需验证证书) 在应用层进行代码重试和负载均衡时,代码重试需要应用自己多个配置doris前端节点地址。比如发现一个连接异常退出,就自动在其他连接上进行重试。 前提条件:集群必须开启HTTPS。 下载证书请在集群详情页面下载。 样例代码: public class Main { private static String URL = "jdbc:mysql:loadbalance://" + "[FE1_host]:[FE1_port],[FE2_host]:[FE2_port],[FE3_host]:[FE3_port]/[your_database]?" + "loadBalanceConnectionGroup=first&ha.enableJMX=true"; static Connection getNewConnection() throws SQLException, ClassNotFoundException { Class.forName("com.mysql.cj.jdbc.Driver"); // 认证用的密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全; // 本示例以密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量 String password = System.getenv("USER_PASSWORD"); String user = "your_username"; Properties props = new Properties(); props.setProperty("user", user); props.setProperty("password", password); props.setProperty("useSSL", "true"); props.setProperty("requireSSL", "true"); return DriverManager.getConnection(URL, props); } public static void main(String[] args) throws Exception { Connection c = getNewConnection(); try { System.out.println("begin print"); String query = "your sqlString"; c.setAutoCommit(false); Statement s = c.createStatement(); ResultSet resultSet = s.executeQuery(query); while(resultSet.next()) { int id = resultSet.getInt(1); System.out.println("id is: "+id); } System.out.println("end print"); Thread.sleep(Math.round(100 * Math.random())); c.close(); } catch (Exception e) { e.printStackTrace(); } }} 父主题: 通过JDBC方式连接Doris
  • 功能介绍 HBase通过org.apache.hadoop.hbase.client.Admin对象的createTable方法来创建表,并指定表名、列族名、冷热时间线。 创建表有两种方式(强烈建议采用预分Region建表方式): 快速建表,即创建表后整张表只有一个Region,随着数据量的增加会自动分裂成多个Region。 预分Region建表,即创建表时预先分配多个Region,此种方法建表可以提高写入大量数据初期的数据写入速度。 表名以及列族名不能包含特殊字符,可以由字母、数字以及下划线组成。
  • 功能介绍 HBase通过ConnectionFactory.createConnection(configuration)方法创建Connection对象。传递的参数为上一步创建的Configuration。 Connection封装了底层与各实际服务器的连接以及与ZooKeeper的连接。Connection通过ConnectionFactory类实例化。创建Connection是重量级操作,而且Connection是线程安全的,因此,多个客户端线程可以共享一个Connection。 典型的用法,一个客户端程序共享一个单独的Connection,每一个线程获取自己的Admin或Table实例,然后调用Admin对象或Table对象提供的操作接口。不建议缓存或者池化Table、Admin。Connection的生命周期由调用者维护,调用者通过调用close(),释放资源。 建议业务代码连接同一个CloudTable集群时,多线程创建并复用同一个Connection,不必每个线程都创建各自Connection。Connection是连接CloudTable集群的连接器,创建过多连接会加重Zookeeper负载,并损耗业务读写性能。
  • 代码样例 以下代码片段是创建Connection对象的示例: private TableName tableName = null;private Connection conn = null;public HBaseSample(Configuration conf) throws IOException { this.tableName = TableName.valueOf("hbase_sample_table"); this.conn = ConnectionFactory.createConnection(conf);}
  • 代码样例 public void testCreateTable() { LOG.info("Entering testCreateTable."); // Specify the table descriptor. HTableDescriptor htd = new HTableDescriptor(tableName); // (1) // Set the column family name to info. HColumnDescriptor hcd = new HColumnDescriptor("info"); // (2) // Set hot and cold data boundary hcd.setValue(HColumnDescriptor.COLD_BOUNDARY, "86400"); htd.addFamily(hcd); // (3) Admin admin = null; try { // Instantiate an Admin object. admin = conn.getAdmin(); // (4) if (!admin.tableExists(tableName)) { LOG.info("Creating table..."); admin.createTable(htd); // 注[1] (5) LOG.info(admin.getClusterStatus()); LOG.info(admin.listNamespaceDescriptors()); LOG.info("Table created successfully."); } else { LOG.warn("table already exists"); } } catch (IOException e) { LOG.error("Create table failed.", e); } finally { if (admin != null) { try { // Close the Admin object. admin.close(); } catch (IOException e) { LOG.error("Failed to close admin ", e); } } } LOG.info("Exiting testCreateTable.");} 代码编号解释 (1)创建表描述符。 (2)创建列族描述符。 (3)添加列族描述符到表描述符中。 (4)获取Admin对象,Admin提供了建表、创建列族、检查表是否存在、修改表结构和列族结构以及删除表等功能。 (5)调用Admin的建表方法。 注意事项 注[1] 表和列族其它属性设置可以参考开发HBase应用。 注[1] 指的是代码样例中的“admin.createTable(htd); // 注[1] (5)”。
  • 代码样例 取消冷热时间线。 public void testModifyTable() { LOG.info("Entering testModifyTable."); // Specify the column family name. byte[] familyName = Bytes.toBytes("info"); Admin admin = null; try { // Instantiate an Admin object. admin = conn.getAdmin(); // Obtain the table descriptor. HTableDescriptor htd = admin.getTableDescriptor(tableName); // Check whether the column family is specified before modification. if (!htd.hasFamily(familyName)) { // Create the column descriptor. HColumnDescriptor hcd = new HColumnDescriptor(familyName); //Disable hot and cold separation. hcd .setValue(HColumnDescriptor.COLD_BOUNDARY, null); htd.addFamily(hcd); // Disable the table to get the table offline before modifying // the table. admin.disableTable(tableName); // Submit a modifyTable request. admin.modifyTable(tableName, htd); //注[1] // Enable the table to get the table online after modifying the // table. admin.enableTable(tableName); } LOG.info("Modify table successfully."); } catch (IOException e) { LOG.error("Modify table failed " ,e); } finally { if (admin != null) { try { // Close the Admin object. admin.close(); } catch (IOException e) { LOG.error("Close admin failed " ,e); } } } LOG.info("Exiting testModifyTable.");} 注意事项。 注[1] 只有在调用disableTable接口后, 再调用modifyTable接口才能将表修改成功。之后,请调用enableTable接口重新启用表。 注[1] 指的是代码样例中的“admin.modifyTable(tableName, htd); //注[1]”。
  • 代码样例 不指定HOT_ONLY参数来查询数据。在这种情况下,将会查询冷存储中的数据。 public void testScanData() { LOG.info("Entering testScanData."); Table table = null; // Instantiate a ResultScanner object. ResultScanner rScanner = null; try { // Create the Configuration instance. table = conn.getTable(tableName); // Instantiate a Get object. Scan scan = new Scan(); byte[] startRow = Bytes.toBytes(Shenzhen#Longgang#2017/7/1 00:00:00); byte[] stopRow = Bytes.toBytes(Shenzhen#Longgang#2017/7/3 00:00:00); scan.setStartRow(startRow); scan.setStopRow(stopRow); scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("temp")); // Set the cache size. scan.setCaching(1000); // Submit a scan request. rScanner = table.getScanner(scan); // Print query results. for (Result r = rScanner.next(); r != null; r = rScanner.next()) { for (Cell cell : r.rawCells()) { LOG.info(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + "," + Bytes.toString(CellUtil.cloneQualifier(cell)) + "," + Bytes.toString(CellUtil.cloneValue(cell))); } } LOG.info("Scan data successfully."); } catch (IOException e) { LOG.error("Scan data failed " ,e); } finally { if (rScanner != null) { // Close the scanner object. rScanner.close(); } if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testScanData.");} 通过指定HOT_ONLY参数来查询数据。在这种情况下,只会查询热存储中的数据。 public void testScanData() { LOG.info("Entering testScanData."); Table table = null; // Instantiate a ResultScanner object. ResultScanner rScanner = null; try { // Create the Configuration instance. table = conn.getTable(tableName); // Instantiate a Get object. Scan scan = new Scan(); byte[] startRow = Bytes.toBytes(Shenzhen#Longgang#2017/7/1 00:00:00); byte[] stopRow = Bytes.toBytes(Shenzhen#Longgang#2017/7/3 00:00:00); scan.setStartRow(startRow); scan.setStopRow(stopRow); scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("temp")); // Set HOT_ONLY. scan.setAttribute(HBaseConstants.HOT_ONLY, Bytes.toBytes(true)); // Set the cache size. scan.setCaching(1000); // Submit a scan request. rScanner = table.getScanner(scan); // Print query results. for (Result r = rScanner.next(); r != null; r = rScanner.next()) { for (Cell cell : r.rawCells()) { LOG.info(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + "," + Bytes.toString(CellUtil.cloneQualifier(cell)) + "," + Bytes.toString(CellUtil.cloneValue(cell))); } } LOG.info("Scan data successfully."); } catch (IOException e) { LOG.error("Scan data failed " ,e); } finally { if (rScanner != null) { // Close the scanner object. rScanner.close(); } if (table != null) { try { // Close the HTable object. table.close(); } catch (IOException e) { LOG.error("Close table failed " ,e); } } } LOG.info("Exiting testScanData.");}
  • Failed to create partition [xxx] . Timeout Doris建表是按照Partition粒度依次创建的。当一个Partition创建失败时,可能会报这个错误。即使不使用Partition,当建表出现问题时,也会报Failed to create partition,因为如前文所述,Doris会为没有指定Partition的表创建一个不可更改的默认的Partition。 当遇到这个错误时,通常是BE在创建数据分片时遇到了问题。可以参照以下步骤排查: 在fe.log中,查找对应时间点的Failed to create partition日志。在该日志中,会出现一系列类似{10001-10010}字样的数字对。数字对的第一个数字表示Backend ID,第二个数字表示Tablet ID。如上这个数字对,表示ID为10001的Backend上,创建ID为10010的Tablet失败了。 前往对应Backend的be.INFO日志,查找对应时间段内,tablet id相关的日志,可以找到错误信息。 以下罗列一些常见的tablet创建失败错误,包括但不限于: BE没有收到相关task,此时无法在be.INFO中找到tablet id相关日志或者BE创建成功,但汇报失败。 预分配内存失败。可能是表中一行的字节长度超过了 100KB。 Too many open files。打开的文件句柄数超过了Linux系统限制。需修改Linux系统的句柄数限制。 如果创建数据分片时超时,也可以通过在fe.conf中设置tablet_create_timeout_second=xxx以及max_create_table_timeout_second=xxx来延长超时时间。其中tablet_create_timeout_second默认是1秒, max_create_table_timeout_second默认是60秒,总体的超时时间为min(tablet_create_timeout_second * replication_num, max_create_table_timeout_second)。
  • 代码样例 Properties clickHouseProperties = new Properties();clickHouseProperties.setProperty(ClickHouseClientOption.CONNECTION_TIMEOUT.getKey(), Integer.toString(60000));clickHouseProperties.setProperty(ClickHouseClientOption.SSL.getKey(), Boolean.toString(false));clickHouseProperties.setProperty(ClickHouseClientOption.SSL_MODE.getKey(), "none");
  • 样例代码 private void createDatabase(String databaseName, String clusterName) throws Exception { String createDbSql = "create database if not exists " + databaseName + " on cluster " + clusterName; util.exeSql(createDbSql);}
  • Python代码样例 # -*- coding: utf-8 -*-# 引入公共模块import sysimport os# 引入Thrift自带模块,如果不存在则需要执行pip install thrift安装from thrift.transport import TTransportfrom thrift.protocol import TBinaryProtocolfrom thrift.transport import THttpClientfrom thrift.transport import TSocket# 引入通过hbase.thrift生成的模块gen_py_path = os.path.abspath('gen-py')sys.path.append(gen_py_path)from hbase import THBaseServicefrom hbase.ttypes import TColumnValue, TColumn, TTableName, TTableDescriptor, TColumnFamilyDescriptor, TGet, TPut, TScan# 配置CloudTable HBase集群的ThriftServer的IP,可以通过集群的详情页面获取host = "x.x.x.x"socket = TSocket.TSocket(host, 9090)transport = TTransport.TBufferedTransport(socket)protocol = TBinaryProtocol.TBinaryProtocol(transport)client = THBaseService.Client(protocol)transport.open()# 测试表名tableNameInBytes = "test".encode("utf8")tableName = TTableName(ns="default".encode("utf8"), qualifier=tableNameInBytes)# 预分region的split keysplitKeys=[]splitKeys.append("row3".encode("utf8"))splitKeys.append("row5".encode("utf8"))# 建表操作client.createTable(TTableDescriptor(tableName=tableName, columns=[TColumnFamilyDescriptor(name="cf1".encode("utf8"))]), splitKeys)print("Create table %s success." % tableName)# Put单条数据put = TPut(row="row1".encode("utf8"), columnValues=[TColumnValue(family="cf1".encode("utf8"), qualifier="q1".encode("utf8"), value="test_value1".encode("utf8"))])client.put(tableNameInBytes, put)print("Put single row success.")# Put多条数据puts = []puts.append(TPut(row="row4".encode("utf8"), columnValues=[TColumnValue(family="cf1".encode("utf8"), qualifier="q1".encode("utf8"), value="test_value1".encode("utf8"))]))puts.append(TPut(row="row6".encode("utf8"), columnValues=[TColumnValue(family="cf1".encode("utf8"), qualifier="q1".encode("utf8"), value="test_value1".encode("utf8"))]))puts.append(TPut(row="row8".encode("utf8"), columnValues=[TColumnValue(family="cf1".encode("utf8"), qualifier="q1".encode("utf8"), value="test_value1".encode("utf8"))]))client.putMultiple(tableNameInBytes, puts)print("Put rows success.")# Get单条数据get = TGet(row="row1".encode("utf8"))result = client.get(tableNameInBytes, get)print("Get Result: ", result)# Get多条数据gets = []gets.append(TGet(row="row4".encode("utf8")))gets.append(TGet(row="row8".encode("utf8")))results = client.getMultiple(tableNameInBytes, gets)print("Get multiple rows: ", results)# Scan数据startRow, stopRow = "row4".encode("utf8"), "row9".encode("utf8")scan = TScan(startRow=startRow, stopRow=stopRow)caching=1results = []while True:scannerResult = client.getScannerResults(tableNameInBytes, scan, caching)lastOne = Nonefor result in scannerResult:results.append(result)print("Scan Result: ", result)lastOne = result# 没有更多数据,退出if lastOne is None:breakelse:# 重新生成下一次scan的startRownewStartRow = bytearray(lastOne.row)newStartRow.append(0x00)scan = TScan(startRow=newStartRow, stopRow=stopRow)# 禁用和删除表client.disableTable(tableName)print("Disable table %s success." % tableName)client.deleteTable(tableName)print("Delete table %s success." % tableName)# 所有操作都结束后,关闭连接transport.close()
  • 代码样例 下面代码片段在com.huawei.cloudtable.hbase.examples.coldhotexample包中。 private static void init() throws IOException { // Default load from conf directory conf = HBaseConfiguration.create(); // 注[1] String userdir = System.getProperty("user.dir") + File.separator + "conf" + File.separator; Path hbaseSite = new Path(userdir + "hbase-site.xml"); if (new File(hbaseSite.toString()).exists()) { conf.addResource(hbaseSite); }}
共100000条
提示

您即将访问非华为云网站,请注意账号财产安全