All Products
Search
Document Center

E-MapReduce:Phoenix

Last Updated:Dec 02, 2025

Apache Phoenix is a SQL layer built on HBase that enables you to use standard SQL to query and manage data.

Prerequisites

A DataServing or custom cluster is created, and the Phoenix and HBase services are selected when you create the cluster. For more information, see Create a cluster.

Use Phoenix from the command line

  1. Log on to your cluster in SSH mode. For more information, see Log on to a cluster.

  2. Run the following command to open the Phoenix CLI:

    /opt/apps/PHOENIX/phoenix-current/bin/sqlline.py
  3. Execute SQL statements to manage data. Common operations:

    • Create a table.

      CREATE TABLE IF NOT EXISTS example(
          my_pk bigint not null,
          m.first_name varchar(50),
          m.last_name varchar(50) 
          CONSTRAINT pk PRIMARY KEY (my_pk)
      );
    • Insert data into the table.

      UPSERT INTO example(my_pk,m.first_name,m.last_name) VALUES(100,'Jack','Ben');
      UPSERT INTO example(my_pk,m.first_name,m.last_name) VALUES(200,'Jack3','Ben3');
    • Query data from the table.

      SELECT * FROM example;

      The following output is returned:

      +--------+-------------+------------+
      | MY_PK  | FIRST_NAME  | LAST_NAME  |
      +--------+-------------+------------+
      | 100    | Jack        | Ben        |
      | 200    | Jack3       | Ben3       |
      +--------+-------------+------------+
    • Drop the table.

      DROP TABLE IF EXISTS example;

Connect to Phoenix using JDBC

Configure the Maven dependency

<dependency>
     <groupId>org.apache.phoenix</groupId>
     <artifactId>phoenix-core</artifactId>
     <version>${phoenix.version}</version>
</dependency>

The ${phoenix.version} variable must match the Phoenix version in your cluster.

Sample code

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class TestPhoenixJdbc {

    public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rset = null;

        Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
        Connection con = DriverManager.getConnection("jdbc:phoenix:[zookeeper quorum hosts]");
        stmt = con.createStatement();

        stmt.executeUpdate("create table test (mykey integer not null primary key, mycolumn varchar)");
        stmt.executeUpdate("upsert into test values (1,'Hello')");
        stmt.executeUpdate("upsert into test values (2,'World!')");
        con.commit();

        PreparedStatement statement = con.prepareStatement("select * from test");
        rset = statement.executeQuery();
        while (rset.next()) {
            System.out.println(rset.getString("mycolumn"));
        }
        statement.close();
        con.close();
    }
}

Connect to a Kerberos-enabled Phoenix cluster using JDBC

If your cluster uses Kerberos authentication, this section describes how to write a Java Database Connectivity (JDBC) client program to securely connect to the Phoenix service on a Kerberos-enabled EMR cluster. The client program authenticates using a JDBC URL that contains the principal and keytab information. The program then runs basic Data Definition Language (DDL) and Data Manipulation Language (DML) operations to verify the connection.

Step 1: Prepare the environment and credentials

Before you write and run the code, you must prepare the environment and create Kerberos credentials. Perform all the following operations on the master node of the cluster.

  1. Connect to the master node of the cluster using SSH. For more information, see Log on to a cluster.

  2. Determine the Kerberos realm.

    Each Kerberos-enabled cluster has a unique realm.

    Run the following command to retrieve the realm information. Find and record the realm for later use.

    cat /etc/krb5.conf | grep default_realm

    The following information is returned.

    default_realm = EMR.C-4FC5FDDE3759****.COM
  3. Create a client principal.

    A principal is the unique identity of a client in the Kerberos system. You must create a principal for the Java application.

    1. On the master node, run the following command to use the kadmin.local tool.

      sudo kadmin.local
    2. In the kadmin.local interactive interface, run the following command to create the principal.

      addprinc phoenix_client@EMR.C-4FC5FDDE3759****.COM

      After you run the command, you are prompted to set a password for the principal. Remember this password. Although the keytab file allows for a password-free logon, the password might still be required in some cases.

  4. Export the keytab file.

    1. In the kadmin.local tool, run the following command to export the keytab file.

      xst -k /tmp/phoenix_client.keytab phoenix_client@EMR.C-4FC5FDDE3759****.COM
    2. Run the following command to exit kadmin.local.

      exit
      Important
      • Permissions: Ensure that the user who runs the Java program has read permissions on the keytab file.

      • Distribution: If your Java program does not run on the master node, you must securely distribute the phoenix_client.keytab file and the /etc/krb5.conf file to the machine where the code runs. Place the files in a path that the script can access.

