华为云用户手册

  • 代码样例 下面代码片段在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,此种方法建表可以提高写入大量数据初期的数据写入速度。 表名以及列族名不能包含特殊字符,可以由字母、数字以及下划线组成。
  • 代码样例 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)”。
  • 代码样例 以下代码片段是创建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);}
  • 功能介绍 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负载,并损耗业务读写性能。
  • 代码样例 取消冷热时间线。 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]”。
  • 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)。
  • 代码样例 不指定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.");}
  • 代码样例 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); }}
  • JSON格式数据导入导出 JSON格式数据导入。 非安全集群 cat ./jsonnossl.json | ./clickhouse client --host 192.168.x.x --port port --user admin --password password --database test010 --query="INSERT INTO test141 FORMAT JSON" 安全集群 cat ./jsonssl.json | ./clickhouse client --host 192.168.x.x --port port --user admin --password password --config-file ./config.xml --database test010 --query="INSERT INTO test142 FORMAT JSON" cat文件路径:导入文件路径,路径自定义。 host:主机名/ClickHouse实例IP地址。 port:端口号(在集群详情页面查看)。 user:创建集群时创建的用户名。 database:数据库名。 password:创建集群时,创建的密码。 INSERT INTO:后面跟数据表。 config-file ./config.xml:指定配置文件,请参见ClickHouse安全通道章节。
  • parquet格式数据导入导出 parquet格式数据导入。 非安全集群 cat parquet_no_ssl.parquet | ./clickhouse client --host 192.168.x.x --port port --user admin --password password --database test010 --query="INSERT INTO test145 FORMAT Parquet" 安全集群 cat parquet_no_ssl.parquet | ./clickhouse client --host 192.168.x.x --port port --user admin --password password --config-file ./config.xml --database test010 --query="INSERT INTO test146 FORMAT Parquet" parquet_no_ssl.parquet:表示格式文件存放路径,路径自定义。 host:主机名/ClickHouse实例IP地址。 port:端口号(在集群详情页面查看)。 user:创建集群时创建的用户名。 database:数据库名。 password:创建集群时,创建的密码。 INSERT INTO:后面跟数据表。 config-file ./config.xml:指定配置文件,请参见ClickHouse安全通道章节。
  • 导入的原子性保证 Doris的每一个导入任务,不论是使用Broker Load进行批量导入,还是使用INSERT语句进行单条导入,都是一个完整的事务操作。导入事务可以保证一批次内的数据原子生效,不会出现部分数据写入的情况。 同时,每个导入任务都会有一个Label。这个Label在数据库(Database)中是唯一的,用于唯一标识一个导入任务。Label可以由用户指定,部分导入功能也会由系统自动生成。 Label是用于保证对应的导入任务,仅能成功导入一次。一个被成功导入的Label,再次使用时,会被拒绝并报错Label already used。通过这个机制,可以在Doris侧做到At-Most-Once语义。如果结合上游系统的At-Least-Once语义,则可以实现导入数据的Exactly-Once语义。
  • 开发思路 ClickHouse作为一款独立的DBMS系统,使用SQL语言就可以进行常见的操作。开发程序示例中,全部通过clickhouse-jdbc API接口来进行描述。 设置属性:设置连接ClickHouse服务实例的参数属性。 建立连接:建立和ClickHouse服务实例的连接。 创建库:创建ClickHouse数据库。 创建表:创建ClickHouse数据库下的表。 插入数据:插入数据到ClickHouse表中。 查询数据:查询ClickHouse表数据。 删除表:删除已创建的ClickHouse表。 父主题: 开发程序
  • 同步和异步 Doris目前的导入方式分为两类,同步和异步。如果是外部程序接入Doris的导入功能,需要判断使用导入方式是哪类再确定接入逻辑。 同步 同步导入方式即用户创建导入任务,Doris同步执行导入,执行完成后返回用户导入结果。用户可直接根据创建导入任务命令返回的结果同步判断导入是否成功。 异步 异步导入方式即用户创建导入任务后,Doris直接返回创建成功。创建成功不代表数据已经导入。导入任务会被异步执行,用户在创建成功后,需要通过轮询的方式发送命令查看导入作业的状态。如果创建失败,则可以根据失败信息,判断是否需要再次创建。 无论是异步还是同步的导入类型,都不应该在Doris返回导入失败或导入创建失败后,无休止的重试。外部系统在有限次数重试并失败后,保留失败信息,大部分多次重试均失败问题都是使用方法问题或数据本身问题。
  • 样例代码 ClickHouseDataSource clickHouseDataSource =new ClickHouseDataSource(JDBC_PREFIX + serverList.get(tries - 1), clickHouseProperties);connection = clickHouseDataSource.getConnection(user, password); 认证用的密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全。
  • 数据分片 Doris表按两层结构进行数据划分,分别是分区和分桶。 每个分桶文件就是一个数据分片(Tablet),Tablet是数据划分的最小逻辑单元。每个Tablet包含若干数据行。各个Tablet之间的数据没有交集,并且在物理上是独立存储的。 一个Tablet只属于一个Partition,相应的多个Tablet在逻辑上归属于不同的分区(Partition)。而一个Partition包含若干个Tablet。因为Tablet在物理上是独立存储的,所以可以视为Partition在物理上也是独立。Tablet是数据移动、复制等操作的最小物理存储单元。
  • 代码样例 不指定HOT_ONLY参数来查询数据。在这种情况下,将会查询冷存储中的数据。 public void testGet() { LOG.info("Entering testGet."); // Specify the column family name. byte[] familyName = Bytes.toBytes("info"); // Specify the column name. byte[][] qualifier = { Bytes.toBytes("temp"), Bytes.toBytes("hum") }; // Specify RowKey. byte[] rowKey = Bytes.toBytes("Shenzhen#Longgang#2017/7/1 03:00:00"); Table table = null; try { // Create the Table instance. table = conn.getTable(tableName); // Instantiate a Get object. Get get = new Get(rowKey); // Set the column family name and column name. get.addColumn(familyName, qualifier[0]); get.addColumn(familyName, qualifier[1]); // Submit a get request. Result result = table.get(get); // Print query results. for (Cell cell : result.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("Get data successfully."); } catch (IOException e) { LOG.error("Get data 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 testGet.");} 通过指定HOT_ONLY参数来查询数据。在这种情况下,只会查询热存储中的数据。 public void testGet() { LOG.info("Entering testGet."); // Specify the column family name. byte[] familyName = Bytes.toBytes("info"); // Specify the column name. byte[][] qualifier = { Bytes.toBytes("temp"), Bytes.toBytes("hum") }; // Specify RowKey. byte[] rowKey = Bytes.toBytes("Shenzhen#Longgang#2017/7/2 10:00:00"); Table table = null; try { // Create the Table instance. table = conn.getTable(tableName); // Instantiate a Get object. Get get = new Get(rowKey); // Set HOT_ONLY. get.setAttribute(HBaseConstants.HOT_ONLY, Bytes.toBytes(true)); // Set the column family name and column name. get.addColumn(familyName, qualifier[0]); get.addColumn(familyName, qualifier[1]); // Submit a get request. Result result = table.get(get); // Print query results. for (Cell cell : result.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("Get data successfully."); } catch (IOException e) { LOG.error("Get data 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 testGet.");}
  • 场景说明 假定用户开发一个网站系统,test_tbl用于实时用户访问网站的记录,记录数据如下表: 表1 原始数据 timestamp type error_code error_msg op_id op_time 2024-06-04 10:36:00 1 404 Resource Not Found 998756 2024-06-04 11:36:00 2024-06-04 10:35:00 1 404 Resource Not Found 998756 2024-06-04 11:35:00 2024-06-03 10:33:00 1 404 Resource Not Found 998756 2024-06-03 11:33:00 2024-03-27 09:10:00 1 200 ok 998756 2024-03-27 10:10:00 2024-03-25 11:08:00 1 404 Resource Not Found 998756 2024-03-25 12:08:00
  • 样例代码 public void testCountOnlyQuery() { LOG.info("Entering testCountOnlyQuery."); try (Table table = conn.getTable(tableName)) { // Using Table instance to create LemonTable. LemonTable lemonTable = new LemonTable(table); // Build LemonQuery. LemonQuery query = LemonQuery.builder() // Set ad-hoc query condition. .setQuery("education:bachelor OR education:master") // just return how many entities meet the query condition, without any rowkey/column .setCountOnly() .build(); ResultSet resultSet = lemonTable.query(query); // Read result rows. int count = resultSet.getCount(); LOG.info("the entity count of query is " + count); } catch (IOException e) { LOG.error("testCountOnlyQuery failed ", e); } LOG.info("Exiting testCountOnlyQuery."); }
  • 注意事项 (1) BitmapIndexDescriptor描述哪些字段使用什么规则来抽取标签,数据表可以定义一个或多个BitmapIndexDescriptor。 (2) 定义哪些列需要抽取标签。取值范围: ExplicitColumnName:指定列。 FamilyOnlyName:某一ColumnFamily下的所有列。 PrefixColumnName:拥有某一前缀的列。 (3) 定义列的抽取标签的规则,可选值如下: QualifierExtractor:表示按照列名来抽取标签。 例如,qualifier是Male,value是1,那么抽取的标签是Male。 QualifierValueExtractor:表示按照列名和value来抽取标签。 例如,qualifier是education,value是master,那么抽取的标签是education:master。 QualifierArrayValueExtractor:可以抽取多个标签,value是json array格式。 例如,qualifier是hobby,value 是 ["basketball","football","volleyball"],抽取的标签如下: hobby:basketballhobby:footballhobby:volleyball QualifierMapValueExtractor:可以抽取多个标签,value是json map格式。 例如,qualifier是hobby,value是 {"basketball":"9","football":"8","volleyball":"7"},抽取的标签如下: hobby:basketballhobby:footballhobby:volleyballhobby:basketball_9hobby:football_8hobby:volleyball_7 (4) 索引表的分区数量SHARD_NUM必须要小于或等于数据表。
  • 场景说明 假定用户开发一个应用程序,用于管理企业中的使用A业务的用户信息,如表1所示,A业务操作流程如下: 创建用户信息表。 在用户信息中新增用户的学历、职称等信息。 根据用户编号查询用户姓名和地址。 根据用户姓名进行查询。 查询年龄段在[20–29]之间的用户信息。 数据统计,统计用户信息表的人员数、年龄最大值、年龄最小值、平均年龄。 用户销户,删除用户信息表中该用户的数据。 A业务结束后,删除用户信息表。 表1 用户信息 编号 姓名 性别 年龄 地址 12005000201 A Male 19 Shenzhen, Guangdong 12005000202 B Female 23 Shijiazhuang, Hebei 12005000203 C Male 26 Ningbo, Zhejiang 12005000204 D Male 18 Xiangyang, Hubei 12005000205 E Female 21 Shangrao, Jiangxi 12005000206 F Male 32 Zhuzhou, Hunan 12005000207 G Female 29 Nanyang, Henan 12005000208 H Female 30 Kaixian, Chongqing 12005000209 I Male 26 Weinan, Shaanxi 12005000210 J Male 25 Dalian, Liaoning
  • 开发环境简介 在进行二次开发时,要准备的开发环境如表1所示。 表1 开发环境 准备项 说明 操作系统 Windows系统,推荐Windows 7及以上版本。 安装JDK 开发环境的基本配置。版本要求:1.7或者1.8。考虑到后续版本的兼容性,强烈推荐使用1.8。 说明: 基于安全考虑,CloudTable服务只支持TLS 1.1和TLS 1.2加密协议,IBM JDK默认TLS只支持1.0,如果使用IBM JDK,请配置启动参数“com.ibm.jsse2.overrideDefaultTLS”为“true”,设置后可以同时支持TLS1.0/1.1/1.2。详情请参见IBM官方网站的相关说明。 安装和配置Eclipse 用于开发CloudTable应用程序的工具。 网络 确保开发环境或客户端与 表格存储服务 主机在网络上互通。 父主题: 准备开发环境
  • 代码样例 public void dropTable() { LOG.info("Entering dropTable."); Admin admin = null; try { admin = conn.getAdmin(); if (admin.tableExists(tableName)) { // Disable the table before deleting it. admin.disableTable(tableName); // Delete table. admin.deleteTable(tableName);//注[1] } LOG.info("Drop table successfully."); } catch (IOException e) { LOG.error("Drop 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 dropTable.");}
  • 注意事项 (1) 查询条件,遵循Lucene语法/BNF范式,例如: "Male ANDMarried AND AGE:25-30 AND BLOOD_TYPE:A""Male ANDMarried AND (AGE:25-30 OR AGE:30-35)AND BLOOD_TYPE:A" (2) 查询返回多少行数据。 (3) 每行数据返回哪些qualifier,如果只设置列族,则表示返回列族下的所有列。
  • 代码样例 public void testGet() { LOG.info("Entering testGet."); // Specify the column family name. byte[] familyName = Bytes.toBytes("info"); // Specify the column name. byte[][] qualifier = { Bytes.toBytes("name"), Bytes.toBytes("address") }; // Specify RowKey. byte[] rowKey = Bytes.toBytes("012005000201"); Table table = null; try { // Create the Table instance. table = conn.getTable(tableName); // Instantiate a Get object. Get get = new Get(rowKey); // Set the column family name and column name. get.addColumn(familyName, qualifier[0]); get.addColumn(familyName, qualifier[1]); // Submit a get request. Result result = table.get(get); // Print query results. for (Cell cell : result.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("Get data successfully."); } catch (IOException e) { LOG.error("Get data 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 testGet.");}
  • 入门指引 表1 服务快速入门指引 服务 入门指引 整体流程类 使用CodeArts快速搭建基于E CS 部署的代码开发流水线 使用CodeArts快速搭建基于CCE部署的代码开发流水线 需求管理 创建Scrum项目并新建工作项 创建IPD系统设备类项目并新建工作项 软件建模 软件建模快速入门 代码托管 完成一次Scrum项目下的JAVA代码开发 管理员配置CodeArts Repo代码仓库的策略设置 流水线 通过流水线生成软件包并部署到主机 代码检查 快速检查CodeArts Repo代码仓库中的代码质量 编译构建 使用编译构建服务Ant构建并上传软件包至软件发布库 使用编译构建服务的Cmake构建并上传软件包至软件发布库 使用编译构建服务的Maven构建上传软件包和推送镜像 制品仓库 上传软件包到CodeArts Artifact软件发布库 上传私有组件到CodeArts Artifact中的Maven私有依赖库 部署 通过部署服务创建Tomcat应用并部署到ECS 测试计划 快速执行一次测试计划(CodeArts TestPlan)并查看测试报告 性能测试 性能测试快速入门 漏洞管理服务 如何使用漏洞管理服务 CodeArts IDE Online CodeArts IDE Online入门流程 5分钟创建并启动IDE实例 CodeArts IDE CodeArts IDE快速入门 Codearts 盘古助手 使用CodeArts 盘古助手生成代码及对应单元测试 开源镜像站 快速上手开源镜像站 开源治理服务 快速创建一个二进制成分分析任务 联接 使用空模板快速开始 使用组合应用模板快速开始
共100000条
提示

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