全部產品
Search
文件中心

MaxCompute:使用說明

更新時間:Jun 19, 2024

本文為您介紹如何下載JDBC和串連MaxCompute,並提供範例程式碼。

注意事項

  • 通過MaxCompute JDBC驅動執行SQL並擷取結果,需要執行帳號滿足以下要求:

    • 是專案空間的成員。

    • 有專案空間的CreateInstance許可權。

    • 有目標表的Select和Download許可權。

      說明
      • 1.9及之前版本的MaxCompute JDBC驅動對每個查詢都會建立暫存資料表,並通過Tunnel從暫存資料表擷取結果。您使用這些版本的JDBC需要具備CreateTable許可權。

      • 2.2及之後版本的MaxCompute JDBC驅動不再建立暫存資料表,直接通過Instance Tunnel擷取查詢結果,沒有CreateTable許可權要求限制。

      MaxCompute許可權詳情請參見MaxCompute許可權

  • MaxCompute提供了資料保護功能。當資料保護模式開啟時,您無法將資料轉移到專案空間之外。2.4之前版本的JDBC無法擷取result set。2.4及之後版本的JDBC可以獲得不超過READ_TABLE_MAX_ROW所定義行數的資料,詳情請參見專案空間操作。資料保護功能詳情請參見資料保護機制

  • MaxCompute 2.0資料類型版本支援較多資料類型,例如TINYINT、SMALLINT、DATETIME、TIMESTAMP、ARRAY、MAP和STRUCT等。您如果需要使用這些新類型,在執行SQL之前需要執行以下語句,開啟MaxCompute 2.0資料類型開關。詳情請參見資料類型版本說明

    set odps.sql.type.system.odps2=true

JDBC下載

您可以通過OSSGitHubMaven庫擷取MaxCompute各版本的JAR包。推薦您下載包含完整依賴jar-with-dependencies的JAR包。

通過Maven方式使用MaxCompute JDBC的專案物件模型POM(Project Object Model)的樣本如下。

<dependency>
  <groupId>com.aliyun.odps</groupId>
  <artifactId>odps-jdbc</artifactId>
  <version>3.3.6</version>
  <classifier>jar-with-dependencies</classifier>
</dependency>
說明

MaxCompute JDBC驅動是開原始碼專案,專案地址為aliyun-odps-jdbc

MaxCompute歡迎您參與JDBC驅動的開發和改進工作。您可以在該專案的Issues頁面反饋問題,或通過Pull requests頁面對原始碼進行改進。使用IssuesPull requests時,請您遵循開源專案的模板要求。

JDBC參數說明

JDBC可以通過URL參數和Properties參數進行配置,其中Properties參數的優先順序高於URL參數。

說明

如果URL key中包含odps_config=config_file,則會讀取config_file作為Properties參數。

  • 基本參數。

    URL key

    Property Key

    是否必選

    描述

    project

    project_name

    MaxCompute專案名稱。

    accessId

    access_id

    阿里雲帳號的AccessKey ID。

    您可以進入AccessKey管理頁面擷取AccessKey ID。

    accessKey

    access_key

    阿里雲帳號的AccessKey Secret。

    您可以進入AccessKey管理頁面擷取AccessKey Secret。

    logview

    logview_host

    MaxCompute Logview地址。固定取值為:http://logview.odps.aliyun.com

    tunnelEndpoint

    tunnel_endpoint

    MaxCompute Tunnel服務的Endpoint。

    各地區及網路對應的Tunnel Endpoint值,請參見Endpoint

  • 日誌配置參數。

    URL key

    Property Key

    是否必選

    描述

    enableOdpsLogger

    enable_odps_logger

    是否啟用MaxCompute JDBC Logger。取值說明:

    • False(預設值):不啟用,JDBC將不記錄日誌到檔案中。

    • True:啟用,將會在JDBC的jar包所在目錄jdbc.log檔案中記錄日誌。

    logConfFile

    log_conf_file

    可以額外指定SLF4J設定檔,靈活配置日誌輸出(比如指定輸出檔案、輸出logLevel 等)。這種方式需要在專案的pom.xml檔案中添加依賴:

    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>

    配置樣本,請參見設定檔樣本

    logLevel

    log_level

    輸出的記錄層級,預設值為:INFO

  • 其他參數

    URL key

    Property Key

    是否必選

    描述

    stsToken

    sts_token

    阿里雲STS令牌。

    charset

    charset

    輸入和輸出的字元集,預設值為:UTF-8

    useProjectTimeZone

    use_project_time_zone

    是否使用project的odps.sql.timezoneProperty。取值說明:

    • False(預設值):不使用。

    • True:使用。

    說明

    Statement中也可以通過set odps.sql.timezone=xxx來指定,

    優先順序順序為Statement > project > null。

    disableConnectinosSetting

    disable_connection_setting

    是否允許設定一個 Connection的SQL參數。取值說明:

    • False(預設值):不允許。

    • True:允許。

    如果允許,在Statement中執行set xxx命令時,會同時設定對應Statement和Connection的SQL參數。否則,只會設定對應Statement的參數。

    settings

    settings

    全域預設sql setting,使用JSON格式傳入,例如{"key":"value"}

    tableList

    table_list

    MaxCompute中表名稱。格式為:projectname.tablename,projectname1.tablename1

    connectTimeout

    connect_timeout

    底層網路建立串連的逾時時間,預設為:10秒(s)。

    readTimeout

    read_timeout

    底層網路連接讀取資料的逾時時間,預設為:120秒(s)。

    說明
    • RESTful API每次請求的連線逾時時間為connectTimeoutreadTimeout之和,即預設是130秒(s),預設重試次數是3次。

    • 想要調整RESTful API連線逾時時間,修改readTimeout參數即可。

    enableCommandApi

    enable_command_api

    是否使用commandAPI。取值說明:

    • False(預設值):不使用。

    • True:使用。

      如果使用,則可以在JDBC中執行一些僅在odpscmd中執行的命令。

    httpsCheck

    https_check

    是否進行HTTPS認證驗證。取值說明:

    • False(預設值):不驗證。

    • True:驗證。

    tunnelConnectTimeout

    tunnel_connect_timeout

    使用tunnel下載資料時,tunnel的連線逾時時間,預設為:180秒(s)。

    tunnelReadTimeout

    tunnel_read_timeout

    使用tunnel下載資料時,tunnel的讀取資料逾時時間,預設為:300秒(s)。

  • Non-MCQA 相關參數(僅離線模式生效)

    URL key

    Property Key

    是否必選

    描述

    autoLimitFallback

    auto_limit_fallback

    自動限制回退。取值說明:

    • False(預設值):不回退。

    • True:回退,在離線模式下,tunnel報no download permission異常時自動回退,限制下載數為10000。

  • MCQA相關(僅MCQA生效)

    • 基本配置

    • URL key

      Property Key

      是否必選

      描述

      interactiveMode

      interactive_mode

      是否開啟MCQA。取值說明:

      • False(預設值):不開啟。

      • True:開啟。

      executeProject

      execute_project_name

      實際執行SQL任務的MaxCompute專案名稱。

      tunnelRetryTime

      tunnel_retry_time

      SQLExecutor設定tunnel重試次數,預設為6次。

      attachTimeout

      attach_timeout

      建立MCQA串連的逾時時間,預設為60秒(s)。

      fallbackQuota

      fallback_quota

      MCQA作業回退時選擇的Quota,不配置使用MaxCompute專案的預設Quota。

    • Limit相關參數

      URL key

      Property Key

      是否必選

      描述

      instanceTunnelMaxRecord

      instance_tunnel_max_record

      結果集的最大記錄數。

      說明

      只有當enableLimit參數設定為False時,該參數才會生效。

      instanceTunnelMaxSize

      instance_tunnel_max_size

      結果集的最大大小,單位:位元組(Byte)。

      autoSelectLimit

      auto_select_limit

      自動查詢限制。

      阿里公用雲端的彈性計算環境,預設查詢最多100萬行,若您需要查看更多資料時,可以配置此參數。

      說明
      • 只有當enableLimit參數設定為False時,該參數才會生效。

      • JDBC v3.2.29版本後,設定 autoSelectLimit參數後,enableLimit會自動化佈建為False

      • 您可以在SQL setting中,添加odps.sql.select.auto.limit,SQL作業執行時,該參數會預設生效。

      enableLimit

      enable_limit

      是否啟用限制。取值說明:

      • False:不啟用。

      • True(預設值):啟用。

        啟用後下載許可權將不被檢查,並且結果記錄數量預設最大限制為10000條。

    • Fallback相關參數

      URL key

      Property Key

      是否必選

      描述

      fallbackForUnknownError

      fallback_for_unknownerror

      發生未知錯誤時是否回退到離線模式。取值說明:

      • False:不回退。

      • True(預設值):回退。

      fallbackForResourceNotEnough

      fallback_for_resourcenotenough

      資源不足時是否回退到離線模式。取值說明:

      • False:不回退。

      • True(預設值):回退。

      fallbackForUpgrading

      fallback_for_upgrading

      升級期間是否回退到離線模式。取值說明:

      • False:不回退。

      • True(預設值):回退。

      fallbackForRunningTimeout

      fallback_for_runningtimeout

      執行操作命令逾時時是否回退到離線模式。取值說明:

      • False:不回退。

      • True(預設值):回退。

      fallbackForUnsupportedFeature

      fallbackForUnsupportedFeature

      遇到MCQA不支援的情境時是否回退到離線模式。取值說明:

      • False:不回退。

      • True(預設值):回退。

      alwaysFallback

      always_fallback

      在以上幾種情境下,是否全部回退到離線模式。取值說明:

      • False(預設值):不回退。

      • True:回退。

      說明

      該參數僅在JDBC v3.2.3及以上版本有效。

      disableFallback

      disable_fallback

      在以上幾種情境下,是否均不回退到離線模式。取值說明:

      • False(預設值):回退。

      • True:不回退。

      fallbackQuota

      fallback_quota

      MCQA作業回退時選擇的Quota名稱,不配置使用MaxCompute專案預設Quota。

串連MaxCompute

  1. 載入MaxCompute JDBC驅動。

    Class.forName("com.aliyun.odps.jdbc.OdpsDriver");
  2. 通過DriverManager建立Connection。

    Connection cnct = DriverManager.getConnection(url, accessId, accessKey);
    • url:格式為jdbc:odps:<maxcompute_endpoint>?project=<maxcompute_project_name>[&useProjectTimeZone={true|false}]。其中:

      • <maxcompute_endpoint>:MaxCompute服務所在地區的Endpoint。例如,華東1(杭州)地區的外網Endpoint為http://service.cn-hangzhou.maxcompute.aliyun.com/api。Endpoint的配置資訊詳情請參見Endpoint

      • <maxcompute_project_name>:MaxCompute專案空間名稱。

      • useProjectTimeZone:是否使用MaxCompute專案空間的時區。

      命令樣本如下。

      jdbc:odps:http://service.cn-hangzhou.maxcompute.aliyun.com/api?project=test_project&useProjectTimeZone=true;
    • accessId:建立專案空間的AccessKey ID。

    • accessKey:建立專案空間的AccessKey ID對應的AccessKey Secret。

      說明

      AccessKey ID和AccessKey Secret的建立和查看,請參見準備阿里雲帳號

  3. 執行查詢。

    Statement stmt = cnct.createStatement();
    ResultSet rset = stmt.executeQuery("SELECT foo FROM bar");
    
    while (rset.next()) {
        // process the results
    }
    
    rset.close();
    stmt.close();
    cnct.close();

範例程式碼

  • 刪除表、建立表和擷取Metadata

    說明

    如果專案中使用了JDBC依賴,則不需要指定SDK依賴,設定了JDBC依賴後,會自動引入SDK。否則程式可能會因為版本不統一導致運行報錯。

    import java.sql.Connection;
    import java.sql.DatabaseMetaData;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Main {
    
        private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
     		// 阿里雲帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM使用者進行API訪問或日常營運,請登入RAM控制台建立RAM使用者
    		// 此處以把AccessKey和AccessKeySecret儲存在環境變數為例說明。您也可以根據業務需要,儲存到設定檔裡
    		// 強烈建議不要把AccessKey和AccessKeySecret儲存到代碼裡,會存在密鑰泄漏風險
    		private static String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    		private static String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) throws SQLException {
            try {
                Class.forName(DRIVER_NAME);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.exit(1);
            }
    				
            Connection conn = DriverManager.getConnection(
                "jdbc:odps:<maxcompute_endpoint>?project=<maxcompute_project>",
                Main.accessId, Main.accessKey);
    
            // create a table
            Statement stmt = conn.createStatement();
            final String tableName = "jdbc_test";
            stmt.execute("DROP TABLE IF EXISTS " + tableName);
            stmt.execute("CREATE TABLE " + tableName + " (key BIGINT, value STRING)");
    
            // get meta data
            DatabaseMetaData metaData = conn.getMetaData();
            System.out.println("product = " + metaData.getDatabaseProductName());
            System.out.println("jdbc version = "
                + metaData.getDriverMajorVersion() + ", "
                + metaData.getDriverMinorVersion());
            ResultSet tables = metaData.getTables(null, null, tableName, null);
            while (tables.next()) {
                String name = tables.getString("TABLE_NAME");
                System.out.println("inspecting table: " + name);
                ResultSet columns = metaData.getColumns(null, null, name, null);
                while (columns.next()) {
                    System.out.println(
                        columns.getString("COLUMN_NAME") + "\t" +
                            columns.getString("TYPE_NAME") + "(" +
                            columns.getInt("DATA_TYPE") + ")");
                }
                columns.close();
            }
    
            tables.close();
            stmt.close();
            conn.close();
        }
    }

    返回結果樣本如下。

    product = MaxCompute/ODPS
    jdbc version = 3, 0
    inspecting table: jdbc_test
    key    BIGINT(-5)
    value    STRING(12)
  • 更新表

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Main {
    
        private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
    		// 阿里雲帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM使用者進行API訪問或日常營運,請登入RAM控制台建立RAM使用者
    		// 此處以把AccessKey和AccessKeySecret儲存在環境變數為例說明。您也可以根據業務需要,儲存到設定檔裡
    		// 強烈建議不要把AccessKey和AccessKeySecret儲存到代碼裡,會存在密鑰泄漏風險
      	private static String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
      	private static String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
      
        public static void main(String[] args) throws SQLException {
            try {
                Class.forName(DRIVER_NAME);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.exit(1);
            }
    				
            Connection conn = DriverManager.getConnection(
                "jdbc:odps:<maxcompute_endpoint>?project=<maxcompute_project>",
                Main.accessId, Main.accessKey);
    
            Statement stmt = conn.createStatement();
            // The following DML also works
            //String dml = "INSERT INTO jdbc_test SELECT 1, \"foo\"";
            String dml = "INSERT INTO jdbc_test VALUES(1, \"foo\")";
            int ret = stmt.executeUpdate(dml);
    
            assert ret == 1;
    
            stmt.close();
            conn.close();
        }
    }
  • 批次更新表

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    
    public class Main {
    
        private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
      	// 阿里雲帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM使用者進行API訪問或日常營運,請登入RAM控制台建立RAM使用者
    		// 此處以把AccessKey 和 AccessKeySecret 儲存在環境變數為例說明。您也可以根據業務需要,儲存到設定檔裡
    		// 強烈建議不要把 AccessKey 和 AccessKeySecret 儲存到代碼裡,會存在密鑰泄漏風險
    		private static String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    		private static String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
      
        public static void main(String[] args) throws SQLException {
            try {
                Class.forName(DRIVER_NAME);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.exit(1);
            }
    				
            Connection conn = DriverManager.getConnection(
                "jdbc:odps:<maxcompute endpoint>?project=<maxcompute project>",
                Main.accessId, Main.accessKey);
    
            PreparedStatement pstmt = conn.prepareStatement("INSERT INTO jdbc_test VALUES(?, ?)");
    
            pstmt.setLong(1, 1L);
            pstmt.setString(2, "foo");
            pstmt.addBatch();
    
            pstmt.setLong(1, 2L);
            pstmt.setString(2, "bar");
            pstmt.addBatch();
    
            int[] ret = pstmt.executeBatch();
    
            assert ret[0] == 1;
            assert ret[1] == 1;
    
            pstmt.close();
            conn.close();
        }
    }
    說明
    • executeBatch方法不適用於Cluster表的批量資料寫入,例如Transaction Table2.0表。

    • 若對普通分區表進行批量資料寫入,需要在INSERT INTO語句中指定分區。樣本如下:

      -- 分區表sale_detail的建表語句如下。
      create table if not exists sale_detail
      (
      shop_name string,
      customer_id string,
      total_price double
      )
      partitioned by (sale_date string, region string);
      
      -- 假設已有分區sale_date='20240219', region='hangzhou',則對分區表進行批量資料寫入時,INSERT INTO語句如下。
      INSERT INTO sale_detail PARTITION(sale_date='20240219', region='hangzhou') VALUES(?, ?, ?)
  • 查詢表

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public class Main {
    
        private static final String DRIVER_NAME = "com.aliyun.odps.jdbc.OdpsDriver";
      	// 阿里雲帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM使用者進行API訪問或日常營運,請登入RAM控制台建立RAM使用者
    		// 此處以把AccessKey 和 AccessKeySecret 儲存在環境變數為例說明。您也可以根據業務需要,儲存到設定檔裡
    		// 強烈建議不要把 AccessKey 和 AccessKeySecret 儲存到代碼裡,會存在密鑰泄漏風險
    		private static String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    		private static String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) throws SQLException {
            try {
                Class.forName(DRIVER_NAME);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                System.exit(1);
            }
    				
            Connection conn = DriverManager.getConnection(
                "jdbc:odps:<maxcompute endpoint>?project=<maxcompute project>",
                Main.accessId, Main.accessKey);
            ResultSet rs;
    
            Statement stmt = conn.createStatement();
            String sql = "SELECT * FROM JDBC_TEST";
            stmt.executeQuery(sql);
    
            ResultSet rset = stmt.getResultSet();
            while (rset.next()) {
                System.out.println(String.valueOf(rset.getInt(1)) + "\t" + rset.getString(2));
            }
        }
    }
    說明

    OdpsStatement支援execute(sql)executeQuery(sql)executeUpdate(sql) 三個方法。其中execute(sql)executeQuery(sql)方法支援desc tableshow tablesshow partitions三個常用命令。