Step 2: Write and package the Java application

  • Method 1: Use a precompiled JAR file (for quick verification)

    hbase-phoenix-kerberos-1.0-SNAPSHOT.jar

  • Method 2: Manually compile and package the application (recommended for production)

    You can refer to the following code sample to manually compile and package the application.

    Core code sample (PhoenixKerberosDemo.java)

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    /**
     * A client that connects to a Kerberos-secured Phoenix cluster using JDBC.
     * All connection parameters are provided through a complete JDBC URL passed from the command line.
     */
    public class PhoenixKerberosDemo {
    
        /**
         * The main entry point for the application.
         *
         * @param args The command-line arguments. The program expects one argument: the full Phoenix JDBC URL.
         */
        public static void main(String[] args) {
            // --- 1. Validate command-line input: Expect one argument, the JDBC URL ---
            if (args.length != 1) {
                System.err.println("ERROR: Invalid number of arguments.");
                System.err.println("Usage: java PhoenixKerberosDemo \"<full_jdbc_url>\"");
                System.err.println("Example: \"jdbc:phoenix:zk1,zk2:2181:/hbase:user@REALM.COM:/path/to/user.keytab\"");
                System.exit(1); // Exit with an error code
            }
    
            String jdbcUrl = args[0];
    
            System.out.println("Attempting to connect to Phoenix...");
            System.out.println("Using JDBC URL: " + jdbcUrl);
    
            try {
                // --- 2. Load the Phoenix driver ---
                Class.forName("org.apache.phoenix.jdbc.PhoenixDriver");
            } catch (ClassNotFoundException e) {
                System.err.println("FATAL ERROR: Phoenix JDBC driver not found in the classpath.");
                e.printStackTrace();
                System.exit(1);
            }
    
            // --- 3. Use a try-with-resources statement to establish a connection and execute SQL. This syntax automatically closes resources. ---
            try (Connection con = DriverManager.getConnection(jdbcUrl);
                 Statement stmt = con.createStatement()) {
    
                System.out.println("Connection established successfully.");
    
                final String tableName = "TEST";
                System.out.println("Creating table '" + tableName + "'...");
                stmt.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " (mykey INTEGER NOT NULL PRIMARY KEY, mycolumn VARCHAR)");
                con.commit();
    
                System.out.println("Upserting data...");
                stmt.executeUpdate("UPSERT INTO " + tableName + " VALUES (1, 'Hello')");
                stmt.executeUpdate("UPSERT INTO " + tableName + " VALUES (2, 'World-Kerberos!')");
                con.commit();
                System.out.println("Data upserted successfully.");
    
                String sql = "SELECT * FROM " + tableName;
                System.out.println("Querying for results with: " + sql);
    
                try (PreparedStatement statement = con.prepareStatement(sql);
                     ResultSet rset = statement.executeQuery()) {
    
                    System.out.println("Query results:");
                    while (rset.next()) {
                        System.out.println(rset.getInt("mykey") + " -> " + rset.getString("mycolumn"));
                    }
                }
    
                System.out.println("Cleaning up the test table...");
                stmt.executeUpdate("DROP TABLE IF EXISTS " + tableName);
                con.commit();
    
            } catch (SQLException e) {
                // Catch SQL exceptions and provide helpful troubleshooting tips
                System.err.println("\n--- FAILED TO EXECUTE DATABASE OPERATION ---");
                System.err.println("Please check the following:");
                System.err.println("1. The JDBC URL is correct (format, principal, keytab path).");
                System.err.println("2. Network connectivity to ZooKeeper and HBase.");
                System.err.println("3. The keytab file exists and has correct read permissions.");
                System.err.println("4. The principal has sufficient permissions on HBase tables and namespaces.");
                e.printStackTrace();
            }
    
            System.out.println("\nExecution finished.");
        }
    }
    

    Maven configuration (pom.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                                 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.aliyun.emr.doctor</groupId>
        <artifactId>hbase-phoenix-kerberos</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>Archetype - hbase-phoenix-kerberos</name>
        <url>http://maven.apache.org</url>
        <properties>
            <phoenix.version>5.2.1</phoenix.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.apache.phoenix</groupId>
                <artifactId>phoenix-core</artifactId>
                <version>${phoenix.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!--  Java Compiler  -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.4</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                            <configuration>
                                <filters>
                                    <filter>
                                        <artifact>*:*</artifact>
                                        <excludes>
                                            <exclude>META-INF/*.SF</exclude>
                                            <exclude>META-INF/*.DSA</exclude>
                                            <exclude>META-INF/*.RSA</exclude>
                                        </excludes>
                                    </filter>
                                </filters>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>

Step 3: Run the application

  1. Select a runtime environment.

    When you run the application, you can choose one of the following two runtime environments:

    • Run on a cluster node (Recommended)

      • Cluster nodes have all the necessary Hadoop, HBase, and Phoenix dependency libraries pre-installed. No extra configuration is required. The network connectivity is pre-configured, which makes the environment complete and stable.

      • Scenarios: This method is suitable for quick verification, testing, development, and debugging.

    • Run outside the cluster

      To run the program outside the cluster, ensure that the following conditions are met:

      • Network connectivity: Ensure that the machine where the program runs can connect to the ZooKeeper, HBase Master, and RegionServer nodes of the cluster.

      • Kerberos configuration: Copy the cluster's krb5.conf file and the generated keytab file to the machine where the program runs.

      • Dependency management: The classpath for the run command must include all required Hadoop, HBase, and Phoenix client dependency JAR packages. This process is often more complex than running on a cluster node. You can use a tool such as Maven or Gradle to manage dependencies.

  2. Run the script.

    The following kerberos-phoenix.sh script integrates all necessary configurations for easy modification and execution.

    #!/bin/bash
    
    # ======================= 1. User Configuration (Modify based on your environment) =======================
    
    # Directory where Hadoop and HBase configuration files are located
    HADOOP_CONF_DIR="/etc/taihao-apps/hadoop-conf"
    HBASE_CONF_DIR="/etc/taihao-apps/hbase-conf"
    
    # Path to the Phoenix client JAR file. Using a symbolic link is a best practice to handle version changes.
    # First, use 'ls -l /opt/apps/PHOENIX/phoenix-current/' to confirm this file exists. This path may need to be modified for different versions.
    PHOENIX_JAR="/opt/apps/PHOENIX/phoenix-current/phoenix-client-lite-hbase-2.6.jar"
    
    # Your application's JAR file name.
    YOUR_JAR_FILE="hbase-phoenix-kerberos-1.0-SNAPSHOT.jar"
    
    # Path to the Kerberos configuration file.
    KRB5_CONF_PATH="/etc/krb5.conf"
    
    # --- [Core] JDBC URL Configuration ---
    # Format: jdbc:phoenix:[ZK Address]:[ZK Port]:[HBase ZNode]:[Principal]:[Absolute Keytab Path]
    # Replace the ZK address, REALM, and Keytab path below with your actual information.
    ZK_QUORUM="master-1-1" # If there are multiple ZooKeeper nodes, separate them with commas, such as "zk1,zk2,zk3"
    ZK_PORT="2181"
    HBASE_ZNODE="/hbase" # For a secure cluster, it might be /hbase-secure
    PRINCIPAL="phoenix_client@EMR.C-4FC5FDDE3759****.COM" # Replace with your Principal
    KEYTAB_PATH="/tmp/phoenix_client.keytab" # Absolute path to the Keytab file
    
    JDBC_URL="jdbc:phoenix:${ZK_QUORUM}:${ZK_PORT}:${HBASE_ZNODE}:${PRINCIPAL}:${KEYTAB_PATH}"
    # =================================================================================
    
    # ======================= 2. Execution Area (Usually no modification needed) =================================
    echo "================================================="
    echo "Starting Phoenix Kerberos JDBC Demo..."
    echo "Using JDBC URL: ${JDBC_URL}"
    echo "================================================="
    
    # Build the Classpath. Order: current directory -> config directory -> your JAR -> dependency JARs
    # `hbase classpath` automatically loads core Hadoop/HBase dependencies
    CLASS_PATH=".:${HADOOP_CONF_DIR}:${HBASE_CONF_DIR}:${YOUR_JAR_FILE}:${PHOENIX_JAR}:$(hbase classpath)"
    
    # Execute the Java program
    java -cp "${CLASS_PATH}" \
         -Djava.security.krb5.conf="${KRB5_CONF_PATH}" \
         PhoenixKerberosDemo "${JDBC_URL}"
    
    # Check the exit code
    if [ $? -eq 0 ]; then
        echo -e "\n[SUCCESS] Program finished successfully."
    else
        echo -e "\n[FAILED] Program terminated with an error."
    fi
    # =================================================================================
    1. Upload the JAR package created in Step 2 and the kerberos-phoenix.sh script to a specified directory on the master node.

    2. Run the following command to grant execute permissions to the script.

      chmod +x kerberos-phoenix.sh
    3. Run the following command to run the script.

      ./kerberos-phoenix.sh

      The following example shows a part of the returned information.

      image

References

For more information about Phoenix, see the following topics in the official documentation: